Add support for completion of quoted/escaped data.

This commit is contained in:
Stefan Monnier 2012-04-25 15:00:18 -04:00
commit dd2ac746d4
9 changed files with 591 additions and 436 deletions

View file

@ -169,6 +169,14 @@ still be supported for Emacs 24.x.
* Lisp changes in Emacs 24.2
** Completion
*** New function `completion-table-with-quoting' to handle completion
in the presence of quoting, such as file completion in shell buffers.
*** New function `completion-table-subvert' to use an existing completion
table, but with a different prefix.
* Changes in Emacs 24.2 on non-free operating systems

View file

@ -1,7 +1,44 @@
2012-04-25 Stefan Monnier <monnier@iro.umontreal.ca>
* ffap.el: Remove old code for obsolete package.
(ffap-complete-as-file-p): Remove.
Use completion-table-with-quoting for comint and pcomplete.
* comint.el (comint--unquote&requote-argument)
(comint--unquote-argument, comint--requote-argument): New functions.
(comint--unquote&expand-filename, comint-unquote-filename): Obsolete.
(comint-quote-filename): Use regexp-opt-charset.
(comint--common-suffix, comint--common-quoted-suffix)
(comint--table-subvert): Remove.
(comint-unquote-function, comint-requote-function): New vars.
(comint--complete-file-name-data): Use them with
completion-table-with-quoting.
* pcmpl-unix.el (pcomplete/scp): Use completion-table-subvert.
* pcomplete.el (pcomplete-arg-quote-list)
(pcomplete-quote-arg-hook, pcomplete-quote-argument): Obsolete.
(pcomplete-unquote-argument-function): Default to non-nil.
(pcomplete-unquote-argument): Simplify.
(pcomplete--common-quoted-suffix): Remove.
(pcomplete-requote-argument-function): New var.
(pcomplete--common-suffix): New function.
(pcomplete-completions-at-point): Use completion-table-with-quoting
and completion-table-subvert.
* minibuffer.el: Use completion-table-with-quoting for read-file-name.
(minibuffer--double-dollars): Preserve properties.
(completion--sifn-requote): New function.
(completion--file-name-table): Rewrite using it and c-t-with-quoting.
* minibuffer.el: Add support for completion of quoted/escaped data.
(completion-table-with-quoting, completion-table-subvert): New funs.
(completion--twq-try, completion--twq-all): New functions.
(completion--nth-completion): New function.
(completion-try-completion, completion-all-completions): Use it.
2012-04-25 Leo Liu <sdl.web@gmail.com>
* progmodes/python.el (python-pdbtrack-get-source-buffer): Use
compilation-message if available to find real filename.
* progmodes/python.el (python-pdbtrack-get-source-buffer):
Use compilation-message if available to find real filename.
2012-04-25 Chong Yidong <cyd@gnu.org>
@ -21,32 +58,31 @@
2012-04-25 Alex Harsanyi <AlexHarsanyi@gmail.com>
Sync with soap-client repository. Support SOAP simpleType. (Bug#10331)
Sync with soap-client repository. Support SOAP simpleType (Bug#10331).
* soap-client.el (soap-resolve-references-for-sequence-type)
(soap-resolve-references-for-array-type): hack to prevent self
(soap-resolve-references-for-array-type): Hack to prevent self
references, see Bug#9.
(soap-parse-envelope): report the contents of the 'detail' node
(soap-parse-envelope): Report the contents of the 'detail' node
when receiving a fault reply.
(soap-parse-envelope): report the contents of the entire 'detail'
node.
(soap-parse-envelope): Report the contents of the entire 'detail' node.
* soap-inspect.el (soap-sample-value-for-simple-type)
(soap-inspect-simple-type): new function
(soap-inspect-simple-type): New function.
* soap-client.el (soap-simple-type): new struct
* soap-client.el (soap-simple-type): New struct.
(soap-default-xsd-types, soap-default-soapenc-types)
(soap-decode-basic-type, soap-encode-basic-type): support
unsignedInt and double basic types
(soap-decode-basic-type, soap-encode-basic-type):
support unsignedInt and double basic types.
(soap-resolve-references-for-simple-type)
(soap-parse-simple-type, soap-encode-simple-type): new function
(soap-parse-schema): parse xsd:simpleType declarations
(soap-parse-simple-type, soap-encode-simple-type): New function.
(soap-parse-schema): Parse xsd:simpleType declarations.
* soap-client.el (soap-default-xsd-types)
(soap-default-soapenc-types): add integer, byte and anyURI types
(soap-parse-complex-type-complex-content): use `soap-wk2l' to find
the local name of "soapenc:Array"
(soap-decode-basic-type, soap-encode-basic-type): support encoding
(soap-default-soapenc-types): Add integer, byte and anyURI types.
(soap-parse-complex-type-complex-content): Use `soap-wk2l' to find
the local name of "soapenc:Array".
(soap-decode-basic-type, soap-encode-basic-type): Support encoding
decoding integer, byte and anyURI xsd types.
2012-04-25 Chong Yidong <cyd@gnu.org>
@ -166,8 +202,8 @@
* ispell.el (ispell-insert-word) Remove unneeded function using
obsolete `translation-table-for-input'.
(ispell-word, ispell-process-line, ispell-complete-word): Use
plain `insert' instead of removed `ispell-insert-word'.
(ispell-word, ispell-process-line, ispell-complete-word):
Use plain `insert' instead of removed `ispell-insert-word'.
2012-04-22 Chong Yidong <cyd@gnu.org>
@ -185,8 +221,8 @@
Move functions from C to Lisp. Make non-blocking method calls
the default. Implement further D-Bus standard interfaces.
* net/dbus.el (dbus-message-internal): Declare function. Remove
unneeded function declarations.
* net/dbus.el (dbus-message-internal): Declare function.
Remove unneeded function declarations.
(defvar dbus-message-type-invalid, dbus-message-type-method-call)
(dbus-message-type-method-return, dbus-message-type-error)
(dbus-message-type-signal): Declare variables. Remove local
@ -202,8 +238,8 @@
(dbus-register-signal, dbus-register-method): New defuns, moved
from dbusbind.c
(dbus-call-method-handler, dbus-setenv)
(dbus-get-all-managed-objects, dbus-managed-objects-handler): New
defuns.
(dbus-get-all-managed-objects, dbus-managed-objects-handler):
New defuns.
(dbus-call-method-non-blocking): Make it an obsolete function.
(dbus-unregister-object, dbus-unregister-service)
(dbus-handle-event, dbus-register-property)
@ -328,8 +364,8 @@
2012-04-20 Chong Yidong <cyd@gnu.org>
* progmodes/gdb-mi.el (gdb-inferior-io--maybe-delete-pty): New
function to call delete-process on the gdb-inferior buffer's pty.
* progmodes/gdb-mi.el (gdb-inferior-io--maybe-delete-pty):
New function to call delete-process on the gdb-inferior buffer's pty.
(gdb-reset): Use it, instead of relying on kill-buffer to kill the
pty process (Bug#11273).
(gdb-update): New arg to suppress talking to the gdb process.
@ -360,8 +396,8 @@
(c-comment-indent, c-scan-conditionals, c-indent-defun)
(c-context-line-break): Bind case-fold-search to nil.
* progmodes/cc-mode.el (c-font-lock-fontify-region): Bind
case-fold-search to nil.
* progmodes/cc-mode.el (c-font-lock-fontify-region):
Bind case-fold-search to nil.
2012-04-20 Chong Yidong <cyd@gnu.org>
@ -1112,8 +1148,8 @@
2012-03-30 Agustín Martín Domingo <agustin.martin@hispalinux.es>
* ispell.el (ispell-get-extended-character-mode): Disable
extended-char-mode for hunspell. hunspell does not support it
* ispell.el (ispell-get-extended-character-mode):
Disable extended-char-mode for hunspell. hunspell does not support it
and treats ~word as ordinary words in pipe mode.
2012-03-30 Glenn Morris <rgm@gnu.org>

View file

@ -104,6 +104,7 @@
(eval-when-compile (require 'cl))
(require 'ring)
(require 'ansi-color)
(require 'regexp-opt) ;For regexp-opt-charset.
;; Buffer Local Variables:
;;============================================================================
@ -3000,26 +3001,62 @@ interpreter (e.g., the percent notation of cmd.exe on Windows)."
See `comint-word'."
(comint-word comint-file-name-chars))
(defun comint--unquote&expand-filename (filename)
;; FIXME: The code below does unquote-then-expand which means that "\\$HOME"
;; gets expanded to the same as "$HOME"
(comint-substitute-in-file-name
(comint-unquote-filename filename)))
(defun comint--unquote&requote-argument (qstr &optional upos)
(unless upos (setq upos 0))
(let* ((qpos 0)
(dquotes nil)
(ustrs '())
(re (concat
"[\"']\\|\\\\\\(.\\)"
"\\|\\$\\(?:\\([[:alpha:]][[:alnum:]]*\\)"
"\\|{\\(?2:[^{}]+\\)}\\)"
(when (memq system-type '(ms-dos windows-nt))
"\\|%\\(?2:[^\\\\/]*\\)%")))
(qupos nil)
(push (lambda (str end)
(push str ustrs)
(setq upos (- upos (length str)))
(unless (or qupos (> upos 0))
(setq qupos (if (< end 0) (- end) (+ upos end))))))
match)
(while (setq match (string-match re qstr qpos))
(funcall push (substring qstr qpos match) match)
(cond
((match-beginning 1) (funcall push (match-string 1 qstr) (match-end 0)))
((match-beginning 2) (funcall push (getenv (match-string 2 qstr))
(- (match-end 0))))
((eq (aref qstr match) ?\") (setq dquotes (not dquotes)))
((eq (aref qstr match) ?\')
(cond
(dquotes (funcall push "'" (match-end 0)))
((< match (1+ (length qstr)))
(let ((end (string-match "'" qstr (1+ match))))
(funcall push (substring qstr (1+ match) end)
(or end (length qstr)))))
(t nil)))
(t (error "Unexpected case in comint--unquote&requote-argument!")))
(setq qpos (match-end 0)))
(funcall push (substring qstr qpos) (length qstr))
(list (mapconcat #'identity (nreverse ustrs) "")
qupos #'comint-quote-filename)))
(defun comint--unquote-argument (str)
(car (comint--unquote&requote-argument str)))
(define-obsolete-function-alias 'comint--unquote&expand-filename
#'comint--unquote-argument "24.2")
(defun comint-match-partial-filename ()
"Return the unquoted&expanded filename at point, or nil if none is found.
Environment variables are substituted. See `comint-word'."
(let ((filename (comint--match-partial-filename)))
(and filename (comint--unquote&expand-filename filename))))
(and filename (comint--unquote-argument filename))))
(defun comint-quote-filename (filename)
"Return FILENAME with magic characters quoted.
Magic characters are those in `comint-file-name-quote-list'."
(if (null comint-file-name-quote-list)
filename
(let ((regexp
(format "[%s]"
(mapconcat 'char-to-string comint-file-name-quote-list ""))))
(let ((regexp (regexp-opt-charset comint-file-name-quote-list)))
(save-match-data
(let ((i 0))
(while (string-match regexp filename i)
@ -3033,6 +3070,12 @@ Magic characters are those in `comint-file-name-quote-list'."
filename
(save-match-data
(replace-regexp-in-string "\\\\\\(.\\)" "\\1" filename t))))
(make-obsolete 'comint-unquote-filename nil "24.2")
(defun comint--requote-argument (upos qstr)
;; See `completion-table-with-quoting'.
(let ((res (comint--unquote&requote-argument qstr upos)))
(cons (nth 1 res) (nth 2 res))))
(defun comint-completion-at-point ()
(run-hook-with-args-until-success 'comint-dynamic-complete-functions))
@ -3066,87 +3109,6 @@ Returns t if successful."
(when (comint--match-partial-filename)
(comint--complete-file-name-data)))
;; FIXME: comint--common-suffix, comint--common-quoted-suffix, and
;; comint--table-subvert don't fully solve the problem, since
;; selecting a file from *Completions* won't quote it, among several
;; other problems.
(defun comint--common-suffix (s1 s2)
(assert (not (or (string-match "\n" s1) (string-match "\n" s2))))
;; Since S2 is expected to be the "unquoted/expanded" version of S1,
;; there shouldn't be any case difference, even if the completion is
;; case-insensitive.
(let ((case-fold-search nil))
(string-match ".*?\\(.*\\)\n.*\\1\\'" (concat s1 "\n" s2))
(- (match-end 1) (match-beginning 1))))
(defun comint--common-quoted-suffix (s1 s2)
;; FIXME: Copied in pcomplete.el.
"Find the common suffix between S1 and S2 where S1 is the expanded S2.
S1 is expected to be the unquoted and expanded version of S2.
Returns (PS1 . PS2), i.e. the shortest prefixes of S1 and S2, such that
S1 = (concat PS1 SS1) and S2 = (concat PS2 SS2) and
SS1 = (unquote SS2)."
(let* ((cs (comint--common-suffix s1 s2))
(ss1 (substring s1 (- (length s1) cs)))
(qss1 (comint-quote-filename ss1))
qc s2b)
(if (and (not (equal ss1 qss1))
(setq qc (comint-quote-filename (substring ss1 0 1)))
(setq s2b (- (length s2) cs (length qc) -1))
(>= s2b 0) ;bug#11158.
(eq t (compare-strings s2 s2b (- (length s2) cs -1)
qc nil nil)))
;; The difference found is just that one char is quoted in S2
;; but not in S1, keep looking before this difference.
(comint--common-quoted-suffix
(substring s1 0 (- (length s1) cs))
(substring s2 0 s2b))
(cons (substring s1 0 (- (length s1) cs))
(substring s2 0 (- (length s2) cs))))))
(defun comint--table-subvert (table s1 s2 &optional quote-fun unquote-fun)
"Completion table that replaces the prefix S1 with S2 in STRING.
The result is a completion table which completes strings of the
form (concat S1 S) in the same way as TABLE completes strings of
the form (concat S2 S)."
(lambda (string pred action)
(let* ((str (if (eq t (compare-strings string 0 (length s1) s1 nil nil
completion-ignore-case))
(let ((rest (substring string (length s1))))
(concat s2 (if unquote-fun
(funcall unquote-fun rest) rest)))))
(res (if str (complete-with-action action table str pred))))
(when res
(cond
((and (eq (car-safe action) 'boundaries))
(let ((beg (or (and (eq (car-safe res) 'boundaries) (cadr res)) 0)))
(list* 'boundaries
(max (length s1)
;; FIXME: Adjust because of quoting/unquoting.
(+ beg (- (length s1) (length s2))))
(and (eq (car-safe res) 'boundaries) (cddr res)))))
((stringp res)
(if (eq t (compare-strings res 0 (length s2) s2 nil nil
completion-ignore-case))
(let ((rest (substring res (length s2))))
(concat s1 (if quote-fun (funcall quote-fun rest) rest)))))
((eq action t)
(let ((bounds (completion-boundaries str table pred "")))
(if (>= (car bounds) (length s2))
(if quote-fun (mapcar quote-fun res) res)
(let ((re (concat "\\`"
(regexp-quote (substring s2 (car bounds))))))
(delq nil
(mapcar (lambda (c)
(if (string-match re c)
(let ((str (substring c (match-end 0))))
(if quote-fun
(funcall quote-fun str) str))))
res))))))
;; E.g. action=nil and it's the only completion.
(res))))))
(defun comint-completion-file-name-table (string pred action)
(if (not (file-name-absolute-p string))
(completion-file-name-table string pred action)
@ -3165,6 +3127,13 @@ the form (concat S2 S)."
res)))
(t (completion-file-name-table string pred action)))))
(defvar comint-unquote-function #'comint--unquote-argument
"Function to use for completion of quoted data.
See `completion-table-with-quoting' and `comint-requote-function'.")
(defvar comint-requote-function #'comint--requote-argument
"Function to use for completion of quoted data.
See `completion-table-with-quoting' and `comint-requote-function'.")
(defun comint--complete-file-name-data ()
"Return the completion data for file name at point."
(let* ((filesuffix (cond ((not comint-completion-addsuffix) "")
@ -3175,14 +3144,11 @@ the form (concat S2 S)."
(filename (comint--match-partial-filename))
(filename-beg (if filename (match-beginning 0) (point)))
(filename-end (if filename (match-end 0) (point)))
(unquoted (if filename (comint--unquote&expand-filename filename) ""))
(table
(let ((prefixes (comint--common-quoted-suffix
unquoted filename)))
(comint--table-subvert
#'comint-completion-file-name-table
(cdr prefixes) (car prefixes)
#'comint-quote-filename #'comint-unquote-filename))))
(completion-table-with-quoting
#'comint-completion-file-name-table
comint-unquote-function
comint-requote-function)))
(nconc
(list
filename-beg filename-end

View file

@ -1340,20 +1340,6 @@ which may actually result in an URL rather than a filename."
;; We must inform complete about whether our completion function
;; will do filename style completion.
(defun ffap-complete-as-file-p ()
;; Will `minibuffer-completion-table' complete the minibuffer
;; contents as a filename? Assumes the minibuffer is current.
;; Note: t and non-nil mean somewhat different reasons.
(if (eq minibuffer-completion-table 'ffap-read-file-or-url-internal)
(not (ffap-url-p (buffer-string))) ; t
(and minibuffer-completing-file-name '(t)))) ;list
(and
(featurep 'complete)
(if (boundp 'PC-completion-as-file-name-predicate)
;; modern version of complete.el, just set the variable:
(setq PC-completion-as-file-name-predicate 'ffap-complete-as-file-p)))
;;; Highlighting (`ffap-highlight'):
;;

View file

@ -1,3 +1,7 @@
2012-04-25 Stefan Monnier <monnier@iro.umontreal.ca>
* mh-utils.el (minibuffer-completing-file-name): Don't declare, unused.
2012-04-21 Juanma Barranquero <lekktu@gmail.com>
* mh-folder.el (top): Check whether which-func-modes is t before
@ -179,8 +183,8 @@
* mh-mime.el (mh-decode-message-subject): New function to decode
RFC2047 encoded Subject lines. Used for reply drafts.
* mh-comp.el (mh-compose-and-send-mail): Call
`mh-decode-message-subject' on (reply or forward) message drafts.
* mh-comp.el (mh-compose-and-send-mail):
Call `mh-decode-message-subject' on (reply or forward) message drafts.
2010-05-07 Chong Yidong <cyd@stupidchicken.com>
@ -353,8 +357,8 @@
* mh-show.el (mh-show-preferred-alternative)
* mh-e.el (mh-annotate-msg-hook): Sync docstring with manual.
* mh-comp.el (mh-send-letter, mh-redistribute): Mention
mh-annotate-msg-hook in docstring.
* mh-comp.el (mh-send-letter, mh-redistribute):
Mention mh-annotate-msg-hook in docstring.
2008-06-29 Jeffrey C Honig <jch@honig.net>
@ -404,8 +408,8 @@
2008-05-23 Bill Wohler <wohler@newt.com>
* mh-e.el (mh-invisible-header-fields-internal): Remove
DKIM-Signature as it is covered by DKIM-. Fully qualify X-EID.
* mh-e.el (mh-invisible-header-fields-internal):
Remove DKIM-Signature as it is covered by DKIM-. Fully qualify X-EID.
2008-05-19 Sergey Poznyakoff <gray@gnu.org.ua>
@ -488,8 +492,8 @@
2007-08-21 Jeffrey C Honig <jch@honig.net>
* mh-folder.el (mh-folder-message-menu, mh-folder-mode-map): Add
folder mode support for mh-show-preferred-alternative (closes SF
* mh-folder.el (mh-folder-message-menu, mh-folder-mode-map):
Add folder mode support for mh-show-preferred-alternative (closes SF
#1777321).
* mh-show.el (mh-show-preferred-alternative)
@ -500,8 +504,8 @@
HTML when text content is lacking (closes SF #1777321).
* mh-e.el:
(mh-invisible-header-fields-internal): Exclude Fax and Phone. Put
known exclusions as comments before the list and move parens to
(mh-invisible-header-fields-internal): Exclude Fax and Phone.
Put known exclusions as comments before the list and move parens to
separate lines to aid in sorting (closes SF #1701231).
* mh-mime.el (mm-decode-body): Remove explicit autoload of
@ -750,16 +754,16 @@
(mh-tool-bar-folder-buttons-set, mh-tool-bar-letter-buttons-set):
Call it (closes SF #1452718).
* mh-folder.el (mh-folder-buttons-init-flag): Delete. Use
mh-folder-tool-bar-map instead.
* mh-folder.el (mh-folder-buttons-init-flag): Delete.
Use mh-folder-tool-bar-map instead.
(image-load-path): Delete. No longer used.
(mh-folder-mode): Moved setting of image-load-path into
(mh-folder-mode): Move setting of image-load-path into
mh-tool-bar-folder-buttons-init.
* mh-letter.el (mh-letter-buttons-init-flag): Delete. Use
mh-letter-tool-bar-map instead.
* mh-letter.el (mh-letter-buttons-init-flag): Delete.
Use mh-letter-tool-bar-map instead.
(image-load-path): Delete. No longer used.
(mh-letter-mode): Moved setting of image-load-path into
(mh-letter-mode): Move setting of image-load-path into
mh-tool-bar-letter-buttons-init.
* mh-seq.el (mh-narrow-to-seq, mh-widen): Use with-current-buffer
@ -1007,8 +1011,8 @@
(mh-print-background-flag, mh-show-maximum-size)
(mh-show-use-xface-flag, mh-store-default-directory)
(mh-summary-height, mh-speed-update-interval)
(mh-show-threads-flag, mh-tool-bar-search-function): Add
:package-version keyword to these options (closes SF #1452724).
(mh-show-threads-flag, mh-tool-bar-search-function):
Add :package-version keyword to these options (closes SF #1452724).
(mh-after-commands-processed-hook)
(mh-alias-reloaded-hook, mh-before-commands-processed-hook)
(mh-before-quit-hook, mh-before-send-letter-hook)
@ -1035,15 +1039,15 @@
(mh-speedbar-selected-folder-with-unseen-messages): : Add
:package-version keyword to these faces (closes SF #1452724).
* mh-tool-bar.el (mh-tool-bar-define): Added commented-out
* mh-tool-bar.el (mh-tool-bar-define): Add commented-out
:package-version keywords (closes SF #1452724).
2006-03-28 Bill Wohler <wohler@newt.com>
* mh-tool-bar.el: Use clipboard-kill-region,
clipboard-kill-ring-save, and clipboard-yank instead of undo,
kill-region, and menu-bar-kill-ring-save respectively. In
MH-Letter mode, move save-buffer and mh-fully-kill-draft icons in
kill-region, and menu-bar-kill-ring-save respectively.
In MH-Letter mode, move save-buffer and mh-fully-kill-draft icons in
front of mh-compose-insertion to be consistent with other mailers,
such as Evolution. In MH-Folder mode, move vanilla reply icon to
the left of the other reply icons. Use mail/inbox icon instead of
@ -1099,8 +1103,8 @@
2006-03-14 Bill Wohler <wohler@newt.com>
* mh-compat.el (mh-image-load-path-for-library): Incorporate
changes from image-load-path-for-library, which are:
* mh-compat.el (mh-image-load-path-for-library):
Incorporate changes from image-load-path-for-library, which are:
(image-load-path-for-library): Pass value of path rather than
symbol. Always return list of directories. Guarantee that image
directory comes first.
@ -1126,8 +1130,8 @@
flag to replace-in-string. This was badly needed by
mh-quote-pick-expr in order to properly quote subjects when using
/ s on XEmacs (closes SF #1447598).
(mh-image-load-path-for-library): Merged changes from Reiner. Add
no-error argument. If path t, just return directory.
(mh-image-load-path-for-library): Merged changes from Reiner.
Add no-error argument. If path t, just return directory.
* mh-e.el (mh-profile-component): Drop `s' from mhparam
-components for Mailutils compatibility (closes SF #1446985).
@ -1185,8 +1189,8 @@
local variable mh-image-directory to image-directory. Move error
checks to default case in cond and simplify.
* mh-comp.el (mh-send-letter, mh-insert-auto-fields): Sync
docstrings with manual.
* mh-comp.el (mh-send-letter, mh-insert-auto-fields):
Sync docstrings with manual.
2006-03-02 Bill Wohler <wohler@newt.com>
@ -1212,8 +1216,8 @@
* mh-utils.el (mh-image-directory)
(mh-image-load-path-called-flag): Delete.
(mh-image-load-path): Incorporate changes from Gnus team. Biggest
changes are that it no longer uses/sets mh-image-directory or
(mh-image-load-path): Incorporate changes from Gnus team.
Biggest changes are that it no longer uses/sets mh-image-directory or
mh-image-load-path-called-flag, and returns the updated path
rather than change it.
(mh-logo-display): Change usage of mh-image-load-path.
@ -1278,8 +1282,8 @@
goto-addr.el.
(mh-alias-suggest-alias): Use goto-address-mail-regexp instead of
mh-address-mail-regexp.
(mh-alias-add-address-under-point): Use
goto-address-find-address-at-point instead of
(mh-alias-add-address-under-point):
Use goto-address-find-address-at-point instead of
mh-goto-address-find-address-at-point.
* mh-e.el (mh-show-use-goto-addr-flag): Delete.
@ -1360,7 +1364,7 @@
2006-02-08 Peter S Galbraith <psg@debian.org>
* mh-e.el (mh-invisible-header-fields-internal): Added entries
* mh-e.el (mh-invisible-header-fields-internal): Add entries
"X-BrightmailFiltered:", "X-Brightmail-Tracker:" and "X-Hashcash".
2006-02-04 Bill Wohler <wohler@newt.com>
@ -1429,17 +1433,17 @@
* mh-search.el (which-func-mode): Shush compiler on Emacs 21 too.
* mh-alias.el (mh-alias-gecos-name): Use
mh-replace-regexp-in-string instead of replace-regexp-in-string.
* mh-alias.el (mh-alias-gecos-name):
Use mh-replace-regexp-in-string instead of replace-regexp-in-string.
(crm, multi-prompt): Use mh-require instead of require.
(mh-goto-address-find-address-at-point): Use
mh-line-beginning-position and mh-line-end-position instead of
line-beginning-position and line-end-position. Use
mh-match-string-no-properties instead of
(mh-goto-address-find-address-at-point):
Use mh-line-beginning-position and mh-line-end-position instead of
line-beginning-position and line-end-position.
Use mh-match-string-no-properties instead of
match-string-no-properties.
* mh-comp.el (mh-modify-header-field): Use
mh-line-beginning-position and mh-line-end-position instead of
* mh-comp.el (mh-modify-header-field):
Use mh-line-beginning-position and mh-line-end-position instead of
line-beginning-position and line-end-position.
* mh-compat.el (mailabbrev): Use mh-require instead of require.
@ -1474,16 +1478,16 @@
mh-line-end-position instead of line-beginning-position and
line-end-position.
* mh-limit.el (mh-subject-to-sequence-unthreaded): Use
mh-match-string-no-properties instead of
* mh-limit.el (mh-subject-to-sequence-unthreaded):
Use mh-match-string-no-properties instead of
match-string-no-properties.
(mh-narrow-to-header-field): Use mh-line-beginning-position and
mh-line-end-position instead of line-beginning-position and
line-end-position.
* mh-mime.el (mh-mime-inline-part, mh-mm-display-part)
(mh-mh-quote-unescaped-sharp, mh-mh-directive-present-p): Use
mh-line-beginning-position and mh-line-end-position instead of
(mh-mh-quote-unescaped-sharp, mh-mh-directive-present-p):
Use mh-line-beginning-position and mh-line-end-position instead of
line-beginning-position and line-end-position.
* mh-search.el (which-func): Use mh-require instead of require.
@ -1492,8 +1496,8 @@
(mh-mairix-next-result, mh-namazu-next-result)
(mh-pick-next-result, mh-grep-next-result)
(mh-index-create-imenu-index, mh-index-match-checksum)
(mh-md5sum-parser, mh-openssl-parser, mh-index-update-maps): Use
mh-line-beginning-position and mh-line-end-position instead of
(mh-md5sum-parser, mh-openssl-parser, mh-index-update-maps):
Use mh-line-beginning-position and mh-line-end-position instead of
line-beginning-position and line-end-position.
* mh-seq.el (mh-list-sequences): Use mh-view-mode-enter instead of
@ -1516,8 +1520,8 @@
(mh-speed-flists): Use mh-cancel-timer instead of cancel-timer.
* mh-thread.el (mh-thread-find-children)
(mh-thread-parse-scan-line, mh-thread-generate): Use
mh-line-beginning-position and mh-line-end-position instead of
(mh-thread-parse-scan-line, mh-thread-generate):
Use mh-line-beginning-position and mh-line-end-position instead of
line-beginning-position and line-end-position.
* mh-utils.el (mh-colors-available-p): Use mh-display-color-cells
@ -1738,8 +1742,8 @@
(mh-letter-header-field-regexp, mh-pgp-support-flag)
(mh-x-mailer-string): Move here from mh-comp.el.
(mh-folder-line-matches-show-buffer-p): Move to mh-alias.el.
(mh-thread-scan-line-map, mh-thread-scan-line-map-stack): Move
here from mh-seq.el.
(mh-thread-scan-line-map, mh-thread-scan-line-map-stack):
Move here from mh-seq.el.
(mh-draft-folder, mh-inbox, mh-user-path, mh-current-folder)
(mh-previous-window-config, mh-seen-list, mh-seq-list)
(mh-show-buffer, mh-showing-mode, mh-globals-hash)
@ -2042,10 +2046,10 @@
(mh-show-mouse, mh-modify, mh-goto-msg, mh-set-folder-modified-p):
Move to new file mh-folder.el.
(with-mh-folder-updating, mh-in-show-buffer)
(mh-do-at-event-location, mh-seq-msgs): Moved to mh-acros.el.
(mh-do-at-event-location, mh-seq-msgs): Move to mh-acros.el.
(mh-make-seq, mh-seq-name, mh-notate, mh-find-seq)
(mh-seq-to-msgs, mh-add-msgs-to-seq, mh-canonicalize-sequence):
Moved to mh-seq.el.
Move to mh-seq.el.
(mh-show-xface-function, mh-uncompface-executable, mh-face-to-png)
(mh-uncompface, mh-icontopbm, mh-face-foreground-compat)
(mh-face-background-compat, mh-face-display-function)
@ -2070,8 +2074,8 @@
mh-init.el.
(mh-help-messages): Now an alist of modes to an alist of messages.
(mh-set-help): New function used to set mh-help-messages.
(mh-help): Adjust for new format of mh-help-messages. Add
help-messages argument.
(mh-help): Adjust for new format of mh-help-messages.
Add help-messages argument.
(mh-prefix-help): Refactor to use mh-help.
(mh-coalesce-msg-list, mh-greaterp, mh-lessp): Move here from
mh-e.el.
@ -2202,8 +2206,8 @@
(mh-search-mode-map): Autoload so that keys are shown in help even
before mh-search is loaded.
(mh-search-mode): Sync docstring with manual.
(mh-index-do-search): Rename argument indexer to searcher. Sync
docstring with manual.
(mh-index-do-search): Rename argument indexer to searcher.
Sync docstring with manual.
(mh-pick-do-search): Sync docstring with manual.
(mh-index-p): Rename to mh-search-p.
(mh-indexer-choices): Rename to mh-search-choices.
@ -2220,7 +2224,7 @@
2006-01-13 Bill Wohler <wohler@newt.com>
* mh-acros.el (require): Added Satyaki's comment regarding what
* mh-acros.el (require): Add Satyaki's comment regarding what
needs to happen to remove this defadvice which caused a little
discussion on emacs-devel today (see Subject: mh-e/mh-acros.el
advices `require' incorrectly).
@ -2292,8 +2296,8 @@
* mh-gnus.el: Require mh-acros.
(mh-defmacro-compat, mh-defun-compat): Move to mh-acros.el.
* mh-utils.el (mh-x-image-url-cache-canonicalize): Use
url-hexify-string to remove special characters from filenames
* mh-utils.el (mh-x-image-url-cache-canonicalize):
Use url-hexify-string to remove special characters from filenames
(closes SF #1396499). Note that this invalidates the existing
names in your cache so you might as well remove
~/Mail/.mhe-x-image-cache/* now.
@ -2352,16 +2356,16 @@
than file-executable-p which returns t for directories.
(mh-file-command-p): Move here from mh-utils, since
mh-variant-*-info are the only functions to use it.
(mh-variant-set, mh-variant-set-variant, mh-variant-p): Use
function mh-variants instead of variable. More robust.
(mh-variant-set, mh-variant-set-variant, mh-variant-p):
Use function mh-variants instead of variable. More robust.
(mh-find-path-run): Move here from mh-utils.el. Mention that
checking this variable is unnecessary.
(mh-find-path): Move here from mh-utils.el. With the advent of MH
variants and an mhparam command that doesn't work if there isn't
an MH profile, we can't get libdir for running install-mh. So
don't bother. If there's an issue with the environment, direct the
user to install MH and run install-mh (closes SF #835192). Don't
read ~/.mh_profile directly. Use mh-profile-component which uses
an MH profile, we can't get libdir for running install-mh.
So don't bother. If there's an issue with the environment, direct the
user to install MH and run install-mh (closes SF #835192).
Don't read ~/.mh_profile directly. Use mh-profile-component which uses
mhparam (closes SF #1016027).
* mh-utils.el (mh-get-profile-field): Rename to
@ -2376,12 +2380,12 @@
(mh-no-install, mh-install): Delete.
* mh-customize.el (mh-folder-msg-number):
* mh-mime.el (mh-file-mime-type): Removed trailing whitespace.
* mh-mime.el (mh-file-mime-type): Remove trailing whitespace.
2006-01-09 Bill Wohler <wohler@newt.com>
* mh-init.el (mh-variant-mu-mh-info, mh-variant-nmh-info): Applied
patch from Satyaki from SF #1016027.
* mh-init.el (mh-variant-mu-mh-info, mh-variant-nmh-info):
Applied patch from Satyaki from SF #1016027.
* mh-e.el (mh-rescan-folder): Try to keep cursor at current
message, even if cur sequence is no longer present (closes SF
@ -2429,7 +2433,7 @@
* mh-comp.el: Require cleanup, wrap compiler-shushing defvars with
eval-when-compile.
(mh-file-is-vcard-p): Removed redundant test.
(mh-file-is-vcard-p): Remove redundant test.
* mh-customize.el: Require cleanup, wrap compiler-shushing defvars
with eval-when-compile.
@ -2455,8 +2459,8 @@
* mh-mime.el: Wrap compiler-shushing defvars with
eval-when-compile.
(mh-have-file-command): Initialize variable to 'undefined. Add
docstring. Update function of same name accordingly. Also don't
(mh-have-file-command): Initialize variable to 'undefined.
Add docstring. Update function of same name accordingly. Also don't
need to load executable any more.
(mh-mime-content-types): Delete.
(mh-minibuffer-read-type): Prompt user for type if
@ -2695,11 +2699,11 @@
with manual.
(mh-yank-cur-msg): Mention that mh-ins-buf-prefix isn't used if
you have added a mail-citation-hook and neither are used if you
use one of the supercite flavors of mh-yank-behavior. Sync
docstrings with manual.
use one of the supercite flavors of mh-yank-behavior.
Sync docstrings with manual.
* mh-customize.el (mh-kill-folder-suppress-prompt-hooks): Rename
from mh-kill-folder-suppress-prompt-hook since it is an abnormal
* mh-customize.el (mh-kill-folder-suppress-prompt-hooks):
Rename from mh-kill-folder-suppress-prompt-hook since it is an abnormal
hook. Use "Hook run by `function'..." instead of "Invoked...".
Sync docstrings with manual.
(mh-ins-buf-prefix, mh-yank-behavior): Mention that
@ -2824,13 +2828,13 @@
* mh-customize.el (mh-speed-flists-interval): Rename to
mh-speed-update-interval.
(mh-speed-run-flists-flag): Delete. Setting
mh-speed-flists-interval to 0 accomplishes the same thing.
(mh-speed-run-flists-flag): Delete.
Setting mh-speed-flists-interval to 0 accomplishes the same thing.
* mh-speed.el (mh-folder-speedbar-buttons, mh-speed-flists): Use
mh-speed-update-interval instead of mh-speed-run-flists-flag.
(mh-speed-toggle, mh-speed-view, mh-speed-refresh): Sync
docstrings with manual.
* mh-speed.el (mh-folder-speedbar-buttons, mh-speed-flists):
Use mh-speed-update-interval instead of mh-speed-run-flists-flag.
(mh-speed-toggle, mh-speed-view, mh-speed-refresh):
Sync docstrings with manual.
2005-12-09 Bill Wohler <wohler@newt.com>
@ -2847,8 +2851,8 @@
(mh-invisible-header-fields-internal): Add X-Bugzilla-* and
X-Virus-Scanned.
* mh-customize.el (mh-insert-signature-hook): Rename
mh-letter-insert-signature-hook to mh-insert-signature-hook.
* mh-customize.el (mh-insert-signature-hook):
Rename mh-letter-insert-signature-hook to mh-insert-signature-hook.
* mh-comp.el (mh-insert-signature): Ditto.
@ -2950,10 +2954,10 @@
(mh-next-undeleted-msg, mh-previous-undeleted-msg): Rename arg to
count. Sync docstrings with manual.
(mh-refile-or-write-again): Use output from mh-write-msg-to-file
so that message doesn't change when using this command. Sync
docstrings with manual.
(mh-page-msg, mh-previous-page): Rename arg to lines. Sync
docstrings with manual.
so that message doesn't change when using this command.
Sync docstrings with manual.
(mh-page-msg, mh-previous-page): Rename arg to lines.
Sync docstrings with manual.
(mh-write-msg-to-file): Rename msg to message. Rename no-headers
to no-header. Sync docstrings with manual.
(mh-ps-print-map): Delete keybindings for deleted commands
@ -2977,8 +2981,8 @@
Sync docstrings with manual.
(mh-toggle-mh-decode-mime-flag): Use English in message, not Lisp.
Sync docstrings with manual.
(mh-mm-display-part, mh-mm-inline-message): Use
mh-highlight-citation-style instead of mh-highlight-citation-p.
(mh-mm-display-part, mh-mm-inline-message):
Use mh-highlight-citation-style instead of mh-highlight-citation-p.
(mh-press-button): Sync docstrings with manual.
(mh-display-with-external-viewer): Fix default output in
minibuffer. Sync docstrings with manual.
@ -3069,8 +3073,8 @@
(mh-smail, mh-extract-rejected-mail, mh-forward, mh-redistribute)
(mh-reply, mh-send, mh-send-other-window)
(mh-fill-paragraph-function): Sync docstrings with manual.
(mh-edit-again, mh-extract-rejected-mail, mh-redistribute): Rename
msg argument to message (to make for a better docstring).
(mh-edit-again, mh-extract-rejected-mail, mh-redistribute):
Rename msg argument to message (to make for a better docstring).
* mh-customize.el (mh-redist-full-contents-flag): Convert defvar
to defcustom. Rename by adding -flag.
@ -3095,8 +3099,8 @@
* mh-customize.el (mh-compose-space-does-completion-flag)
(mh-signature-separator-flag, mh-interpret-number-as-range-flag)
(mh-adaptive-cmd-note-flag): Use "Non-nil means" instead of "On
means" to remain checkdoc clean and consistent with Emacs. I
raised this issue with the Emacs developers and Stallman agrees
means" to remain checkdoc clean and consistent with Emacs.
I raised this issue with the Emacs developers and Stallman agrees
that "On means" should be allowed in custom docstrings but that
this change requires thought and should wait until after the Emacs
22 release.
@ -3108,14 +3112,14 @@
* mh-customize.el (mh-interpret-number-as-range-flag): Add * to
docstring.
(mh-adaptive-cmd-note-flag-check, mh-scan-format-file-check): New
functions to check input for mh-adaptive-cmd-note-flag and
(mh-adaptive-cmd-note-flag-check, mh-scan-format-file-check):
New functions to check input for mh-adaptive-cmd-note-flag and
mh-scan-format-file respectively.
(mh-adaptive-cmd-note-flag, mh-scan-format-file): Docstring fixes,
add :set.
* mh-e.el (mh-scan-field-destination-offset): New variable. The
destination is the -, t, b, c, or n character for Replied, To, cc,
* mh-e.el (mh-scan-field-destination-offset): New variable.
The destination is the -, t, b, c, or n character for Replied, To, cc,
Bcc, or Newsgroups respectively.
(mh-make-folder, mh-regenerate-headers, mh-generate-new-cmd-note):
Call new function mh-msg-num-width-to-column to make leap between
@ -3235,10 +3239,10 @@
2005-10-23 Bill Wohler <wohler@newt.com>
* mh-comp.el (mh-letter-menu): Rename
mh-mhn-compose-external-compressed-tar to
mh-mh-compose-external-compressed-tar. Rename
mh-mhn-compose-anon-ftp to mh-mh-compose-anon-ftp. Rename
* mh-comp.el (mh-letter-menu):
Rename mh-mhn-compose-external-compressed-tar to
mh-mh-compose-external-compressed-tar.
Rename mh-mhn-compose-anon-ftp to mh-mh-compose-anon-ftp. Rename
mh-edit-mhn to mh-mh-to-mime. Rename mh-mhn-directive-present-p to
mh-mh-directive-present-p. Rename mh-revert-mhn-edit to
mh-mh-to-mime-undo. Rename mh-gnus-pgp-support-flag to
@ -3248,21 +3252,21 @@
mh-mh-directive-present-p.
(mh-send-letter): Rename mh-mhn-directive-present-p to
mh-mh-directive-present-p. Rename mh-edit-mhn to mh-mh-to-mime.
(mh-letter-mode-map): Rename mh-edit-mhn to mh-mh-to-mime. Rename
mh-mhn-compose-anon-ftp to mh-mh-compose-anon-ftp. Rename
mh-mhn-compose-external-compressed-tar to
(mh-letter-mode-map): Rename mh-edit-mhn to mh-mh-to-mime.
Rename mh-mhn-compose-anon-ftp to mh-mh-compose-anon-ftp.
Rename mh-mhn-compose-external-compressed-tar to
mh-mh-compose-external-compressed-tar. Rename mh-revert-mhn-edit
to mh-mh-to-mime-undo. Rename mh-mhn-compose-external-type to
mh-mh-compose-external-type. Rename mh-mhn-compose-anon-ftp to
mh-mh-compose-anon-ftp. Rename
mh-mhn-compose-external-compressed-tar to
mh-mh-compose-anon-ftp.
Rename mh-mhn-compose-external-compressed-tar to
mh-mh-compose-external-compressed-tar. Rename mh-revert-mhn-edit
to mh-mh-to-mime-undo. Rename mh-mhn-compose-external-type to
mh-mh-compose-external-type.
(mh-send-letter, mh-letter-mode-map): Rename mh-edit-mhn to
mh-mh-to-mime, mh-revert-mhn-edit to mh-mh-to-mime-undo.
(mh-reply, mh-yank-cur-msg, mh-insert-prefix-string): Rename
mh-yank-from-start-of-msg to mh-yank-behavior.
(mh-reply, mh-yank-cur-msg, mh-insert-prefix-string):
Rename mh-yank-from-start-of-msg to mh-yank-behavior.
(mh-letter-mode, mh-to-field, mh-to-fcc, mh-insert-signature)
(mh-check-whom, mh-insert-auto-fields, mh-send-letter)
(mh-insert-letter, mh-yank-cur-msg, mh-insert-prefix-string)
@ -3305,8 +3309,8 @@
(mh-mhn-compose-anon-ftp): Rename to mh-mh-compose-anon-ftp.
Rename mh-mhn-compose-external-type to mh-mh-compose-external-type.
(mh-mhn-compose-external-compressed-tar): Rename to
mh-mh-compose-external-compressed-tar. Rename
mh-mhn-compose-external-type to mh-mh-compose-external-type.
mh-mh-compose-external-compressed-tar.
Rename mh-mhn-compose-external-type to mh-mh-compose-external-type.
(mh-mhn-compose-external-type): Rename to mh-mh-compose-external-type.
(mh-edit-mhn): Rename to mh-mh-to-mime. Rename mh-mhn-args to
mh-mh-to-mime-args. Rename mh-edit-mhn-hook to mh-mh-to-mime-hook.
@ -3323,8 +3327,8 @@
(mh-mh-compose-external-type): Rename extra-param argument to
parameters.
(mh-mml-to-mime, mh-secure-message, mh-mml-unsecure-message)
(mh-mime-display-part, mh-mime-display-single): Rename
mh-gnus-pgp-support-flag to mh-pgp-support-flag.
(mh-mime-display-part, mh-mime-display-single):
Rename mh-gnus-pgp-support-flag to mh-pgp-support-flag.
(mh-compose-insertion): Rename mh-mhn-compose-insertion to
mh-mh-attach-file.
(mh-compose-forward): Rename mh-mhn-compose-forw to
@ -3389,8 +3393,8 @@
* mh-init.el (mh-image-load-path-called-flag): New variable which
is used by mh-image-load-path so that it runs only once.
(mh-image-load-path): Modify so that it gets run only once. Also
flatten out heavily nested if statements to make it clearer.
(mh-image-load-path): Modify so that it gets run only once.
Also flatten out heavily nested if statements to make it clearer.
* mh-e.el (mh-folder-mode): Call mh-image-load-path to allow Emacs
to find images used in the toolbar.
@ -3414,11 +3418,11 @@
need to be indented.
* mh-e.el: mh-folder-tick-face had been renamed to mh-folder-tick
but the code that invoked the face had not been updated. Tick
highlighting working again.
but the code that invoked the face had not been updated.
Tick highlighting working again.
* mh-seq.el (mh-non-seq-mode-line-annotation): Move
make-variable-buffer-local call to top level to avoid warnings in
* mh-seq.el (mh-non-seq-mode-line-annotation):
Move make-variable-buffer-local call to top level to avoid warnings in
CVS Emacs.
* mh-comp.el (mh-insert-letter): Replace deprecated read-input

View file

@ -732,8 +732,7 @@ See Info node `(elisp) Programmed Completion' for details."
;; Shush compiler.
(mh-do-in-xemacs
(defvar completion-root-regexp)
(defvar minibuffer-completing-file-name))
(defvar completion-root-regexp))
(defun mh-folder-completing-read (prompt default allow-root-folder-flag)
"Read folder name with PROMPT and default result DEFAULT.

View file

@ -45,17 +45,6 @@
;; corresponding to the displayed completions because we only
;; provide the start info but not the end info in
;; completion-base-position.
;; - quoting is problematic. E.g. the double-dollar quoting used in
;; substitute-in-file-name (and hence read-file-name-internal) bumps
;; into various bugs:
;; - choose-completion doesn't know how to quote the text it inserts.
;; E.g. it fails to double the dollars in file-name completion, or
;; to backslash-escape spaces and other chars in comint completion.
;; - when completing ~/tmp/fo$$o, the highlighting in *Completions*
;; is off by one position.
;; - all code like PCM which relies on all-completions to match
;; its argument gets confused because all-completions returns unquoted
;; texts (as desired for *Completions* output).
;; - C-x C-f ~/*/sr ? should not list "~/./src".
;; - minibuffer-force-complete completes ~/src/emacs/t<!>/lisp/minibuffer.el
;; to ~/src/emacs/trunk/ and throws away lisp/minibuffer.el.
@ -66,12 +55,9 @@
;; - Make things like icomplete-mode or lightning-completion work with
;; completion-in-region-mode.
;; - extend `metadata':
;; - quoting/unquoting (so we can complete files names with envvars
;; and backslashes, and all-completion can list names without
;; quoting backslashes and dollars).
;; - indicate how to turn all-completion's output into
;; try-completion's output: e.g. completion-ignored-extensions.
;; maybe that could be merged with the "quote" operation above.
;; maybe that could be merged with the "quote" operation.
;; - indicate that `all-completions' doesn't do prefix-completion
;; but just returns some list that relates in some other way to
;; the provided string (as is the case in filecache.el), in which
@ -224,6 +210,42 @@ case sensitive instead."
(let ((completion-ignore-case (not dont-fold)))
(complete-with-action action table string pred))))
(defun completion-table-subvert (table s1 s2)
"Completion table that replaces the prefix S1 with S2 in STRING.
The result is a completion table which completes strings of the
form (concat S1 S) in the same way as TABLE completes strings of
the form (concat S2 S)."
(lambda (string pred action)
(let* ((str (if (eq t (compare-strings string 0 (length s1) s1 nil nil
completion-ignore-case))
(concat s2 (substring string (length s1)))))
(res (if str (complete-with-action action table str pred))))
(when res
(cond
((eq (car-safe action) 'boundaries)
(let ((beg (or (and (eq (car-safe res) 'boundaries) (cadr res)) 0)))
(list* 'boundaries
(max (length s1)
(+ beg (- (length s1) (length s2))))
(and (eq (car-safe res) 'boundaries) (cddr res)))))
((stringp res)
(if (eq t (compare-strings res 0 (length s2) s2 nil nil
completion-ignore-case))
(concat s1 (substring res (length s2)))))
((eq action t)
(let ((bounds (completion-boundaries str table pred "")))
(if (>= (car bounds) (length s2))
res
(let ((re (concat "\\`"
(regexp-quote (substring s2 (car bounds))))))
(delq nil
(mapcar (lambda (c)
(if (string-match re c)
(substring c (match-end 0))))
res))))))
;; E.g. action=nil and it's the only completion.
(res))))))
(defun completion-table-with-context (prefix table string pred action)
;; TODO: add `suffix' maybe?
(let ((pred
@ -347,6 +369,186 @@ Note: TABLE needs to be a proper completion table which obeys predicates."
(complete-with-action action table string pred))
tables)))
(defun completion-table-with-quoting (table unquote requote)
;; A difficult part of completion-with-quoting is to map positions in the
;; quoted string to equivalent positions in the unquoted string and
;; vice-versa. There is no efficient and reliable algorithm that works for
;; arbitrary quote and unquote functions.
;; So to map from quoted positions to unquoted positions, we simply assume
;; that `concat' and `unquote' commute (which tends to be the case).
;; And we ask `requote' to do the work of mapping from unquoted positions
;; back to quoted positions.
"Return a new completion table operating on quoted text.
TABLE operates on the unquoted text.
UNQUOTE is a function that takes a string and returns a new unquoted string.
REQUOTE is a function of 2 args (UPOS QSTR) where
QSTR is a string entered by the user (and hence indicating
the user's preferred form of quoting); and
UPOS is a position within the unquoted form of QSTR.
REQUOTE should return a pair (QPOS . QFUN) such that QPOS is the
position corresponding to UPOS but in QSTR, and QFUN is a function
of one argument (a string) which returns that argument appropriately quoted
for use at QPOS."
;; FIXME: One problem with the current setup is that `qfun' doesn't know if
;; its argument is "the end of the completion", so if the quoting used double
;; quotes (for example), we end up completing "fo" to "foobar and throwing
;; away the closing double quote.
(lambda (string pred action)
(cond
((eq action 'metadata)
(append (completion-metadata string table pred)
'((completion--unquote-requote . t))))
((eq action 'lambda) ;;test-completion
(let ((ustring (funcall unquote string)))
(test-completion ustring table pred)))
((eq (car-safe action) 'boundaries)
(let* ((ustring (funcall unquote string))
(qsuffix (cdr action))
(ufull (if (zerop (length qsuffix)) ustring
(funcall unquote (concat string qsuffix))))
(_ (assert (string-prefix-p ustring ufull)))
(usuffix (substring ufull (length ustring)))
(boundaries (completion-boundaries ustring table pred usuffix))
(qlboundary (car (funcall requote (car boundaries) string)))
(qrboundary (if (zerop (cdr boundaries)) 0 ;Common case.
(let* ((urfullboundary
(+ (cdr boundaries) (length ustring))))
(- (car (funcall requote urfullboundary
(concat string qsuffix)))
(length string))))))
(list* 'boundaries qlboundary qrboundary)))
((eq action nil) ;;try-completion
(let* ((ustring (funcall unquote string))
(completion (try-completion ustring table pred)))
;; Most forms of quoting allow several ways to quote the same string.
;; So here we could simply requote `completion' in a kind of
;; "canonical" quoted form without paying attention to the way
;; `string' was quoted. But since we have to solve the more complex
;; problems of "pay attention to the original quoting" for
;; all-completions, we may as well use it here, since it provides
;; a nicer behavior.
(if (not (stringp completion)) completion
(car (completion--twq-try
string ustring completion 0 unquote requote)))))
((eq action t) ;;all-completions
;; When all-completions is used for completion-try/all-completions
;; (e.g. for `pcm' style), we can't do the job properly here because
;; the caller will match our output against some pattern derived from
;; the user's (quoted) input, and we don't have access to that
;; pattern, so we can't know how to requote our output so that it
;; matches the quoting used in the pattern. It is to fix this
;; fundamental problem that we have to introduce the new
;; unquote-requote method so that completion-try/all-completions can
;; pass the unquoted string to the style functions.
(pcase-let*
((ustring (funcall unquote string))
(completions (all-completions ustring table pred))
(boundary (car (completion-boundaries ustring table pred ""))))
(completion--twq-all
string ustring completions boundary unquote requote)))
((eq action 'completion--unquote)
(let ((ustring (funcall unquote string))
(uprefix (funcall unquote (substring string 0 pred))))
;; We presume (more or less) that `concat' and `unquote' commute.
(assert (string-prefix-p uprefix ustring))
(list ustring table (length uprefix)
(lambda (unquoted-result op)
(pcase op
(`1 ;;try
(if (not (stringp (car-safe unquoted-result)))
unquoted-result
(completion--twq-try
string ustring
(car unquoted-result) (cdr unquoted-result)
unquote requote)))
(`2 ;;all
(let* ((last (last unquoted-result))
(base (or (cdr last) 0)))
(when last
(setcdr last nil)
(completion--twq-all string ustring
unquoted-result base
unquote requote))))))))))))
(defun completion--twq-try (string ustring completion point
unquote requote)
;; Basically two case: either the new result is
;; - commonprefix1 <point> morecommonprefix <qpos> suffix
;; - commonprefix <qpos> newprefix <point> suffix
(pcase-let*
((prefix (fill-common-string-prefix ustring completion))
(suffix (substring completion (max point (length prefix))))
(`(,qpos . ,qfun) (funcall requote (length prefix) string))
(qstr1 (if (> point (length prefix))
(funcall qfun (substring completion (length prefix) point))))
(qsuffix (funcall qfun suffix))
(qstring (concat (substring string 0 qpos) qstr1 qsuffix))
(qpoint
(cond
((zerop point) 0)
((> point (length prefix)) (+ qpos (length qstr1)))
(t (car (funcall requote point string))))))
;; Make sure `requote' worked.
(assert (equal (funcall unquote qstring) completion))
(cons qstring qpoint)))
(defun completion--twq-all (string ustring completions boundary
unquote requote)
(when completions
(pcase-let*
((prefix
(let ((completion-regexp-list nil))
(try-completion "" (cons (substring ustring boundary)
completions))))
(`(,qfullpos . ,qfun)
(funcall requote (+ boundary (length prefix)) string))
(qfullprefix (substring string 0 qfullpos))
(_ (assert (let ((uboundarystr (substring ustring 0 boundary)))
(equal (funcall unquote qfullprefix)
(concat uboundarystr prefix)))))
(qboundary (car (funcall requote boundary string)))
(_ (assert (<= qboundary qfullpos)))
;; FIXME: this split/quote/concat business messes up the carefully
;; placed completions-common-part and completions-first-difference
;; faces. We could try within the mapcar loop to search for the
;; boundaries of those faces, pass them to `requote' to find their
;; equivalent positions in the quoted output and re-add the faces:
;; this might actually lead to correct results but would be
;; pretty expensive.
;; The better solution is to not quote the *Completions* display,
;; which nicely circumvents the problem. The solution I used here
;; instead is to hope that `qfun' preserves the text-properties and
;; presume that the `first-difference' is not within the `prefix';
;; this presumption is not always true, but at least in practice it is
;; true in most cases.
(qprefix (propertize (substring qfullprefix qboundary)
'face 'completions-common-part)))
;; Here we choose to quote all elements returned, but a better option
;; would be to return unquoted elements together with a function to
;; requote them, so that *Completions* can show nicer unquoted values
;; which only get quoted when needed by choose-completion.
(nconc
(mapcar (lambda (completion)
(assert (string-prefix-p prefix completion))
(let* ((new (substring completion (length prefix)))
(qnew (funcall qfun new))
(qcompletion (concat qprefix qnew)))
(assert
(equal (funcall unquote
(concat (substring string 0 qboundary)
qcompletion))
(concat (substring ustring 0 boundary)
completion)))
qcompletion))
completions)
qboundary))))
;; (defmacro complete-in-turn (a b) `(completion-table-in-turn ,a ,b))
;; (defmacro dynamic-completion-table (fun) `(completion-table-dynamic ,fun))
(define-obsolete-function-alias
@ -535,21 +737,47 @@ completing buffer and file names, respectively."
(delete-dups (append (cdr over) (copy-sequence completion-styles)))
completion-styles)))
(defun completion--nth-completion (n string table pred point metadata)
"Call the Nth method of completion styles."
(unless metadata
(setq metadata
(completion-metadata (substring string 0 point) table pred)))
;; We provide special support for quoting/unquoting here because it cannot
;; reliably be done within the normal completion-table routines: Completion
;; styles such as `substring' or `partial-completion' need to match the
;; output of all-completions with the user's input, and since most/all
;; quoting mechanisms allow several equivalent quoted forms, the
;; completion-style can't do this matching (e.g. `substring' doesn't know
;; that "\a\b\e" is a valid (quoted) substring of "label").
;; The quote/unquote function needs to come from the completion table (rather
;; than from completion-extra-properties) because it may apply only to some
;; part of the string (e.g. substitute-in-file-name).
(let ((requote
(when (completion-metadata-get metadata 'completion--unquote-requote)
(let ((new (funcall table string point 'completion--unquote)))
(setq string (pop new))
(setq table (pop new))
(setq point (pop new))
(pop new))))
(result
(completion--some (lambda (style)
(funcall (nth n (assq style
completion-styles-alist))
string table pred point))
(completion--styles metadata))))
(if requote
(funcall requote result n)
result)))
(defun completion-try-completion (string table pred point &optional metadata)
"Try to complete STRING using completion table TABLE.
Only the elements of table that satisfy predicate PRED are considered.
POINT is the position of point within STRING.
The return value can be either nil to indicate that there is no completion,
t to indicate that STRING is the only possible completion,
or a pair (STRING . NEWPOINT) of the completed result string together with
or a pair (NEWSTRING . NEWPOINT) of the completed result string together with
a new position for point."
(completion--some (lambda (style)
(funcall (nth 1 (assq style completion-styles-alist))
string table pred point))
(completion--styles (or metadata
(completion-metadata
(substring string 0 point)
table pred)))))
(completion--nth-completion 1 string table pred point metadata))
(defun completion-all-completions (string table pred point &optional metadata)
"List the possible completions of STRING in completion table TABLE.
@ -559,13 +787,7 @@ The return value is a list of completions and may contain the base-size
in the last `cdr'."
;; FIXME: We need to additionally return the info needed for the
;; second part of completion-base-position.
(completion--some (lambda (style)
(funcall (nth 2 (assq style completion-styles-alist))
string table pred point))
(completion--styles (or metadata
(completion-metadata
(substring string 0 point)
table pred)))))
(completion--nth-completion 2 string table pred point metadata))
(defun minibuffer--bitset (modified completions exact)
(logior (if modified 4 0)
@ -1754,7 +1976,10 @@ This is only used when the minibuffer area has no active minibuffer.")
;;; Completion tables.
(defun minibuffer--double-dollars (str)
(replace-regexp-in-string "\\$" "$$" str))
;; Reuse the actual "$" from the string to preserve any text-property it
;; might have, such as `face'.
(replace-regexp-in-string "\\$" (lambda (dollar) (concat dollar dollar))
str))
(defun completion--make-envvar-table ()
(mapcar (lambda (enventry)
@ -1880,58 +2105,40 @@ same as `substitute-in-file-name'."
(make-obsolete-variable 'read-file-name-predicate
"use the regular PRED argument" "23.2")
(defun completion--file-name-table (string pred action)
(defun completion--sifn-requote (upos qstr)
(let ((qpos 0))
(while (and (> upos 0)
(string-match "\\$\\(\\$\\|\\([[:alnum:]_]+\\|{[^}]*}\\)\\)?"
qstr qpos))
(cond
((>= (- (match-beginning 0) qpos) upos) ; UPOS is before current match.
(setq qpos (+ qpos upos))
(setq upos 0))
((not (match-end 1)) ;A sole $: probably an error.
(setq upos (- upos (- (match-end 0) qpos)))
(setq qpos (match-end 0)))
(t
(setq upos (- upos (- (match-beginning 0) qpos)))
(setq qpos (match-end 0))
(setq upos (- upos (length (substitute-in-file-name
(match-string 0 qstr))))))))
;; If `upos' is negative, it's because it's within the expansion of an
;; envvar, i.e. there is no exactly matching qpos, so we just use the next
;; available qpos right after the envvar.
(cons (if (>= upos 0) (+ qpos upos) qpos)
#'minibuffer--double-dollars)))
(defalias 'completion--file-name-table
(completion-table-with-quoting #'completion-file-name-table
#'substitute-in-file-name
#'completion--sifn-requote)
"Internal subroutine for `read-file-name'. Do not call this.
This is a completion table for file names, like `completion-file-name-table'
except that it passes the file name through `substitute-in-file-name'."
(cond
((eq (car-safe action) 'boundaries)
;; For the boundaries, we can't really delegate to
;; substitute-in-file-name+completion-file-name-table and then fix
;; them up (as we do for the other actions), because it would
;; require us to track the relationship between `str' and
;; `string', which is difficult. And in any case, if
;; substitute-in-file-name turns "fo-$TO-ba" into "fo-o/b-ba",
;; there's no way for us to return proper boundaries info, because
;; the boundary is not (yet) in `string'.
;;
;; FIXME: Actually there is a way to return correct boundaries
;; info, at the condition of modifying the all-completions
;; return accordingly. But for now, let's not bother.
(completion-file-name-table string pred action))
(t
(let* ((default-directory
(if (stringp pred)
;; It used to be that `pred' was abused to pass `dir'
;; as an argument.
(prog1 (file-name-as-directory (expand-file-name pred))
(setq pred nil))
default-directory))
(str (condition-case nil
(substitute-in-file-name string)
(error string)))
(comp (completion-file-name-table
str
(with-no-warnings (or pred read-file-name-predicate))
action)))
(cond
((stringp comp)
;; Requote the $s before returning the completion.
(minibuffer--double-dollars comp))
((and (null action) comp
;; Requote the $s before checking for changes.
(setq str (minibuffer--double-dollars str))
(not (string-equal string str)))
;; If there's no real completion, but substitute-in-file-name
;; changed the string, then return the new string.
str)
(t comp))))))
except that it passes the file name through `substitute-in-file-name'.")
(defalias 'read-file-name-internal
(completion-table-in-turn 'completion--embedded-envvar-table
'completion--file-name-table)
(completion-table-in-turn #'completion--embedded-envvar-table
#'completion--file-name-table)
"Internal subroutine for `read-file-name'. Do not call this.")
(defvar read-file-name-function 'read-file-name-default
@ -2073,7 +2280,7 @@ and `read-file-name-function'."
;; use (eq minibuffer-completion-table #'read-file-name-internal), which is
;; probably even worse. Maybe We should add some read-file-name-setup-hook
;; instead, but for now, let's keep this non-obsolete.
;;(make-obsolete-variable 'minibuffer-completing-file-name nil "24.1" 'get)
;;(make-obsolete-variable 'minibuffer-completing-file-name nil "future" 'get)
(defun read-file-name-default (prompt &optional dir default-filename mustmatch initial predicate)
"Default method for reading file names.

View file

@ -205,8 +205,8 @@ Includes files as well as host names followed by a colon."
;; Avoid connecting to the remote host when we're
;; only completing the host name.
(list string)
(comint--table-subvert (pcomplete-all-entries)
"" "/ssh:")))
(completion-table-subvert (pcomplete-all-entries)
"" "/ssh:")))
((string-match "/" string) ; Local file name.
(pcomplete-all-entries))
(t ;Host name or local file name.

View file

@ -165,22 +165,8 @@ A non-nil value is useful if `pcomplete-autolist' is non-nil too."
:type 'boolean
:group 'pcomplete)
(defcustom pcomplete-arg-quote-list nil
"List of characters to quote when completing an argument."
:type '(choice (repeat character)
(const :tag "Don't quote" nil))
:group 'pcomplete)
(defcustom pcomplete-quote-arg-hook nil
"A hook which is run to quote a character within a filename.
Each function is passed both the filename to be quoted, and the index
to be considered. If the function wishes to provide an alternate
quoted form, it need only return the replacement string. If no
function provides a replacement, quoting shall proceed as normal,
using a backslash to quote any character which is a member of
`pcomplete-arg-quote-list'."
:type 'hook
:group 'pcomplete)
(define-obsolete-variable-alias
'pcomplete-arg-quote-list 'comint-file-name-quote-list "24.2")
(defcustom pcomplete-man-function 'man
"A function to that will be called to display a manual page.
@ -370,48 +356,28 @@ modified to be an empty string, or the desired separation string."
;; it pretty much impossible to have completion other than
;; prefix-completion.
;;
;; pcomplete--common-quoted-suffix and comint--table-subvert try to
;; work around this difficulty with heuristics, but it's
;; really a hack.
;; pcomplete--common-suffix and completion-table-subvert try to work around
;; this difficulty with heuristics, but it's really a hack.
(defvar pcomplete-unquote-argument-function nil)
(defvar pcomplete-unquote-argument-function #'comint--unquote-argument)
(defun pcomplete-unquote-argument (s)
(cond
(pcomplete-unquote-argument-function
(funcall pcomplete-unquote-argument-function s))
((null pcomplete-arg-quote-list) s)
(t
(replace-regexp-in-string "\\\\\\(.\\)" "\\1" s t))))
(defsubst pcomplete-unquote-argument (s)
(funcall pcomplete-unquote-argument-function s))
(defun pcomplete--common-quoted-suffix (s1 s2)
;; FIXME: Copied in comint.el.
"Find the common suffix between S1 and S2 where S1 is the expanded S2.
S1 is expected to be the unquoted and expanded version of S2.
Returns (PS1 . PS2), i.e. the shortest prefixes of S1 and S2, such that
S1 = (concat PS1 SS1) and S2 = (concat PS2 SS2) and
SS1 = (unquote SS2)."
(let* ((cs (comint--common-suffix s1 s2))
(ss1 (substring s1 (- (length s1) cs)))
(qss1 (pcomplete-quote-argument ss1))
qc s2b)
(if (and (not (equal ss1 qss1))
(setq qc (pcomplete-quote-argument (substring ss1 0 1)))
(setq s2b (- (length s2) cs (length qc) -1))
(>= s2b 0) ;bug#11158.
(eq t (compare-strings s2 s2b (- (length s2) cs -1)
qc nil nil)))
;; The difference found is just that one char is quoted in S2
;; but not in S1, keep looking before this difference.
(pcomplete--common-quoted-suffix
(substring s1 0 (- (length s1) cs))
(substring s2 0 s2b))
(cons (substring s1 0 (- (length s1) cs))
(substring s2 0 (- (length s2) cs))))))
(defvar pcomplete-requote-argument-function #'comint--requote-argument)
(defun pcomplete--common-suffix (s1 s2)
;; Since S2 is expected to be the "unquoted/expanded" version of S1,
;; there shouldn't be any case difference, even if the completion is
;; case-insensitive.
(let ((case-fold-search nil))
(string-match
;; \x3FFF7F is just an arbitrary char among the ones Emacs accepts
;; that hopefully will never appear in normal text.
"\\(?:.\\|\n\\)*?\\(\\(?:.\\|\n\\)*\\)\x3FFF7F\\(?:.\\|\n\\)*\\1\\'"
(concat s1 "\x3FFF7F" s2))
(- (match-end 1) (match-beginning 1))))
;; I don't think such commands are usable before first setting up buffer-local
;; variables to parse args, so there's no point autoloading it.
;; ;;;###autoload
(defun pcomplete-completions-at-point ()
"Provide standard completion using pcomplete's completion tables.
Same as `pcomplete' but using the standard completion UI."
@ -442,34 +408,31 @@ Same as `pcomplete' but using the standard completion UI."
;; pcomplete-stub and works from the buffer's text instead,
;; we need to trick minibuffer-complete, into using
;; pcomplete-stub without its knowledge. To that end, we
;; use comint--table-subvert to construct a completion
;; use completion-table-subvert to construct a completion
;; table which expects strings using a prefix from the
;; buffer's text but internally uses the corresponding
;; prefix from pcomplete-stub.
(beg (max (- (point) (length pcomplete-stub))
(pcomplete-begin)))
(buftext (buffer-substring beg (point))))
(buftext (pcomplete-unquote-argument
(buffer-substring beg (point)))))
(when completions
(let ((table
(cond
((not (equal pcomplete-stub buftext))
;; This isn't always strictly right (e.g. if
;; FOO="toto/$FOO", then completion of /$FOO/bar may
;; result in something incorrect), but given the lack of
;; any other info, it's about as good as it gets, and in
;; practice it should work just fine (fingers crossed).
(let ((prefixes (pcomplete--common-quoted-suffix
(completion-table-with-quoting
(if (equal pcomplete-stub buftext)
completions
;; This may not always be strictly right, but given the lack
;; of any other info, it's about as good as it gets, and in
;; practice it should work just fine (fingers crossed).
(let ((suf-len (pcomplete--common-suffix
pcomplete-stub buftext)))
(comint--table-subvert
completions (cdr prefixes) (car prefixes)
#'pcomplete-quote-argument #'pcomplete-unquote-argument)))
(t
(lambda (string pred action)
(let ((res (complete-with-action
action completions string pred)))
(if (stringp res)
(pcomplete-quote-argument res)
res))))))
(completion-table-subvert
completions
(substring buftext 0 (- (length buftext) suf-len))
(substring pcomplete-stub 0
(- (length pcomplete-stub) suf-len)))))
pcomplete-unquote-argument-function
pcomplete-requote-argument-function))
(pred
;; Pare it down, if applicable.
(when (and pcomplete-use-paring pcomplete-seen)
@ -828,22 +791,8 @@ this is `comint-dynamic-complete-functions'."
(throw 'pcompleted t)
pcomplete-args))))))
(defun pcomplete-quote-argument (filename)
"Return FILENAME with magic characters quoted.
Magic characters are those in `pcomplete-arg-quote-list'."
(if (null pcomplete-arg-quote-list)
filename
(let ((index 0))
(mapconcat (lambda (c)
(prog1
(or (run-hook-with-args-until-success
'pcomplete-quote-arg-hook filename index)
(when (memq c pcomplete-arg-quote-list)
(string ?\\ c))
(char-to-string c))
(setq index (1+ index))))
filename
""))))
(define-obsolete-function-alias
'pcomplete-quote-argument #'comint-quote-filename "24.2")
;; file-system completion lists
@ -1179,14 +1128,14 @@ Returns non-nil if a space was appended at the end."
(if (not pcomplete-ignore-case)
(insert-and-inherit (if raw-p
(substring entry (length stub))
(pcomplete-quote-argument
(comint-quote-filename
(substring entry (length stub)))))
;; the stub is not quoted at this time, so to determine the
;; length of what should be in the buffer, we must quote it
;; FIXME: Here we presume that quoting `stub' gives us the exact
;; text in the buffer before point, which is not guaranteed;
;; e.g. it is not the case in eshell when completing ${FOO}tm[TAB].
(delete-char (- (length (pcomplete-quote-argument stub))))
(delete-char (- (length (comint-quote-filename stub))))
;; if there is already a backslash present to handle the first
;; character, don't bother quoting it
(when (eq (char-before) ?\\)
@ -1194,7 +1143,7 @@ Returns non-nil if a space was appended at the end."
(setq entry (substring entry 1)))
(insert-and-inherit (if raw-p
entry
(pcomplete-quote-argument entry))))
(comint-quote-filename entry))))
(let (space-added)
(when (and (not (memq (char-before) pcomplete-suffix-list))
addsuffix)
@ -1204,7 +1153,7 @@ Returns non-nil if a space was appended at the end."
pcomplete-last-completion-stub stub)
space-added)))
;; selection of completions
;; Selection of completions.
(defun pcomplete-do-complete (stub completions)
"Dynamically complete at point using STUB and COMPLETIONS.