unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
From: Tassilo Horn <tsdh@gnu.org>
To: Stefan Monnier <monnier@IRO.UMontreal.CA>
Cc: help-gnu-emacs@gnu.org
Subject: Re: Completion: display of candidates
Date: Tue, 19 Feb 2019 08:27:49 +0100	[thread overview]
Message-ID: <87lg2cgruy.fsf@gnu.org> (raw)
In-Reply-To: <jwv7edwesgm.fsf-monnier+emacs@gnu.org> (Stefan Monnier's message of "Mon, 18 Feb 2019 15:48:36 -0500")

Stefan Monnier <monnier@IRO.UMontreal.CA> writes:

>> Right, and here comes the next problem: concretely I get my
>> completions from `locate --basename <pattern>`.  So the user (me)
>> might enter a wildcard pattern like "foo*bar.*".  But the
>> completions/matches obviously have no * in it, so no completion
>> matches the candidates.
>
> That completely depends on the completion style.
>
> For example `partial-completion` (which is included in the default
> `completion-styles`) does accept * so you can do `M-x r*v*uf TAB` to
> find revert-buffer.

Hm, that there can be dependencies between (1) finding completion
candidates and (2) completion styles doesn't spark joy in my heart.  I
thought of (1) as a kind of generic backend and (2) as a frontend which
users select based on personal preference.  But since both have to work
with the user's input string, I don't see how to make it better...

>> How to handle that?  Use the PREDICATE argument in completing-read so
>
> The PREDICATE argument can only rule out matches, not add new ones.

Yeah, in the end I've waived my hands and went without text properties
and just selected a unicode character which is unlikely to be used in
file names as separator.  The results are quite satisfying.

--8<---------------cut here---------------start------------->8---
(defconst th/recentf-locate-excluded-paths
  (let ((home (getenv "HOME")))
    (list
     #'backup-file-name-p
     (expand-file-name ".cargo/" home)
     (expand-file-name ".cache/" home)
     (expand-file-name ".m2/" home)
     (expand-file-name ".IntelliJIdea[^/]+/" home))))

(defun th/recentf-locate-completions (str)
  (with-current-buffer (get-buffer-create " *th/locate-matches*")
    (erase-buffer)
    (mapc (lambda (rf) (insert rf "\n")) recentf-list)
    (let ((home-dir (getenv "HOME"))
	  lst line-move-visual)
      (when (> (length str) 2)
	(call-process "locate" nil t nil
		      "--basename"
		      "--existing"
		      "--ignore-case"
		      "--limit" "500"
		      str))
      (goto-char (point-min))
      (while (not (eobp))
	(let* ((path (buffer-substring (point) (line-end-position)))
	       (basename (file-name-nondirectory path))
	       (dir (file-name-directory path)))
	  (unless (seq-find (lambda (pred)
			      (cond
			       ((stringp pred)
				(string-match-p pred path))
			       ((functionp pred) (funcall pred path))
			       (t (error "Don't know how to handle %S" pred))))
			    th/recentf-locate-excluded-paths)
	    (push (format "%s ‼ %s" basename dir) lst)))
	(next-line))
      (sort lst (lambda (a b)
		  (or
		   ;; a is in HOME but b is not, so sort a before b
		   (and (string-match-p (concat " ‼ " home-dir) a)
			(not (string-match-p (concat " ‼ " home-dir) b)))
		   ;; otherwise sort by base name.
		   (string-lessp a b)))))))

(defun th/recentf-locate-file (locate-candidate)
  (interactive
   (list (completing-read
	  "Locate File: "
	  (completion-table-dynamic #'th/recentf-locate-completions)
	  nil t)))
  (let ((path (progn
		(string-match "^\\(.*\\) ‼ \\(.*\\)$" locate-candidate)
		(expand-file-name (match-string 1 locate-candidate)
				  (match-string 2 locate-candidate)))))
    (find-file path)))

(global-set-key (kbd "<f5>") #'th/recentf-locate-file)
--8<---------------cut here---------------end--------------->8---

Bye,
Tassilo



  reply	other threads:[~2019-02-19  7:27 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-18  7:54 Completion: display of candidates Tassilo Horn
2019-02-18 13:26 ` Stefan Monnier
2019-02-18 14:55   ` Tassilo Horn
2019-02-18 18:05     ` Stefan Monnier
2019-02-18 19:24       ` Tassilo Horn
2019-02-18 20:48         ` Stefan Monnier
2019-02-19  7:27           ` Tassilo Horn [this message]
2019-02-19 15:28             ` Stefan Monnier
     [not found]               ` <87imxe1pfs.fsf@gnu.org>
2019-02-20 16:54                 ` Stefan Monnier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87lg2cgruy.fsf@gnu.org \
    --to=tsdh@gnu.org \
    --cc=help-gnu-emacs@gnu.org \
    --cc=monnier@IRO.UMontreal.CA \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).