1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306 |
- ;;; pcomplete.el --- programmable completion -*- lexical-binding: t -*-
- ;; Copyright (C) 1999-2015 Free Software Foundation, Inc.
- ;; Author: John Wiegley <johnw@gnu.org>
- ;; Keywords: processes abbrev
- ;; This file is part of GNU Emacs.
- ;; GNU Emacs is free software: you can redistribute it and/or modify
- ;; it under the terms of the GNU General Public License as published by
- ;; the Free Software Foundation, either version 3 of the License, or
- ;; (at your option) any later version.
- ;; GNU Emacs is distributed in the hope that it will be useful,
- ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ;; GNU General Public License for more details.
- ;; You should have received a copy of the GNU General Public License
- ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
- ;;; Commentary:
- ;; This module provides a programmable completion facility using
- ;; "completion functions". Each completion function is responsible
- ;; for producing a list of possible completions relevant to the current
- ;; argument position.
- ;;
- ;; To use pcomplete with shell-mode, for example, you will need the
- ;; following in your init file:
- ;;
- ;; (add-hook 'shell-mode-hook 'pcomplete-shell-setup)
- ;;
- ;; Most of the code below simply provides support mechanisms for
- ;; writing completion functions. Completion functions themselves are
- ;; very easy to write. They have few requirements beyond those of
- ;; regular Lisp functions.
- ;;
- ;; Consider the following example, which will complete against
- ;; filenames for the first two arguments, and directories for all
- ;; remaining arguments:
- ;;
- ;; (defun pcomplete/my-command ()
- ;; (pcomplete-here (pcomplete-entries))
- ;; (pcomplete-here (pcomplete-entries))
- ;; (while (pcomplete-here (pcomplete-dirs))))
- ;;
- ;; Here are the requirements for completion functions:
- ;;
- ;; @ They must be called "pcomplete/MAJOR-MODE/NAME", or
- ;; "pcomplete/NAME". This is how they are looked up, using the NAME
- ;; specified in the command argument (the argument in first
- ;; position).
- ;;
- ;; @ They must be callable with no arguments.
- ;;
- ;; @ Their return value is ignored. If they actually return normally,
- ;; it means no completions were available.
- ;;
- ;; @ In order to provide completions, they must throw the tag
- ;; `pcomplete-completions'. The value must be a completion table
- ;; (i.e. a table that can be passed to try-completion and friends)
- ;; for the final argument.
- ;;
- ;; @ To simplify completion function logic, the tag `pcompleted' may
- ;; be thrown with a value of nil in order to abort the function. It
- ;; means that there were no completions available.
- ;;
- ;; When a completion function is called, the variable `pcomplete-args'
- ;; is in scope, and contains all of the arguments specified on the
- ;; command line. The variable `pcomplete-last' is the index of the
- ;; last argument in that list.
- ;;
- ;; The variable `pcomplete-index' is used by the completion code to
- ;; know which argument the completion function is currently examining.
- ;; It always begins at 1, meaning the first argument after the command
- ;; name.
- ;;
- ;; To facilitate writing completion logic, a special macro,
- ;; `pcomplete-here', has been provided which does several things:
- ;;
- ;; 1. It will throw `pcompleted' (with a value of nil) whenever
- ;; `pcomplete-index' exceeds `pcomplete-last'.
- ;;
- ;; 2. It will increment `pcomplete-index' if the final argument has
- ;; not been reached yet.
- ;;
- ;; 3. It will evaluate the form passed to it, and throw the result
- ;; using the `pcomplete-completions' tag, if it is called when
- ;; `pcomplete-index' is pointing to the final argument.
- ;;
- ;; Sometimes a completion function will want to vary the possible
- ;; completions for an argument based on the previous one. To
- ;; facilitate tests like this, the function `pcomplete-test' and
- ;; `pcomplete-match' are provided. Called with one argument, they
- ;; test the value of the previous command argument. Otherwise, a
- ;; relative index may be given as an optional second argument, where 0
- ;; refers to the current argument, 1 the previous, 2 the one before
- ;; that, etc. The symbols `first' and `last' specify absolute
- ;; offsets.
- ;;
- ;; Here is an example which will only complete against directories for
- ;; the second argument if the first argument is also a directory:
- ;;
- ;; (defun pcomplete/example ()
- ;; (pcomplete-here (pcomplete-entries))
- ;; (if (pcomplete-test 'file-directory-p)
- ;; (pcomplete-here (pcomplete-dirs))
- ;; (pcomplete-here (pcomplete-entries))))
- ;;
- ;; For generating completion lists based on directory contents, see
- ;; the functions `pcomplete-entries', `pcomplete-dirs',
- ;; `pcomplete-executables' and `pcomplete-all-entries'.
- ;;
- ;; Consult the documentation for `pcomplete-here' for information
- ;; about its other arguments.
- ;;; Code:
- (require 'comint)
- (defgroup pcomplete nil
- "Programmable completion."
- :version "21.1"
- :group 'processes)
- ;;; User Variables:
- (defcustom pcomplete-file-ignore nil
- "A regexp of filenames to be disregarded during file completion."
- :type '(choice regexp (const :tag "None" nil))
- :group 'pcomplete)
- (defcustom pcomplete-dir-ignore nil
- "A regexp of names to be disregarded during directory completion."
- :type '(choice regexp (const :tag "None" nil))
- :group 'pcomplete)
- (defcustom pcomplete-ignore-case (memq system-type '(ms-dos windows-nt cygwin))
- ;; FIXME: the doc mentions file-name completion, but the code
- ;; seems to apply it to all completions.
- "If non-nil, ignore case when doing filename completion."
- :type 'boolean
- :group 'pcomplete)
- (defcustom pcomplete-autolist nil
- "If non-nil, automatically list possibilities on partial completion.
- This mirrors the optional behavior of tcsh."
- :type 'boolean
- :group 'pcomplete)
- (defcustom pcomplete-suffix-list (list ?/ ?:)
- "A list of characters which constitute a proper suffix."
- :type '(repeat character)
- :group 'pcomplete)
- (make-obsolete-variable 'pcomplete-suffix-list nil "24.1")
- (defcustom pcomplete-recexact nil
- "If non-nil, use shortest completion if characters cannot be added.
- This mirrors the optional behavior of tcsh.
- A non-nil value is useful if `pcomplete-autolist' is non-nil too."
- :type 'boolean
- :group 'pcomplete)
- (define-obsolete-variable-alias
- 'pcomplete-arg-quote-list 'comint-file-name-quote-list "24.3")
- (defcustom pcomplete-man-function 'man
- "A function to that will be called to display a manual page.
- It will be passed the name of the command to document."
- :type 'function
- :group 'pcomplete)
- (defcustom pcomplete-compare-entry-function 'string-lessp
- "This function is used to order file entries for completion.
- The behavior of most all shells is to sort alphabetically."
- :type '(radio (function-item string-lessp)
- (function-item file-newer-than-file-p)
- (function :tag "Other"))
- :group 'pcomplete)
- (defcustom pcomplete-help nil
- "A string or function (or nil) used for context-sensitive help.
- If a string, it should name an Info node that will be jumped to.
- If non-nil, it must a sexp that will be evaluated, and whose
- result will be shown in the minibuffer.
- If nil, the function `pcomplete-man-function' will be called with the
- current command argument."
- :type '(choice string sexp (const :tag "Use man page" nil))
- :group 'pcomplete)
- (defcustom pcomplete-expand-before-complete nil
- "If non-nil, expand the current argument before completing it.
- This means that typing something such as `$HOME/bi' followed by
- \\[pcomplete-argument] will cause the variable reference to be
- resolved first, and the resultant value that will be completed against
- to be inserted in the buffer. Note that exactly what gets expanded
- and how is entirely up to the behavior of the
- `pcomplete-parse-arguments-function'."
- :type 'boolean
- :group 'pcomplete)
- (defcustom pcomplete-parse-arguments-function
- 'pcomplete-parse-buffer-arguments
- "A function to call to parse the current line's arguments.
- It should be called with no parameters, and with point at the position
- of the argument that is to be completed.
- It must either return nil, or a cons cell of the form:
- ((ARG...) (BEG-POS...))
- The two lists must be identical in length. The first gives the final
- value of each command line argument (which need not match the textual
- representation of that argument), and BEG-POS gives the beginning
- position of each argument, as it is seen by the user. The establishes
- a relationship between the fully resolved value of the argument, and
- the textual representation of the argument."
- :type 'function
- :group 'pcomplete)
- (defcustom pcomplete-cycle-completions t
- "If non-nil, hitting the TAB key cycles through the completion list.
- Typical Emacs behavior is to complete as much as possible, then pause
- waiting for further input. Then if TAB is hit again, show a list of
- possible completions. When `pcomplete-cycle-completions' is non-nil,
- it acts more like zsh or 4nt, showing the first maximal match first,
- followed by any further matches on each subsequent pressing of the TAB
- key. \\[pcomplete-list] is the key to press if the user wants to see
- the list of possible completions."
- :type 'boolean
- :group 'pcomplete)
- (defcustom pcomplete-cycle-cutoff-length 5
- "If the number of completions is greater than this, don't cycle.
- This variable is a compromise between the traditional Emacs style of
- completion, and the \"cycling\" style. Basically, if there are more
- than this number of completions possible, don't automatically pick the
- first one and then expect the user to press TAB to cycle through them.
- Typically, when there are a large number of completion possibilities,
- the user wants to see them in a list buffer so that they can know what
- options are available. But if the list is small, it means the user
- has already entered enough input to disambiguate most of the
- possibilities, and therefore they are probably most interested in
- cycling through the candidates. Set this value to nil if you want
- cycling to always be enabled."
- :type '(choice integer (const :tag "Always cycle" nil))
- :group 'pcomplete)
- (defcustom pcomplete-restore-window-delay 1
- "The number of seconds to wait before restoring completion windows.
- Once the completion window has been displayed, if the user then goes
- on to type something else, that completion window will be removed from
- the display (actually, the original window configuration before it was
- displayed will be restored), after this many seconds of idle time. If
- set to nil, completion windows will be left on second until the user
- removes them manually. If set to 0, they will disappear immediately
- after the user enters a key other than TAB."
- :type '(choice integer (const :tag "Never restore" nil))
- :group 'pcomplete)
- (defcustom pcomplete-try-first-hook nil
- "A list of functions which are called before completing an argument.
- This can be used, for example, for completing things which might apply
- to all arguments, such as variable names after a $."
- :type 'hook
- :group 'pcomplete)
- (defsubst pcomplete-executables (&optional regexp)
- "Complete amongst a list of directories and executables."
- (pcomplete-entries regexp 'file-executable-p))
- (defcustom pcomplete-command-completion-function
- (function
- (lambda ()
- (pcomplete-here (pcomplete-executables))))
- "Function called for completing the initial command argument."
- :type 'function
- :group 'pcomplete)
- (defcustom pcomplete-command-name-function 'pcomplete-command-name
- "Function called for determining the current command name."
- :type 'function
- :group 'pcomplete)
- (defcustom pcomplete-default-completion-function
- (function
- (lambda ()
- (while (pcomplete-here (pcomplete-entries)))))
- "Function called when no completion rule can be found.
- This function is used to generate completions for every argument."
- :type 'function
- :group 'pcomplete)
- (defcustom pcomplete-use-paring t
- "If t, pare alternatives that have already been used.
- If nil, you will always see the completion set of possible options, no
- matter which of those options have already been used in previous
- command arguments."
- :type 'boolean
- :group 'pcomplete)
- (defcustom pcomplete-termination-string " "
- "A string that is inserted after any completion or expansion.
- This is usually a space character, useful when completing lists of
- words separated by spaces. However, if your list uses a different
- separator character, or if the completion occurs in a word that is
- already terminated by a character, this variable should be locally
- modified to be an empty string, or the desired separation string."
- :type 'string
- :group 'pcomplete)
- ;;; Internal Variables:
- ;; for cycling completion support
- (defvar pcomplete-current-completions nil)
- (defvar pcomplete-last-completion-length)
- (defvar pcomplete-last-completion-stub)
- (defvar pcomplete-last-completion-raw)
- (defvar pcomplete-last-window-config nil)
- (defvar pcomplete-window-restore-timer nil)
- (make-variable-buffer-local 'pcomplete-current-completions)
- (make-variable-buffer-local 'pcomplete-last-completion-length)
- (make-variable-buffer-local 'pcomplete-last-completion-stub)
- (make-variable-buffer-local 'pcomplete-last-completion-raw)
- (make-variable-buffer-local 'pcomplete-last-window-config)
- (make-variable-buffer-local 'pcomplete-window-restore-timer)
- ;; used for altering pcomplete's behavior. These global variables
- ;; should always be nil.
- (defvar pcomplete-show-help nil)
- (defvar pcomplete-show-list nil)
- (defvar pcomplete-expand-only-p nil)
- ;; for the sake of the bye-compiler, when compiling other files that
- ;; contain completion functions
- (defvar pcomplete-args nil)
- (defvar pcomplete-begins nil)
- (defvar pcomplete-last nil)
- (defvar pcomplete-index nil)
- (defvar pcomplete-stub nil)
- (defvar pcomplete-seen nil)
- (defvar pcomplete-norm-func nil)
- ;;; User Functions:
- ;;; Alternative front-end using the standard completion facilities.
- ;; The way pcomplete-parse-arguments, pcomplete-stub, and
- ;; pcomplete-quote-argument work only works because of some deep
- ;; hypothesis about the way the completion work. Basically, it makes
- ;; it pretty much impossible to have completion other than
- ;; prefix-completion.
- ;;
- ;; 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 #'comint--unquote-argument)
- (defsubst pcomplete-unquote-argument (s)
- (funcall pcomplete-unquote-argument-function s))
- (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))))
- (defun pcomplete-completions-at-point ()
- "Provide standard completion using pcomplete's completion tables.
- Same as `pcomplete' but using the standard completion UI."
- ;; FIXME: it only completes the text before point, whereas the
- ;; standard UI may also consider text after point.
- ;; FIXME: the `pcomplete' UI may be used internally during
- ;; pcomplete-completions and then throw to `pcompleted', thus
- ;; imposing the pcomplete UI over the standard UI.
- (catch 'pcompleted
- (let* ((pcomplete-stub)
- pcomplete-seen pcomplete-norm-func
- pcomplete-args pcomplete-last pcomplete-index
- (pcomplete-autolist pcomplete-autolist)
- (pcomplete-suffix-list pcomplete-suffix-list)
- ;; Apparently the vars above are global vars modified by
- ;; side-effects, whereas pcomplete-completions is the core
- ;; function that finds the chunk of text to complete
- ;; (returned indirectly in pcomplete-stub) and the set of
- ;; possible completions.
- (completions (pcomplete-completions))
- ;; Usually there's some close connection between pcomplete-stub
- ;; and the text before point. But depending on what
- ;; pcomplete-parse-arguments-function does, that connection
- ;; might not be that close. E.g. in eshell,
- ;; pcomplete-parse-arguments-function expands envvars.
- ;;
- ;; Since we use minibuffer-complete, which doesn't know
- ;; 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 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 (pcomplete-unquote-argument
- (buffer-substring beg (point)))))
- (when completions
- (let ((table
- (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)))
- (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)
- ;; Capture the dynbound values for later use.
- (let ((norm-func pcomplete-norm-func)
- (seen
- (mapcar (lambda (f)
- (funcall pcomplete-norm-func
- (directory-file-name f)))
- pcomplete-seen)))
- (lambda (f)
- (not (member
- (funcall norm-func (directory-file-name f))
- seen)))))))
- (when pcomplete-ignore-case
- (setq table (completion-table-case-fold table)))
- (list beg (point) table
- :predicate pred
- :exit-function
- ;; If completion is finished, add a terminating space.
- ;; We used to also do this if STATUS is `sole', but
- ;; that does not work right when completion cycling.
- (unless (zerop (length pcomplete-termination-string))
- (lambda (_s status)
- (when (eq status 'finished)
- (if (looking-at
- (regexp-quote pcomplete-termination-string))
- (goto-char (match-end 0))
- (insert pcomplete-termination-string)))))))))))
- ;; 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-std-complete ()
- (let ((data (pcomplete-completions-at-point)))
- (completion-in-region (nth 0 data) (nth 1 data) (nth 2 data)
- (plist-get :predicate (nthcdr 3 data)))))
- ;;; Pcomplete's native UI.
- ;;;###autoload
- (defun pcomplete (&optional interactively)
- "Support extensible programmable completion.
- To use this function, just bind the TAB key to it, or add it to your
- completion functions list (it should occur fairly early in the list)."
- (interactive "p")
- (if (and interactively
- pcomplete-cycle-completions
- pcomplete-current-completions
- (memq last-command '(pcomplete
- pcomplete-expand-and-complete
- pcomplete-reverse)))
- (progn
- (delete-char (- pcomplete-last-completion-length))
- (if (eq this-command 'pcomplete-reverse)
- (progn
- (push (car (last pcomplete-current-completions))
- pcomplete-current-completions)
- (setcdr (last pcomplete-current-completions 2) nil))
- (nconc pcomplete-current-completions
- (list (car pcomplete-current-completions)))
- (setq pcomplete-current-completions
- (cdr pcomplete-current-completions)))
- (pcomplete-insert-entry pcomplete-last-completion-stub
- (car pcomplete-current-completions)
- nil pcomplete-last-completion-raw))
- (setq pcomplete-current-completions nil
- pcomplete-last-completion-raw nil)
- (catch 'pcompleted
- (let* ((pcomplete-stub)
- pcomplete-seen pcomplete-norm-func
- pcomplete-args pcomplete-last pcomplete-index
- (pcomplete-autolist pcomplete-autolist)
- (pcomplete-suffix-list pcomplete-suffix-list)
- (completions (pcomplete-completions))
- (result (pcomplete-do-complete pcomplete-stub completions)))
- (and result
- (not (eq (car result) 'listed))
- (cdr result)
- (pcomplete-insert-entry pcomplete-stub (cdr result)
- (memq (car result)
- '(sole shortest))
- pcomplete-last-completion-raw))))))
- ;;;###autoload
- (defun pcomplete-reverse ()
- "If cycling completion is in use, cycle backwards."
- (interactive)
- (call-interactively 'pcomplete))
- ;;;###autoload
- (defun pcomplete-expand-and-complete ()
- "Expand the textual value of the current argument.
- This will modify the current buffer."
- (interactive)
- (let ((pcomplete-expand-before-complete t))
- (pcomplete)))
- ;;;###autoload
- (defun pcomplete-continue ()
- "Complete without reference to any cycling completions."
- (interactive)
- (setq pcomplete-current-completions nil
- pcomplete-last-completion-raw nil)
- (call-interactively 'pcomplete))
- ;;;###autoload
- (defun pcomplete-expand ()
- "Expand the textual value of the current argument.
- This will modify the current buffer."
- (interactive)
- (let ((pcomplete-expand-before-complete t)
- (pcomplete-expand-only-p t))
- (pcomplete)
- (when (and pcomplete-current-completions
- (> (length pcomplete-current-completions) 0)) ;??
- (delete-char (- pcomplete-last-completion-length))
- (while pcomplete-current-completions
- (unless (pcomplete-insert-entry
- "" (car pcomplete-current-completions) t
- pcomplete-last-completion-raw)
- (insert-and-inherit pcomplete-termination-string))
- (setq pcomplete-current-completions
- (cdr pcomplete-current-completions))))))
- ;;;###autoload
- (defun pcomplete-help ()
- "Display any help information relative to the current argument."
- (interactive)
- (let ((pcomplete-show-help t))
- (pcomplete)))
- ;;;###autoload
- (defun pcomplete-list ()
- "Show the list of possible completions for the current argument."
- (interactive)
- (when (and pcomplete-cycle-completions
- pcomplete-current-completions
- (eq last-command 'pcomplete-argument))
- (delete-char (- pcomplete-last-completion-length))
- (setq pcomplete-current-completions nil
- pcomplete-last-completion-raw nil))
- (let ((pcomplete-show-list t))
- (pcomplete)))
- ;;; Internal Functions:
- ;; argument handling
- (defun pcomplete-arg (&optional index offset)
- "Return the textual content of the INDEXth argument.
- INDEX is based from the current processing position. If INDEX is
- positive, values returned are closer to the command argument; if
- negative, they are closer to the last argument. If the INDEX is
- outside of the argument list, nil is returned. The default value for
- INDEX is 0, meaning the current argument being examined.
- The special indices `first' and `last' may be used to access those
- parts of the list.
- The OFFSET argument is added to/taken away from the index that will be
- used. This is really only useful with `first' and `last', for
- accessing absolute argument positions."
- (setq index
- (if (eq index 'first)
- 0
- (if (eq index 'last)
- pcomplete-last
- (- pcomplete-index (or index 0)))))
- (if offset
- (setq index (+ index offset)))
- (nth index pcomplete-args))
- (defun pcomplete-begin (&optional index offset)
- "Return the beginning position of the INDEXth argument.
- See the documentation for `pcomplete-arg'."
- (setq index
- (if (eq index 'first)
- 0
- (if (eq index 'last)
- pcomplete-last
- (- pcomplete-index (or index 0)))))
- (if offset
- (setq index (+ index offset)))
- (nth index pcomplete-begins))
- (defsubst pcomplete-actual-arg (&optional index offset)
- "Return the actual text representation of the last argument.
- This is different from `pcomplete-arg', which returns the textual value
- that the last argument evaluated to. This function returns what the
- user actually typed in."
- (buffer-substring (pcomplete-begin index offset) (point)))
- (defsubst pcomplete-next-arg ()
- "Move the various pointers to the next argument."
- (setq pcomplete-index (1+ pcomplete-index)
- pcomplete-stub (pcomplete-arg))
- (if (> pcomplete-index pcomplete-last)
- (progn
- (message "No completions")
- (throw 'pcompleted nil))))
- (defun pcomplete-command-name ()
- "Return the command name of the first argument."
- (file-name-nondirectory (pcomplete-arg 'first)))
- (defun pcomplete-match (regexp &optional index offset start)
- "Like `string-match', but on the current completion argument."
- (let ((arg (pcomplete-arg (or index 1) offset)))
- (if arg
- (string-match regexp arg start)
- (throw 'pcompleted nil))))
- (defun pcomplete-match-string (which &optional index offset)
- "Like `match-string', but on the current completion argument."
- (let ((arg (pcomplete-arg (or index 1) offset)))
- (if arg
- (match-string which arg)
- (throw 'pcompleted nil))))
- (defalias 'pcomplete-match-beginning 'match-beginning)
- (defalias 'pcomplete-match-end 'match-end)
- (defsubst pcomplete--test (pred arg)
- "Perform a programmable completion predicate match."
- (and pred
- (cond ((eq pred t) t)
- ((functionp pred)
- (funcall pred arg))
- ((stringp pred)
- (string-match (concat "^" pred "$") arg)))
- pred))
- (defun pcomplete-test (predicates &optional index offset)
- "Predicates to test the current programmable argument with."
- (let ((arg (pcomplete-arg (or index 1) offset)))
- (unless (null predicates)
- (if (not (listp predicates))
- (pcomplete--test predicates arg)
- (let ((pred predicates)
- found)
- (while (and pred (not found))
- (setq found (pcomplete--test (car pred) arg)
- pred (cdr pred)))
- found)))))
- (defun pcomplete-parse-buffer-arguments ()
- "Parse whitespace separated arguments in the current region."
- (let ((begin (point-min))
- (end (point-max))
- begins args)
- (save-excursion
- (goto-char begin)
- (while (< (point) end)
- (skip-chars-forward " \t\n")
- (push (point) begins)
- (skip-chars-forward "^ \t\n")
- (push (buffer-substring-no-properties
- (car begins) (point))
- args))
- (cons (nreverse args) (nreverse begins)))))
- ;;;###autoload
- (defun pcomplete-comint-setup (completef-sym)
- "Setup a comint buffer to use pcomplete.
- COMPLETEF-SYM should be the symbol where the
- dynamic-complete-functions are kept. For comint mode itself,
- this is `comint-dynamic-complete-functions'."
- (set (make-local-variable 'pcomplete-parse-arguments-function)
- 'pcomplete-parse-comint-arguments)
- (add-hook 'completion-at-point-functions
- 'pcomplete-completions-at-point nil 'local)
- (set (make-local-variable completef-sym)
- (copy-sequence (symbol-value completef-sym)))
- (let* ((funs (symbol-value completef-sym))
- (elem (or (memq 'comint-filename-completion funs)
- (memq 'shell-filename-completion funs)
- (memq 'shell-dynamic-complete-filename funs)
- (memq 'comint-dynamic-complete-filename funs))))
- (if elem
- (setcar elem 'pcomplete)
- (add-to-list completef-sym 'pcomplete))))
- ;;;###autoload
- (defun pcomplete-shell-setup ()
- "Setup `shell-mode' to use pcomplete."
- ;; FIXME: insufficient
- (pcomplete-comint-setup 'comint-dynamic-complete-functions))
- (declare-function comint-bol "comint" (&optional arg))
- (defun pcomplete-parse-comint-arguments ()
- "Parse whitespace separated arguments in the current region."
- (declare (obsolete comint-parse-pcomplete-arguments "24.1"))
- (let ((begin (save-excursion (comint-bol nil) (point)))
- (end (point))
- begins args)
- (save-excursion
- (goto-char begin)
- (while (< (point) end)
- (skip-chars-forward " \t\n")
- (push (point) begins)
- (while
- (progn
- (skip-chars-forward "^ \t\n\\")
- (when (eq (char-after) ?\\)
- (forward-char 1)
- (unless (eolp)
- (forward-char 1)
- t))))
- (push (buffer-substring-no-properties (car begins) (point))
- args))
- (cons (nreverse args) (nreverse begins)))))
- (defun pcomplete-parse-arguments (&optional expand-p)
- "Parse the command line arguments. Most completions need this info."
- (let ((results (funcall pcomplete-parse-arguments-function)))
- (when results
- (setq pcomplete-args (or (car results) (list ""))
- pcomplete-begins (or (cdr results) (list (point)))
- pcomplete-last (1- (length pcomplete-args))
- pcomplete-index 0
- pcomplete-stub (pcomplete-arg 'last))
- (let ((begin (pcomplete-begin 'last)))
- (if (and (listp pcomplete-stub) ;??
- (not pcomplete-expand-only-p))
- (let* ((completions pcomplete-stub) ;??
- (common-stub (car completions))
- (c completions)
- (len (length common-stub)))
- (while (and c (> len 0))
- (while (and (> len 0)
- (not (string=
- (substring common-stub 0 len)
- (substring (car c) 0
- (min (length (car c))
- len)))))
- (setq len (1- len)))
- (setq c (cdr c)))
- (setq pcomplete-stub (substring common-stub 0 len)
- pcomplete-autolist t)
- (when (and begin (not pcomplete-show-list))
- (delete-region begin (point))
- (pcomplete-insert-entry "" pcomplete-stub))
- (throw 'pcomplete-completions completions))
- (when expand-p
- (if (stringp pcomplete-stub)
- (when begin
- (delete-region begin (point))
- (insert-and-inherit pcomplete-stub))
- (if (and (listp pcomplete-stub)
- pcomplete-expand-only-p)
- ;; this is for the benefit of `pcomplete-expand'
- (setq pcomplete-last-completion-length (- (point) begin)
- pcomplete-current-completions pcomplete-stub)
- (error "Cannot expand argument"))))
- (if pcomplete-expand-only-p
- (throw 'pcompleted t)
- pcomplete-args))))))
- (define-obsolete-function-alias
- 'pcomplete-quote-argument #'comint-quote-filename "24.3")
- ;; file-system completion lists
- (defsubst pcomplete-dirs-or-entries (&optional regexp predicate)
- "Return either directories, or qualified entries."
- (pcomplete-entries
- nil
- (lambda (f)
- (or (file-directory-p f)
- (and (or (null regexp) (string-match regexp f))
- (or (null predicate) (funcall predicate f)))))))
- (defun pcomplete--entries (&optional regexp predicate)
- "Like `pcomplete-entries' but without env-var handling."
- (let* ((ign-pred
- (when (or pcomplete-file-ignore pcomplete-dir-ignore)
- ;; Capture the dynbound value for later use.
- (let ((file-ignore pcomplete-file-ignore)
- (dir-ignore pcomplete-dir-ignore))
- (lambda (file)
- (not
- (if (eq (aref file (1- (length file))) ?/)
- (and dir-ignore (string-match dir-ignore file))
- (and file-ignore (string-match file-ignore file))))))))
- (reg-pred (if regexp (lambda (file) (string-match regexp file))))
- (pred (cond
- ((null (or ign-pred reg-pred)) predicate)
- ((null (or ign-pred predicate)) reg-pred)
- ((null (or reg-pred predicate)) ign-pred)
- (t (lambda (f)
- (and (or (null reg-pred) (funcall reg-pred f))
- (or (null ign-pred) (funcall ign-pred f))
- (or (null predicate) (funcall predicate f))))))))
- (lambda (s p a)
- (if (and (eq a 'metadata) pcomplete-compare-entry-function)
- `(metadata (cycle-sort-function
- . ,(lambda (comps)
- (sort comps pcomplete-compare-entry-function)))
- ,@(cdr (completion-file-name-table s p a)))
- (let ((completion-ignored-extensions nil)
- (completion-ignore-case pcomplete-ignore-case))
- (completion-table-with-predicate
- #'comint-completion-file-name-table pred 'strict s p a))))))
- (defconst pcomplete--env-regexp
- "\\(?:\\`\\|[^\\]\\)\\(?:\\\\\\\\\\)*\\(\\$\\(?:{\\([^}]+\\)}\\|\\(?2:[[:alnum:]_]+\\)\\)\\)")
- (defun pcomplete-entries (&optional regexp predicate)
- "Complete against a list of directory candidates.
- If REGEXP is non-nil, it is a regular expression used to refine the
- match (files not matching the REGEXP will be excluded).
- If PREDICATE is non-nil, it will also be used to refine the match
- \(files for which the PREDICATE returns nil will be excluded).
- If no directory information can be extracted from the completed
- component, `default-directory' is used as the basis for completion."
- ;; FIXME: The old code did env-var expansion here, so we reproduce this
- ;; behavior for now, but really env-var handling should be performed globally
- ;; rather than here since it also applies to non-file arguments.
- (let ((table (pcomplete--entries regexp predicate)))
- (lambda (string pred action)
- (let ((strings nil)
- (orig-length (length string)))
- ;; Perform env-var expansion.
- (while (string-match pcomplete--env-regexp string)
- (push (substring string 0 (match-beginning 1)) strings)
- (push (getenv (match-string 2 string)) strings)
- (setq string (substring string (match-end 1))))
- (if (not (and strings
- (or (eq action t)
- (eq (car-safe action) 'boundaries))))
- (let ((newstring
- (mapconcat 'identity (nreverse (cons string strings)) "")))
- ;; FIXME: We could also try to return unexpanded envvars.
- (complete-with-action action table newstring pred))
- (let* ((envpos (apply #'+ (mapcar #' length strings)))
- (newstring
- (mapconcat 'identity (nreverse (cons string strings)) ""))
- (bounds (completion-boundaries newstring table pred
- (or (cdr-safe action) ""))))
- (if (>= (car bounds) envpos)
- ;; The env-var is "out of bounds".
- (if (eq action t)
- (complete-with-action action table newstring pred)
- `(boundaries
- ,(+ (car bounds) (- orig-length (length newstring)))
- . ,(cdr bounds)))
- ;; The env-var is in the file bounds.
- (if (eq action t)
- (let ((comps (complete-with-action
- action table newstring pred))
- (len (- envpos (car bounds))))
- ;; Strip the part of each completion that's actually
- ;; coming from the env-var.
- (mapcar (lambda (s) (substring s len)) comps))
- `(boundaries
- ,(+ envpos (- orig-length (length newstring)))
- . ,(cdr bounds))))))))))
- (defsubst pcomplete-all-entries (&optional regexp predicate)
- "Like `pcomplete-entries', but doesn't ignore any entries."
- (let (pcomplete-file-ignore
- pcomplete-dir-ignore)
- (pcomplete-entries regexp predicate)))
- (defsubst pcomplete-dirs (&optional regexp)
- "Complete amongst a list of directories."
- (pcomplete-entries regexp 'file-directory-p))
- ;; generation of completion lists
- (defun pcomplete-find-completion-function (command)
- "Find the completion function to call for the given COMMAND."
- (let ((sym (intern-soft
- (concat "pcomplete/" (symbol-name major-mode) "/" command))))
- (unless sym
- (setq sym (intern-soft (concat "pcomplete/" command))))
- (and sym (fboundp sym) sym)))
- (defun pcomplete-completions ()
- "Return a list of completions for the current argument position."
- (catch 'pcomplete-completions
- (when (pcomplete-parse-arguments pcomplete-expand-before-complete)
- (if (= pcomplete-index pcomplete-last)
- (funcall pcomplete-command-completion-function)
- (let ((sym (or (pcomplete-find-completion-function
- (funcall pcomplete-command-name-function))
- pcomplete-default-completion-function)))
- (ignore
- (pcomplete-next-arg)
- (funcall sym)))))))
- (defun pcomplete-opt (options &optional prefix _no-ganging _args-follow)
- "Complete a set of OPTIONS, each beginning with PREFIX (?- by default).
- PREFIX may be t, in which case no PREFIX character is necessary.
- If NO-GANGING is non-nil, each option is separate (-xy is not allowed).
- If ARGS-FOLLOW is non-nil, then options which take arguments may have
- the argument appear after a ganged set of options. This is how tar
- behaves, for example.
- Arguments NO-GANGING and ARGS-FOLLOW are currently ignored."
- (if (and (= pcomplete-index pcomplete-last)
- (string= (pcomplete-arg) "-"))
- (let ((len (length options))
- (index 0)
- char choices)
- (while (< index len)
- (setq char (aref options index))
- (if (eq char ?\()
- (let ((result (read-from-string options index)))
- (setq index (cdr result)))
- (unless (memq char '(?/ ?* ?? ?.))
- (push (char-to-string char) choices))
- (setq index (1+ index))))
- (throw 'pcomplete-completions
- (mapcar
- (function
- (lambda (opt)
- (concat "-" opt)))
- (pcomplete-uniqify-list choices))))
- (let ((arg (pcomplete-arg)))
- (when (and (> (length arg) 1)
- (stringp arg)
- (eq (aref arg 0) (or prefix ?-)))
- (pcomplete-next-arg)
- (let ((char (aref arg 1))
- (len (length options))
- (index 0)
- opt-char arg-char result)
- (while (< (1+ index) len)
- (setq opt-char (aref options index)
- arg-char (aref options (1+ index)))
- (if (eq arg-char ?\()
- (setq result
- (read-from-string options (1+ index))
- index (cdr result)
- result (car result))
- (setq result nil))
- (when (and (eq char opt-char)
- (memq arg-char '(?\( ?/ ?* ?? ?.)))
- (if (< pcomplete-index pcomplete-last)
- (pcomplete-next-arg)
- (throw 'pcomplete-completions
- (cond ((eq arg-char ?/) (pcomplete-dirs))
- ((eq arg-char ?*) (pcomplete-executables))
- ((eq arg-char ??) nil)
- ((eq arg-char ?.) (pcomplete-entries))
- ((eq arg-char ?\() (eval result))))))
- (setq index (1+ index))))))))
- (defun pcomplete--here (&optional form stub paring form-only)
- "Complete against the current argument, if at the end.
- See the documentation for `pcomplete-here'."
- (if (< pcomplete-index pcomplete-last)
- (progn
- (if (eq paring 0)
- (setq pcomplete-seen nil)
- (unless (eq paring t)
- (let ((arg (pcomplete-arg)))
- (when (stringp arg)
- (push (if paring
- (funcall paring arg)
- (file-truename arg))
- pcomplete-seen)))))
- (pcomplete-next-arg)
- t)
- (when pcomplete-show-help
- (pcomplete--help)
- (throw 'pcompleted t))
- (if stub
- (setq pcomplete-stub stub))
- (if (or (eq paring t) (eq paring 0))
- (setq pcomplete-seen nil)
- (setq pcomplete-norm-func (or paring 'file-truename)))
- (unless form-only
- (run-hooks 'pcomplete-try-first-hook))
- (throw 'pcomplete-completions
- (if (functionp form)
- (funcall form)
- ;; Old calling convention, might still be used by files
- ;; byte-compiled with the older code.
- (eval form)))))
- (defmacro pcomplete-here (&optional form stub paring form-only)
- "Complete against the current argument, if at the end.
- If completion is to be done here, evaluate FORM to generate the completion
- table which will be used for completion purposes. If STUB is a
- string, use it as the completion stub instead of the default (which is
- the entire text of the current argument).
- For an example of when you might want to use STUB: if the current
- argument text is `long-path-name/', you don't want the completions
- list display to be cluttered by `long-path-name/' appearing at the
- beginning of every alternative. Not only does this make things less
- intelligible, but it is also inefficient. Yet, if the completion list
- does not begin with this string for every entry, the current argument
- won't complete correctly.
- The solution is to specify a relative stub. It allows you to
- substitute a different argument from the current argument, almost
- always for the sake of efficiency.
- If PARING is nil, this argument will be pared against previous
- arguments using the function `file-truename' to normalize them.
- PARING may be a function, in which case that function is used for
- normalization. If PARING is t, the argument dealt with by this
- call will not participate in argument paring. If it is the
- integer 0, all previous arguments that have been seen will be
- cleared.
- If FORM-ONLY is non-nil, only the result of FORM will be used to
- generate the completions list. This means that the hook
- `pcomplete-try-first-hook' will not be run."
- (declare (debug t))
- `(pcomplete--here (lambda () ,form) ,stub ,paring ,form-only))
- (defmacro pcomplete-here* (&optional form stub form-only)
- "An alternate form which does not participate in argument paring."
- (declare (debug t))
- `(pcomplete-here ,form ,stub t ,form-only))
- ;; display support
- (defun pcomplete-restore-windows ()
- "If the only window change was due to Completions, restore things."
- (if pcomplete-last-window-config
- (let* ((cbuf (get-buffer "*Completions*"))
- (cwin (and cbuf (get-buffer-window cbuf))))
- (when (window-live-p cwin)
- (bury-buffer cbuf)
- (set-window-configuration pcomplete-last-window-config))))
- (setq pcomplete-last-window-config nil
- pcomplete-window-restore-timer nil))
- ;; Abstractions so that the code below will work for both Emacs 20 and
- ;; XEmacs 21
- (defalias 'pcomplete-event-matches-key-specifier-p
- (if (featurep 'xemacs)
- 'event-matches-key-specifier-p
- 'eq))
- (defun pcomplete-read-event (&optional prompt)
- (if (fboundp 'read-event)
- (read-event prompt)
- (aref (read-key-sequence prompt) 0)))
- (defun pcomplete-show-completions (completions)
- "List in help buffer sorted COMPLETIONS.
- Typing SPC flushes the help buffer."
- (when pcomplete-window-restore-timer
- (cancel-timer pcomplete-window-restore-timer)
- (setq pcomplete-window-restore-timer nil))
- (unless pcomplete-last-window-config
- (setq pcomplete-last-window-config (current-window-configuration)))
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list completions))
- (minibuffer-message "Hit space to flush")
- (let (event)
- (prog1
- (catch 'done
- (while (with-current-buffer (get-buffer "*Completions*")
- (setq event (pcomplete-read-event)))
- (cond
- ((pcomplete-event-matches-key-specifier-p event ?\s)
- (set-window-configuration pcomplete-last-window-config)
- (setq pcomplete-last-window-config nil)
- (throw 'done nil))
- ((or (pcomplete-event-matches-key-specifier-p event 'tab)
- ;; Needed on a terminal
- (pcomplete-event-matches-key-specifier-p event 9))
- (let ((win (or (get-buffer-window "*Completions*" 0)
- (display-buffer "*Completions*"
- 'not-this-window))))
- (with-selected-window win
- (if (pos-visible-in-window-p (point-max))
- (goto-char (point-min))
- (scroll-up))))
- (message ""))
- (t
- (push event unread-command-events)
- (throw 'done nil)))))
- (if (and pcomplete-last-window-config
- pcomplete-restore-window-delay)
- (setq pcomplete-window-restore-timer
- (run-with-timer pcomplete-restore-window-delay nil
- 'pcomplete-restore-windows))))))
- ;; insert completion at point
- (defun pcomplete-insert-entry (stub entry &optional addsuffix raw-p)
- "Insert a completion entry at point.
- Returns non-nil if a space was appended at the end."
- (let ((here (point)))
- (if (not pcomplete-ignore-case)
- (insert-and-inherit (if raw-p
- (substring entry (length stub))
- (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 (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) ?\\)
- (insert-and-inherit (substring entry 0 1))
- (setq entry (substring entry 1)))
- (insert-and-inherit (if raw-p
- entry
- (comint-quote-filename entry))))
- (let (space-added)
- (when (and (not (memq (char-before) pcomplete-suffix-list))
- addsuffix)
- (insert-and-inherit pcomplete-termination-string)
- (setq space-added t))
- (setq pcomplete-last-completion-length (- (point) here)
- pcomplete-last-completion-stub stub)
- space-added)))
- ;; Selection of completions.
- (defun pcomplete-do-complete (stub completions)
- "Dynamically complete at point using STUB and COMPLETIONS.
- This is basically just a wrapper for `pcomplete-stub' which does some
- extra checking, and munging of the COMPLETIONS list."
- (unless (stringp stub)
- (message "Cannot complete argument")
- (throw 'pcompleted nil))
- (if (null completions)
- (ignore
- (if (and stub (> (length stub) 0))
- (message "No completions of %s" stub)
- (message "No completions")))
- ;; pare it down, if applicable
- (when (and pcomplete-use-paring pcomplete-seen)
- (setq pcomplete-seen
- (mapcar 'directory-file-name pcomplete-seen))
- (dolist (p pcomplete-seen)
- (add-to-list 'pcomplete-seen
- (funcall pcomplete-norm-func p)))
- (setq completions
- (apply-partially 'completion-table-with-predicate
- completions
- (when pcomplete-seen
- (lambda (f)
- (not (member
- (funcall pcomplete-norm-func
- (directory-file-name f))
- pcomplete-seen))))
- 'strict)))
- ;; OK, we've got a list of completions.
- (if pcomplete-show-list
- ;; FIXME: pay attention to boundaries.
- (pcomplete-show-completions (all-completions stub completions))
- (pcomplete-stub stub completions))))
- (defun pcomplete-stub (stub candidates &optional cycle-p)
- "Dynamically complete STUB from CANDIDATES list.
- This function inserts completion characters at point by completing
- STUB from the strings in CANDIDATES. A completions listing may be
- shown in a help buffer if completion is ambiguous.
- Returns nil if no completion was inserted.
- Returns `sole' if completed with the only completion match.
- Returns `shortest' if completed with the shortest of the matches.
- Returns `partial' if completed as far as possible with the matches.
- Returns `listed' if a completion listing was shown.
- See also `pcomplete-filename'."
- (let* ((completion-ignore-case pcomplete-ignore-case)
- (completions (all-completions stub candidates))
- (entry (try-completion stub candidates))
- result)
- (cond
- ((null entry)
- (if (and stub (> (length stub) 0))
- (message "No completions of %s" stub)
- (message "No completions")))
- ((eq entry t)
- (setq entry stub)
- (message "Sole completion")
- (setq result 'sole))
- ((= 1 (length completions))
- (setq result 'sole))
- ((and pcomplete-cycle-completions
- (or cycle-p
- (not pcomplete-cycle-cutoff-length)
- (<= (length completions)
- pcomplete-cycle-cutoff-length)))
- (let ((bound (car (completion-boundaries stub candidates nil ""))))
- (unless (zerop bound)
- (setq completions (mapcar (lambda (c) (concat (substring stub 0 bound) c))
- completions)))
- (setq entry (car completions)
- pcomplete-current-completions completions)))
- ((and pcomplete-recexact
- (string-equal stub entry)
- (member entry completions))
- ;; It's not unique, but user wants shortest match.
- (message "Completed shortest")
- (setq result 'shortest))
- ((or pcomplete-autolist
- (string-equal stub entry))
- ;; It's not unique, list possible completions.
- ;; FIXME: pay attention to boundaries.
- (pcomplete-show-completions completions)
- (setq result 'listed))
- (t
- (message "Partially completed")
- (setq result 'partial)))
- (cons result entry)))
- ;; context sensitive help
- (defun pcomplete--help ()
- "Produce context-sensitive help for the current argument.
- If specific documentation can't be given, be generic."
- (if (and pcomplete-help
- (or (and (stringp pcomplete-help)
- (fboundp 'Info-goto-node))
- (listp pcomplete-help)))
- (if (listp pcomplete-help)
- (message "%s" (eval pcomplete-help))
- (save-window-excursion (info))
- (switch-to-buffer-other-window "*info*")
- (funcall (symbol-function 'Info-goto-node) pcomplete-help))
- (if pcomplete-man-function
- (let ((cmd (funcall pcomplete-command-name-function)))
- (if (and cmd (> (length cmd) 0))
- (funcall pcomplete-man-function cmd)))
- (message "No context-sensitive help available"))))
- ;; general utilities
- (defun pcomplete-uniqify-list (l)
- "Sort and remove multiples in L."
- (setq l (sort l 'string-lessp))
- (let ((m l))
- (while m
- (while (and (cdr m)
- (string= (car m)
- (cadr m)))
- (setcdr m (cddr m)))
- (setq m (cdr m))))
- l)
- (defun pcomplete-process-result (cmd &rest args)
- "Call CMD using `call-process' and return the simplest result."
- (with-temp-buffer
- (apply 'call-process cmd nil t nil args)
- (skip-chars-backward "\n")
- (buffer-substring (point-min) (point))))
- ;; create a set of aliases which allow completion functions to be not
- ;; quite so verbose
- ;;; jww (1999-10-20): are these a good idea?
- ;; (defalias 'pc-here 'pcomplete-here)
- ;; (defalias 'pc-test 'pcomplete-test)
- ;; (defalias 'pc-opt 'pcomplete-opt)
- ;; (defalias 'pc-match 'pcomplete-match)
- ;; (defalias 'pc-match-string 'pcomplete-match-string)
- ;; (defalias 'pc-match-beginning 'pcomplete-match-beginning)
- ;; (defalias 'pc-match-end 'pcomplete-match-end)
- (provide 'pcomplete)
- ;;; pcomplete.el ends here
|