diff options
| author | Stefan Monnier | 2012-04-25 14:53:57 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2012-04-25 14:53:57 -0400 |
| commit | b4ff4f1fcb552dab77d4312f9adb9f290782fa98 (patch) | |
| tree | ed23ce73595490f9587bf179bad6b8797b13529a | |
| parent | 79c4eeb45046eca02bd4a5daad1b673eb48377a1 (diff) | |
| download | emacs-b4ff4f1fcb552dab77d4312f9adb9f290782fa98.tar.gz emacs-b4ff4f1fcb552dab77d4312f9adb9f290782fa98.zip | |
Use completion-table-with-quoting for comint and pcomplete.
* lisp/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.
* lisp/pcmpl-unix.el (pcomplete/scp): Use completion-table-subvert.
* lisp/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.
| -rw-r--r-- | lisp/ChangeLog | 21 | ||||
| -rw-r--r-- | lisp/comint.el | 160 | ||||
| -rw-r--r-- | lisp/pcmpl-unix.el | 4 | ||||
| -rw-r--r-- | lisp/pcomplete.el | 145 |
4 files changed, 133 insertions, 197 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 8a21f5966c7..dc56bf3c1e2 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,5 +1,26 @@ | |||
| 1 | 2012-04-25 Stefan Monnier <monnier@iro.umontreal.ca> | 1 | 2012-04-25 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 2 | ||
| 3 | Use completion-table-with-quoting for comint and pcomplete. | ||
| 4 | * comint.el (comint--unquote&requote-argument) | ||
| 5 | (comint--unquote-argument, comint--requote-argument): New functions. | ||
| 6 | (comint--unquote&expand-filename, comint-unquote-filename): Obsolete. | ||
| 7 | (comint-quote-filename): Use regexp-opt-charset. | ||
| 8 | (comint--common-suffix, comint--common-quoted-suffix) | ||
| 9 | (comint--table-subvert): Remove. | ||
| 10 | (comint-unquote-function, comint-requote-function): New vars. | ||
| 11 | (comint--complete-file-name-data): Use them with | ||
| 12 | completion-table-with-quoting. | ||
| 13 | * pcmpl-unix.el (pcomplete/scp): Use completion-table-subvert. | ||
| 14 | * pcomplete.el (pcomplete-arg-quote-list) | ||
| 15 | (pcomplete-quote-arg-hook, pcomplete-quote-argument): Obsolete. | ||
| 16 | (pcomplete-unquote-argument-function): Default to non-nil. | ||
| 17 | (pcomplete-unquote-argument): Simplify. | ||
| 18 | (pcomplete--common-quoted-suffix): Remove. | ||
| 19 | (pcomplete-requote-argument-function): New var. | ||
| 20 | (pcomplete--common-suffix): New function. | ||
| 21 | (pcomplete-completions-at-point): Use completion-table-with-quoting | ||
| 22 | and completion-table-subvert. | ||
| 23 | |||
| 3 | * minibuffer.el: Use completion-table-with-quoting for read-file-name. | 24 | * minibuffer.el: Use completion-table-with-quoting for read-file-name. |
| 4 | (minibuffer--double-dollars): Preserve properties. | 25 | (minibuffer--double-dollars): Preserve properties. |
| 5 | (completion--sifn-requote): New function. | 26 | (completion--sifn-requote): New function. |
diff --git a/lisp/comint.el b/lisp/comint.el index 10981675971..2f8d7bd850c 100644 --- a/lisp/comint.el +++ b/lisp/comint.el | |||
| @@ -104,6 +104,7 @@ | |||
| 104 | (eval-when-compile (require 'cl)) | 104 | (eval-when-compile (require 'cl)) |
| 105 | (require 'ring) | 105 | (require 'ring) |
| 106 | (require 'ansi-color) | 106 | (require 'ansi-color) |
| 107 | (require 'regexp-opt) ;For regexp-opt-charset. | ||
| 107 | 108 | ||
| 108 | ;; Buffer Local Variables: | 109 | ;; Buffer Local Variables: |
| 109 | ;;============================================================================ | 110 | ;;============================================================================ |
| @@ -3000,26 +3001,62 @@ interpreter (e.g., the percent notation of cmd.exe on Windows)." | |||
| 3000 | See `comint-word'." | 3001 | See `comint-word'." |
| 3001 | (comint-word comint-file-name-chars)) | 3002 | (comint-word comint-file-name-chars)) |
| 3002 | 3003 | ||
| 3003 | (defun comint--unquote&expand-filename (filename) | 3004 | (defun comint--unquote&requote-argument (qstr &optional upos) |
| 3004 | ;; FIXME: The code below does unquote-then-expand which means that "\\$HOME" | 3005 | (unless upos (setq upos 0)) |
| 3005 | ;; gets expanded to the same as "$HOME" | 3006 | (let* ((qpos 0) |
| 3006 | (comint-substitute-in-file-name | 3007 | (dquotes nil) |
| 3007 | (comint-unquote-filename filename))) | 3008 | (ustrs '()) |
| 3009 | (re (concat | ||
| 3010 | "[\"']\\|\\\\\\(.\\)" | ||
| 3011 | "\\|\\$\\(?:\\([[:alpha:]][[:alnum:]]*\\)" | ||
| 3012 | "\\|{\\(?2:[^{}]+\\)}\\)" | ||
| 3013 | (when (memq system-type '(ms-dos windows-nt)) | ||
| 3014 | "\\|%\\(?2:[^\\\\/]*\\)%"))) | ||
| 3015 | (qupos nil) | ||
| 3016 | (push (lambda (str end) | ||
| 3017 | (push str ustrs) | ||
| 3018 | (setq upos (- upos (length str))) | ||
| 3019 | (unless (or qupos (> upos 0)) | ||
| 3020 | (setq qupos (if (< end 0) (- end) (+ upos end)))))) | ||
| 3021 | match) | ||
| 3022 | (while (setq match (string-match re qstr qpos)) | ||
| 3023 | (funcall push (substring qstr qpos match) match) | ||
| 3024 | (cond | ||
| 3025 | ((match-beginning 1) (funcall push (match-string 1 qstr) (match-end 0))) | ||
| 3026 | ((match-beginning 2) (funcall push (getenv (match-string 2 qstr)) | ||
| 3027 | (- (match-end 0)))) | ||
| 3028 | ((eq (aref qstr match) ?\") (setq dquotes (not dquotes))) | ||
| 3029 | ((eq (aref qstr match) ?\') | ||
| 3030 | (cond | ||
| 3031 | (dquotes (funcall push "'" (match-end 0))) | ||
| 3032 | ((< match (1+ (length qstr))) | ||
| 3033 | (let ((end (string-match "'" qstr (1+ match)))) | ||
| 3034 | (funcall push (substring qstr (1+ match) end) | ||
| 3035 | (or end (length qstr))))) | ||
| 3036 | (t nil))) | ||
| 3037 | (t (error "Unexpected case in comint--unquote&requote-argument!"))) | ||
| 3038 | (setq qpos (match-end 0))) | ||
| 3039 | (funcall push (substring qstr qpos) (length qstr)) | ||
| 3040 | (list (mapconcat #'identity (nreverse ustrs) "") | ||
| 3041 | qupos #'comint-quote-filename))) | ||
| 3042 | |||
| 3043 | (defun comint--unquote-argument (str) | ||
| 3044 | (car (comint--unquote&requote-argument str))) | ||
| 3045 | (define-obsolete-function-alias 'comint--unquote&expand-filename | ||
| 3046 | #'comint--unquote-argument "24.2") | ||
| 3008 | 3047 | ||
| 3009 | (defun comint-match-partial-filename () | 3048 | (defun comint-match-partial-filename () |
| 3010 | "Return the unquoted&expanded filename at point, or nil if none is found. | 3049 | "Return the unquoted&expanded filename at point, or nil if none is found. |
| 3011 | Environment variables are substituted. See `comint-word'." | 3050 | Environment variables are substituted. See `comint-word'." |
| 3012 | (let ((filename (comint--match-partial-filename))) | 3051 | (let ((filename (comint--match-partial-filename))) |
| 3013 | (and filename (comint--unquote&expand-filename filename)))) | 3052 | (and filename (comint--unquote-argument filename)))) |
| 3014 | 3053 | ||
| 3015 | (defun comint-quote-filename (filename) | 3054 | (defun comint-quote-filename (filename) |
| 3016 | "Return FILENAME with magic characters quoted. | 3055 | "Return FILENAME with magic characters quoted. |
| 3017 | Magic characters are those in `comint-file-name-quote-list'." | 3056 | Magic characters are those in `comint-file-name-quote-list'." |
| 3018 | (if (null comint-file-name-quote-list) | 3057 | (if (null comint-file-name-quote-list) |
| 3019 | filename | 3058 | filename |
| 3020 | (let ((regexp | 3059 | (let ((regexp (regexp-opt-charset comint-file-name-quote-list))) |
| 3021 | (format "[%s]" | ||
| 3022 | (mapconcat 'char-to-string comint-file-name-quote-list "")))) | ||
| 3023 | (save-match-data | 3060 | (save-match-data |
| 3024 | (let ((i 0)) | 3061 | (let ((i 0)) |
| 3025 | (while (string-match regexp filename i) | 3062 | (while (string-match regexp filename i) |
| @@ -3033,6 +3070,12 @@ Magic characters are those in `comint-file-name-quote-list'." | |||
| 3033 | filename | 3070 | filename |
| 3034 | (save-match-data | 3071 | (save-match-data |
| 3035 | (replace-regexp-in-string "\\\\\\(.\\)" "\\1" filename t)))) | 3072 | (replace-regexp-in-string "\\\\\\(.\\)" "\\1" filename t)))) |
| 3073 | (make-obsolete 'comint-unquote-filename nil "24.2") | ||
| 3074 | |||
| 3075 | (defun comint--requote-argument (upos qstr) | ||
| 3076 | ;; See `completion-table-with-quoting'. | ||
| 3077 | (let ((res (comint--unquote&requote-argument qstr upos))) | ||
| 3078 | (cons (nth 1 res) (nth 2 res)))) | ||
| 3036 | 3079 | ||
| 3037 | (defun comint-completion-at-point () | 3080 | (defun comint-completion-at-point () |
| 3038 | (run-hook-with-args-until-success 'comint-dynamic-complete-functions)) | 3081 | (run-hook-with-args-until-success 'comint-dynamic-complete-functions)) |
| @@ -3066,87 +3109,6 @@ Returns t if successful." | |||
| 3066 | (when (comint--match-partial-filename) | 3109 | (when (comint--match-partial-filename) |
| 3067 | (comint--complete-file-name-data))) | 3110 | (comint--complete-file-name-data))) |
| 3068 | 3111 | ||
| 3069 | ;; FIXME: comint--common-suffix, comint--common-quoted-suffix, and | ||
| 3070 | ;; comint--table-subvert don't fully solve the problem, since | ||
| 3071 | ;; selecting a file from *Completions* won't quote it, among several | ||
| 3072 | ;; other problems. | ||
| 3073 | |||
| 3074 | (defun comint--common-suffix (s1 s2) | ||
| 3075 | (assert (not (or (string-match "\n" s1) (string-match "\n" s2)))) | ||
| 3076 | ;; Since S2 is expected to be the "unquoted/expanded" version of S1, | ||
| 3077 | ;; there shouldn't be any case difference, even if the completion is | ||
| 3078 | ;; case-insensitive. | ||
| 3079 | (let ((case-fold-search nil)) | ||
| 3080 | (string-match ".*?\\(.*\\)\n.*\\1\\'" (concat s1 "\n" s2)) | ||
| 3081 | (- (match-end 1) (match-beginning 1)))) | ||
| 3082 | |||
| 3083 | (defun comint--common-quoted-suffix (s1 s2) | ||
| 3084 | ;; FIXME: Copied in pcomplete.el. | ||
| 3085 | "Find the common suffix between S1 and S2 where S1 is the expanded S2. | ||
| 3086 | S1 is expected to be the unquoted and expanded version of S2. | ||
| 3087 | Returns (PS1 . PS2), i.e. the shortest prefixes of S1 and S2, such that | ||
| 3088 | S1 = (concat PS1 SS1) and S2 = (concat PS2 SS2) and | ||
| 3089 | SS1 = (unquote SS2)." | ||
| 3090 | (let* ((cs (comint--common-suffix s1 s2)) | ||
| 3091 | (ss1 (substring s1 (- (length s1) cs))) | ||
| 3092 | (qss1 (comint-quote-filename ss1)) | ||
| 3093 | qc s2b) | ||
| 3094 | (if (and (not (equal ss1 qss1)) | ||
| 3095 | (setq qc (comint-quote-filename (substring ss1 0 1))) | ||
| 3096 | (setq s2b (- (length s2) cs (length qc) -1)) | ||
| 3097 | (>= s2b 0) ;bug#11158. | ||
| 3098 | (eq t (compare-strings s2 s2b (- (length s2) cs -1) | ||
| 3099 | qc nil nil))) | ||
| 3100 | ;; The difference found is just that one char is quoted in S2 | ||
| 3101 | ;; but not in S1, keep looking before this difference. | ||
| 3102 | (comint--common-quoted-suffix | ||
| 3103 | (substring s1 0 (- (length s1) cs)) | ||
| 3104 | (substring s2 0 s2b)) | ||
| 3105 | (cons (substring s1 0 (- (length s1) cs)) | ||
| 3106 | (substring s2 0 (- (length s2) cs)))))) | ||
| 3107 | |||
| 3108 | (defun comint--table-subvert (table s1 s2 &optional quote-fun unquote-fun) | ||
| 3109 | "Completion table that replaces the prefix S1 with S2 in STRING. | ||
| 3110 | The result is a completion table which completes strings of the | ||
| 3111 | form (concat S1 S) in the same way as TABLE completes strings of | ||
| 3112 | the form (concat S2 S)." | ||
| 3113 | (lambda (string pred action) | ||
| 3114 | (let* ((str (if (eq t (compare-strings string 0 (length s1) s1 nil nil | ||
| 3115 | completion-ignore-case)) | ||
| 3116 | (let ((rest (substring string (length s1)))) | ||
| 3117 | (concat s2 (if unquote-fun | ||
| 3118 | (funcall unquote-fun rest) rest))))) | ||
| 3119 | (res (if str (complete-with-action action table str pred)))) | ||
| 3120 | (when res | ||
| 3121 | (cond | ||
| 3122 | ((and (eq (car-safe action) 'boundaries)) | ||
| 3123 | (let ((beg (or (and (eq (car-safe res) 'boundaries) (cadr res)) 0))) | ||
| 3124 | (list* 'boundaries | ||
| 3125 | (max (length s1) | ||
| 3126 | ;; FIXME: Adjust because of quoting/unquoting. | ||
| 3127 | (+ beg (- (length s1) (length s2)))) | ||
| 3128 | (and (eq (car-safe res) 'boundaries) (cddr res))))) | ||
| 3129 | ((stringp res) | ||
| 3130 | (if (eq t (compare-strings res 0 (length s2) s2 nil nil | ||
| 3131 | completion-ignore-case)) | ||
| 3132 | (let ((rest (substring res (length s2)))) | ||
| 3133 | (concat s1 (if quote-fun (funcall quote-fun rest) rest))))) | ||
| 3134 | ((eq action t) | ||
| 3135 | (let ((bounds (completion-boundaries str table pred ""))) | ||
| 3136 | (if (>= (car bounds) (length s2)) | ||
| 3137 | (if quote-fun (mapcar quote-fun res) res) | ||
| 3138 | (let ((re (concat "\\`" | ||
| 3139 | (regexp-quote (substring s2 (car bounds)))))) | ||
| 3140 | (delq nil | ||
| 3141 | (mapcar (lambda (c) | ||
| 3142 | (if (string-match re c) | ||
| 3143 | (let ((str (substring c (match-end 0)))) | ||
| 3144 | (if quote-fun | ||
| 3145 | (funcall quote-fun str) str)))) | ||
| 3146 | res)))))) | ||
| 3147 | ;; E.g. action=nil and it's the only completion. | ||
| 3148 | (res)))))) | ||
| 3149 | |||
| 3150 | (defun comint-completion-file-name-table (string pred action) | 3112 | (defun comint-completion-file-name-table (string pred action) |
| 3151 | (if (not (file-name-absolute-p string)) | 3113 | (if (not (file-name-absolute-p string)) |
| 3152 | (completion-file-name-table string pred action) | 3114 | (completion-file-name-table string pred action) |
| @@ -3165,6 +3127,13 @@ the form (concat S2 S)." | |||
| 3165 | res))) | 3127 | res))) |
| 3166 | (t (completion-file-name-table string pred action))))) | 3128 | (t (completion-file-name-table string pred action))))) |
| 3167 | 3129 | ||
| 3130 | (defvar comint-unquote-function #'comint--unquote-argument | ||
| 3131 | "Function to use for completion of quoted data. | ||
| 3132 | See `completion-table-with-quoting' and `comint-requote-function'.") | ||
| 3133 | (defvar comint-requote-function #'comint--requote-argument | ||
| 3134 | "Function to use for completion of quoted data. | ||
| 3135 | See `completion-table-with-quoting' and `comint-requote-function'.") | ||
| 3136 | |||
| 3168 | (defun comint--complete-file-name-data () | 3137 | (defun comint--complete-file-name-data () |
| 3169 | "Return the completion data for file name at point." | 3138 | "Return the completion data for file name at point." |
| 3170 | (let* ((filesuffix (cond ((not comint-completion-addsuffix) "") | 3139 | (let* ((filesuffix (cond ((not comint-completion-addsuffix) "") |
| @@ -3175,14 +3144,11 @@ the form (concat S2 S)." | |||
| 3175 | (filename (comint--match-partial-filename)) | 3144 | (filename (comint--match-partial-filename)) |
| 3176 | (filename-beg (if filename (match-beginning 0) (point))) | 3145 | (filename-beg (if filename (match-beginning 0) (point))) |
| 3177 | (filename-end (if filename (match-end 0) (point))) | 3146 | (filename-end (if filename (match-end 0) (point))) |
| 3178 | (unquoted (if filename (comint--unquote&expand-filename filename) "")) | ||
| 3179 | (table | 3147 | (table |
| 3180 | (let ((prefixes (comint--common-quoted-suffix | 3148 | (completion-table-with-quoting |
| 3181 | unquoted filename))) | 3149 | #'comint-completion-file-name-table |
| 3182 | (comint--table-subvert | 3150 | comint-unquote-function |
| 3183 | #'comint-completion-file-name-table | 3151 | comint-requote-function))) |
| 3184 | (cdr prefixes) (car prefixes) | ||
| 3185 | #'comint-quote-filename #'comint-unquote-filename)))) | ||
| 3186 | (nconc | 3152 | (nconc |
| 3187 | (list | 3153 | (list |
| 3188 | filename-beg filename-end | 3154 | filename-beg filename-end |
diff --git a/lisp/pcmpl-unix.el b/lisp/pcmpl-unix.el index 3af22c82dfb..ae4bd270b09 100644 --- a/lisp/pcmpl-unix.el +++ b/lisp/pcmpl-unix.el | |||
| @@ -205,8 +205,8 @@ Includes files as well as host names followed by a colon." | |||
| 205 | ;; Avoid connecting to the remote host when we're | 205 | ;; Avoid connecting to the remote host when we're |
| 206 | ;; only completing the host name. | 206 | ;; only completing the host name. |
| 207 | (list string) | 207 | (list string) |
| 208 | (comint--table-subvert (pcomplete-all-entries) | 208 | (completion-table-subvert (pcomplete-all-entries) |
| 209 | "" "/ssh:"))) | 209 | "" "/ssh:"))) |
| 210 | ((string-match "/" string) ; Local file name. | 210 | ((string-match "/" string) ; Local file name. |
| 211 | (pcomplete-all-entries)) | 211 | (pcomplete-all-entries)) |
| 212 | (t ;Host name or local file name. | 212 | (t ;Host name or local file name. |
diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el index cad2ffb2a2c..c9961a67f3d 100644 --- a/lisp/pcomplete.el +++ b/lisp/pcomplete.el | |||
| @@ -165,22 +165,8 @@ A non-nil value is useful if `pcomplete-autolist' is non-nil too." | |||
| 165 | :type 'boolean | 165 | :type 'boolean |
| 166 | :group 'pcomplete) | 166 | :group 'pcomplete) |
| 167 | 167 | ||
| 168 | (defcustom pcomplete-arg-quote-list nil | 168 | (define-obsolete-variable-alias |
| 169 | "List of characters to quote when completing an argument." | 169 | 'pcomplete-arg-quote-list 'comint-file-name-quote-list "24.2") |
| 170 | :type '(choice (repeat character) | ||
| 171 | (const :tag "Don't quote" nil)) | ||
| 172 | :group 'pcomplete) | ||
| 173 | |||
| 174 | (defcustom pcomplete-quote-arg-hook nil | ||
| 175 | "A hook which is run to quote a character within a filename. | ||
| 176 | Each function is passed both the filename to be quoted, and the index | ||
| 177 | to be considered. If the function wishes to provide an alternate | ||
| 178 | quoted form, it need only return the replacement string. If no | ||
| 179 | function provides a replacement, quoting shall proceed as normal, | ||
| 180 | using a backslash to quote any character which is a member of | ||
| 181 | `pcomplete-arg-quote-list'." | ||
| 182 | :type 'hook | ||
| 183 | :group 'pcomplete) | ||
| 184 | 170 | ||
| 185 | (defcustom pcomplete-man-function 'man | 171 | (defcustom pcomplete-man-function 'man |
| 186 | "A function to that will be called to display a manual page. | 172 | "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." | |||
| 370 | ;; it pretty much impossible to have completion other than | 356 | ;; it pretty much impossible to have completion other than |
| 371 | ;; prefix-completion. | 357 | ;; prefix-completion. |
| 372 | ;; | 358 | ;; |
| 373 | ;; pcomplete--common-quoted-suffix and comint--table-subvert try to | 359 | ;; pcomplete--common-suffix and completion-table-subvert try to work around |
| 374 | ;; work around this difficulty with heuristics, but it's | 360 | ;; this difficulty with heuristics, but it's really a hack. |
| 375 | ;; really a hack. | 361 | |
| 376 | 362 | (defvar pcomplete-unquote-argument-function #'comint--unquote-argument) | |
| 377 | (defvar pcomplete-unquote-argument-function nil) | 363 | |
| 378 | 364 | (defsubst pcomplete-unquote-argument (s) | |
| 379 | (defun pcomplete-unquote-argument (s) | 365 | (funcall pcomplete-unquote-argument-function s)) |
| 380 | (cond | 366 | |
| 381 | (pcomplete-unquote-argument-function | 367 | (defvar pcomplete-requote-argument-function #'comint--requote-argument) |
| 382 | (funcall pcomplete-unquote-argument-function s)) | 368 | |
| 383 | ((null pcomplete-arg-quote-list) s) | 369 | (defun pcomplete--common-suffix (s1 s2) |
| 384 | (t | 370 | ;; Since S2 is expected to be the "unquoted/expanded" version of S1, |
| 385 | (replace-regexp-in-string "\\\\\\(.\\)" "\\1" s t)))) | 371 | ;; there shouldn't be any case difference, even if the completion is |
| 386 | 372 | ;; case-insensitive. | |
| 387 | (defun pcomplete--common-quoted-suffix (s1 s2) | 373 | (let ((case-fold-search nil)) |
| 388 | ;; FIXME: Copied in comint.el. | 374 | (string-match |
| 389 | "Find the common suffix between S1 and S2 where S1 is the expanded S2. | 375 | ;; \x3FFF7F is just an arbitrary char among the ones Emacs accepts |
| 390 | S1 is expected to be the unquoted and expanded version of S2. | 376 | ;; that hopefully will never appear in normal text. |
| 391 | Returns (PS1 . PS2), i.e. the shortest prefixes of S1 and S2, such that | 377 | "\\(?:.\\|\n\\)*?\\(\\(?:.\\|\n\\)*\\)\x3FFF7F\\(?:.\\|\n\\)*\\1\\'" |
| 392 | S1 = (concat PS1 SS1) and S2 = (concat PS2 SS2) and | 378 | (concat s1 "\x3FFF7F" s2)) |
| 393 | SS1 = (unquote SS2)." | 379 | (- (match-end 1) (match-beginning 1)))) |
| 394 | (let* ((cs (comint--common-suffix s1 s2)) | 380 | |
| 395 | (ss1 (substring s1 (- (length s1) cs))) | ||
| 396 | (qss1 (pcomplete-quote-argument ss1)) | ||
| 397 | qc s2b) | ||
| 398 | (if (and (not (equal ss1 qss1)) | ||
| 399 | (setq qc (pcomplete-quote-argument (substring ss1 0 1))) | ||
| 400 | (setq s2b (- (length s2) cs (length qc) -1)) | ||
| 401 | (>= s2b 0) ;bug#11158. | ||
| 402 | (eq t (compare-strings s2 s2b (- (length s2) cs -1) | ||
| 403 | qc nil nil))) | ||
| 404 | ;; The difference found is just that one char is quoted in S2 | ||
| 405 | ;; but not in S1, keep looking before this difference. | ||
| 406 | (pcomplete--common-quoted-suffix | ||
| 407 | (substring s1 0 (- (length s1) cs)) | ||
| 408 | (substring s2 0 s2b)) | ||
| 409 | (cons (substring s1 0 (- (length s1) cs)) | ||
| 410 | (substring s2 0 (- (length s2) cs)))))) | ||
| 411 | |||
| 412 | ;; I don't think such commands are usable before first setting up buffer-local | ||
| 413 | ;; variables to parse args, so there's no point autoloading it. | ||
| 414 | ;; ;;;###autoload | ||
| 415 | (defun pcomplete-completions-at-point () | 381 | (defun pcomplete-completions-at-point () |
| 416 | "Provide standard completion using pcomplete's completion tables. | 382 | "Provide standard completion using pcomplete's completion tables. |
| 417 | Same as `pcomplete' but using the standard completion UI." | 383 | Same as `pcomplete' but using the standard completion UI." |
| @@ -442,34 +408,31 @@ Same as `pcomplete' but using the standard completion UI." | |||
| 442 | ;; pcomplete-stub and works from the buffer's text instead, | 408 | ;; pcomplete-stub and works from the buffer's text instead, |
| 443 | ;; we need to trick minibuffer-complete, into using | 409 | ;; we need to trick minibuffer-complete, into using |
| 444 | ;; pcomplete-stub without its knowledge. To that end, we | 410 | ;; pcomplete-stub without its knowledge. To that end, we |
| 445 | ;; use comint--table-subvert to construct a completion | 411 | ;; use completion-table-subvert to construct a completion |
| 446 | ;; table which expects strings using a prefix from the | 412 | ;; table which expects strings using a prefix from the |
| 447 | ;; buffer's text but internally uses the corresponding | 413 | ;; buffer's text but internally uses the corresponding |
| 448 | ;; prefix from pcomplete-stub. | 414 | ;; prefix from pcomplete-stub. |
| 449 | (beg (max (- (point) (length pcomplete-stub)) | 415 | (beg (max (- (point) (length pcomplete-stub)) |
| 450 | (pcomplete-begin))) | 416 | (pcomplete-begin))) |
| 451 | (buftext (buffer-substring beg (point)))) | 417 | (buftext (pcomplete-unquote-argument |
| 418 | (buffer-substring beg (point))))) | ||
| 452 | (when completions | 419 | (when completions |
| 453 | (let ((table | 420 | (let ((table |
| 454 | (cond | 421 | (completion-table-with-quoting |
| 455 | ((not (equal pcomplete-stub buftext)) | 422 | (if (equal pcomplete-stub buftext) |
| 456 | ;; This isn't always strictly right (e.g. if | 423 | completions |
| 457 | ;; FOO="toto/$FOO", then completion of /$FOO/bar may | 424 | ;; This may not always be strictly right, but given the lack |
| 458 | ;; result in something incorrect), but given the lack of | 425 | ;; of any other info, it's about as good as it gets, and in |
| 459 | ;; any other info, it's about as good as it gets, and in | 426 | ;; practice it should work just fine (fingers crossed). |
| 460 | ;; practice it should work just fine (fingers crossed). | 427 | (let ((suf-len (pcomplete--common-suffix |
| 461 | (let ((prefixes (pcomplete--common-quoted-suffix | ||
| 462 | pcomplete-stub buftext))) | 428 | pcomplete-stub buftext))) |
| 463 | (comint--table-subvert | 429 | (completion-table-subvert |
| 464 | completions (cdr prefixes) (car prefixes) | 430 | completions |
| 465 | #'pcomplete-quote-argument #'pcomplete-unquote-argument))) | 431 | (substring buftext 0 (- (length buftext) suf-len)) |
| 466 | (t | 432 | (substring pcomplete-stub 0 |
| 467 | (lambda (string pred action) | 433 | (- (length pcomplete-stub) suf-len))))) |
| 468 | (let ((res (complete-with-action | 434 | pcomplete-unquote-argument-function |
| 469 | action completions string pred))) | 435 | pcomplete-requote-argument-function)) |
| 470 | (if (stringp res) | ||
| 471 | (pcomplete-quote-argument res) | ||
| 472 | res)))))) | ||
| 473 | (pred | 436 | (pred |
| 474 | ;; Pare it down, if applicable. | 437 | ;; Pare it down, if applicable. |
| 475 | (when (and pcomplete-use-paring pcomplete-seen) | 438 | (when (and pcomplete-use-paring pcomplete-seen) |
| @@ -828,22 +791,8 @@ this is `comint-dynamic-complete-functions'." | |||
| 828 | (throw 'pcompleted t) | 791 | (throw 'pcompleted t) |
| 829 | pcomplete-args)))))) | 792 | pcomplete-args)))))) |
| 830 | 793 | ||
| 831 | (defun pcomplete-quote-argument (filename) | 794 | (define-obsolete-function-alias |
| 832 | "Return FILENAME with magic characters quoted. | 795 | 'pcomplete-quote-argument #'comint-quote-filename "24.2") |
| 833 | Magic characters are those in `pcomplete-arg-quote-list'." | ||
| 834 | (if (null pcomplete-arg-quote-list) | ||
| 835 | filename | ||
| 836 | (let ((index 0)) | ||
| 837 | (mapconcat (lambda (c) | ||
| 838 | (prog1 | ||
| 839 | (or (run-hook-with-args-until-success | ||
| 840 | 'pcomplete-quote-arg-hook filename index) | ||
| 841 | (when (memq c pcomplete-arg-quote-list) | ||
| 842 | (string ?\\ c)) | ||
| 843 | (char-to-string c)) | ||
| 844 | (setq index (1+ index)))) | ||
| 845 | filename | ||
| 846 | "")))) | ||
| 847 | 796 | ||
| 848 | ;; file-system completion lists | 797 | ;; file-system completion lists |
| 849 | 798 | ||
| @@ -1179,14 +1128,14 @@ Returns non-nil if a space was appended at the end." | |||
| 1179 | (if (not pcomplete-ignore-case) | 1128 | (if (not pcomplete-ignore-case) |
| 1180 | (insert-and-inherit (if raw-p | 1129 | (insert-and-inherit (if raw-p |
| 1181 | (substring entry (length stub)) | 1130 | (substring entry (length stub)) |
| 1182 | (pcomplete-quote-argument | 1131 | (comint-quote-filename |
| 1183 | (substring entry (length stub))))) | 1132 | (substring entry (length stub))))) |
| 1184 | ;; the stub is not quoted at this time, so to determine the | 1133 | ;; the stub is not quoted at this time, so to determine the |
| 1185 | ;; length of what should be in the buffer, we must quote it | 1134 | ;; length of what should be in the buffer, we must quote it |
| 1186 | ;; FIXME: Here we presume that quoting `stub' gives us the exact | 1135 | ;; FIXME: Here we presume that quoting `stub' gives us the exact |
| 1187 | ;; text in the buffer before point, which is not guaranteed; | 1136 | ;; text in the buffer before point, which is not guaranteed; |
| 1188 | ;; e.g. it is not the case in eshell when completing ${FOO}tm[TAB]. | 1137 | ;; e.g. it is not the case in eshell when completing ${FOO}tm[TAB]. |
| 1189 | (delete-char (- (length (pcomplete-quote-argument stub)))) | 1138 | (delete-char (- (length (comint-quote-filename stub)))) |
| 1190 | ;; if there is already a backslash present to handle the first | 1139 | ;; if there is already a backslash present to handle the first |
| 1191 | ;; character, don't bother quoting it | 1140 | ;; character, don't bother quoting it |
| 1192 | (when (eq (char-before) ?\\) | 1141 | (when (eq (char-before) ?\\) |
| @@ -1194,7 +1143,7 @@ Returns non-nil if a space was appended at the end." | |||
| 1194 | (setq entry (substring entry 1))) | 1143 | (setq entry (substring entry 1))) |
| 1195 | (insert-and-inherit (if raw-p | 1144 | (insert-and-inherit (if raw-p |
| 1196 | entry | 1145 | entry |
| 1197 | (pcomplete-quote-argument entry)))) | 1146 | (comint-quote-filename entry)))) |
| 1198 | (let (space-added) | 1147 | (let (space-added) |
| 1199 | (when (and (not (memq (char-before) pcomplete-suffix-list)) | 1148 | (when (and (not (memq (char-before) pcomplete-suffix-list)) |
| 1200 | addsuffix) | 1149 | addsuffix) |
| @@ -1204,7 +1153,7 @@ Returns non-nil if a space was appended at the end." | |||
| 1204 | pcomplete-last-completion-stub stub) | 1153 | pcomplete-last-completion-stub stub) |
| 1205 | space-added))) | 1154 | space-added))) |
| 1206 | 1155 | ||
| 1207 | ;; selection of completions | 1156 | ;; Selection of completions. |
| 1208 | 1157 | ||
| 1209 | (defun pcomplete-do-complete (stub completions) | 1158 | (defun pcomplete-do-complete (stub completions) |
| 1210 | "Dynamically complete at point using STUB and COMPLETIONS. | 1159 | "Dynamically complete at point using STUB and COMPLETIONS. |