diff options
| author | Simon Marshall | 1995-04-03 13:06:25 +0000 |
|---|---|---|
| committer | Simon Marshall | 1995-04-03 13:06:25 +0000 |
| commit | 59f36b08082a7ef690cdcfe16fd9d5315ea4ad00 (patch) | |
| tree | ee363616e4b8c0d08f9eb893334f2ca4ab814e4f /lisp | |
| parent | 7b4c65034c0081cd144a77b22f8a0214b51e4f86 (diff) | |
| download | emacs-59f36b08082a7ef690cdcfe16fd9d5315ea4ad00.tar.gz emacs-59f36b08082a7ef690cdcfe16fd9d5315ea4ad00.zip | |
Added support for special (quoted) characters in file names:
new functions comint-quote-filename and comint-unquote-filename, using
new variable comint-file-name-quote-list.
Changed comint-word, comint-match-partial-filename and
comint-dynamic-list-filename-completions to support character quoting.
Made comint-dynamic-complete-as-filename and comint-dynamic-simple-complete use
strings of comint-completion-addsuffix for completion, if a cons pair.
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/comint.el | 119 |
1 files changed, 79 insertions, 40 deletions
diff --git a/lisp/comint.el b/lisp/comint.el index a904779543f..ac73762903a 100644 --- a/lisp/comint.el +++ b/lisp/comint.el | |||
| @@ -118,6 +118,7 @@ | |||
| 118 | ;;; comint-last-input-match - string ... | 118 | ;;; comint-last-input-match - string ... |
| 119 | ;;; comint-dynamic-complete-functions - hook For the completion mechanism | 119 | ;;; comint-dynamic-complete-functions - hook For the completion mechanism |
| 120 | ;;; comint-completion-fignore - list ... | 120 | ;;; comint-completion-fignore - list ... |
| 121 | ;;; comint-file-name-quote-list - list ... | ||
| 121 | ;;; comint-get-old-input - function Hooks for specific | 122 | ;;; comint-get-old-input - function Hooks for specific |
| 122 | ;;; comint-input-filter-functions - hook process-in-a-buffer | 123 | ;;; comint-input-filter-functions - hook process-in-a-buffer |
| 123 | ;;; comint-output-filter-functions - hook function modes. | 124 | ;;; comint-output-filter-functions - hook function modes. |
| @@ -130,7 +131,7 @@ | |||
| 130 | ;;; comint-scroll-show-maximum-output - boolean... | 131 | ;;; comint-scroll-show-maximum-output - boolean... |
| 131 | ;;; | 132 | ;;; |
| 132 | ;;; Comint mode non-buffer local variables: | 133 | ;;; Comint mode non-buffer local variables: |
| 133 | ;;; comint-completion-addsuffix - boolean For file name completion | 134 | ;;; comint-completion-addsuffix - boolean/cons For file name completion |
| 134 | ;;; comint-completion-autolist - boolean behavior | 135 | ;;; comint-completion-autolist - boolean behavior |
| 135 | ;;; comint-completion-recexact - boolean ... | 136 | ;;; comint-completion-recexact - boolean ... |
| 136 | 137 | ||
| @@ -391,6 +392,7 @@ Entry to this mode runs the hooks on `comint-mode-hook'." | |||
| 391 | (make-local-variable 'comint-ptyp) | 392 | (make-local-variable 'comint-ptyp) |
| 392 | (make-local-variable 'comint-exec-hook) | 393 | (make-local-variable 'comint-exec-hook) |
| 393 | (make-local-variable 'comint-process-echoes) | 394 | (make-local-variable 'comint-process-echoes) |
| 395 | (make-local-variable 'comint-file-name-quote-list) | ||
| 394 | (run-hooks 'comint-mode-hook)) | 396 | (run-hooks 'comint-mode-hook)) |
| 395 | 397 | ||
| 396 | (if comint-mode-map | 398 | (if comint-mode-map |
| @@ -1406,23 +1408,23 @@ applications." | |||
| 1406 | ;; Use this instead of `read-char' to avoid "Non-character input-event". | 1408 | ;; Use this instead of `read-char' to avoid "Non-character input-event". |
| 1407 | (setq c (read-char-exclusive)) | 1409 | (setq c (read-char-exclusive)) |
| 1408 | (cond ((= c ?\C-g) | 1410 | (cond ((= c ?\C-g) |
| 1409 | ;; This function may get called from a process filter, where | 1411 | ;; This function may get called from a process filter, where |
| 1410 | ;; inhibit-quit is set. In later versions of emacs read-char | 1412 | ;; inhibit-quit is set. In later versions of emacs read-char |
| 1411 | ;; may clear quit-flag itself and return C-g. That would make | 1413 | ;; may clear quit-flag itself and return C-g. That would make |
| 1412 | ;; it impossible to quit this loop in a simple way, so | 1414 | ;; it impossible to quit this loop in a simple way, so |
| 1413 | ;; re-enable it here (for backward-compatibility the check for | 1415 | ;; re-enable it here (for backward-compatibility the check for |
| 1414 | ;; quit-flag below would still be necessary, so this seems | 1416 | ;; quit-flag below would still be necessary, so this seems |
| 1415 | ;; like the simplest way to do things). | 1417 | ;; like the simplest way to do things). |
| 1416 | (setq quit-flag t | 1418 | (setq quit-flag t |
| 1417 | done t)) | 1419 | done t)) |
| 1418 | ((or (= c ?\r) (= c ?\n) (= c ?\e)) | 1420 | ((or (= c ?\r) (= c ?\n) (= c ?\e)) |
| 1419 | (setq done t)) | 1421 | (setq done t)) |
| 1420 | ((= c ?\C-u) | 1422 | ((= c ?\C-u) |
| 1421 | (setq ans "")) | 1423 | (setq ans "")) |
| 1422 | ((and (/= c ?\b) (/= c ?\177)) | 1424 | ((and (/= c ?\b) (/= c ?\177)) |
| 1423 | (setq ans (concat ans (char-to-string c)))) | 1425 | (setq ans (concat ans (char-to-string c)))) |
| 1424 | ((> (length ans) 0) | 1426 | ((> (length ans) 0) |
| 1425 | (setq ans (substring ans 0 -1))))) | 1427 | (setq ans (substring ans 0 -1))))) |
| 1426 | (if quit-flag | 1428 | (if quit-flag |
| 1427 | ;; Emulate a true quit, except that we have to return a value. | 1429 | ;; Emulate a true quit, except that we have to return a value. |
| 1428 | (prog1 | 1430 | (prog1 |
| @@ -1802,6 +1804,8 @@ This mirrors the optional behavior of tcsh.") | |||
| 1802 | 1804 | ||
| 1803 | (defvar comint-completion-addsuffix t | 1805 | (defvar comint-completion-addsuffix t |
| 1804 | "*If non-nil, add a `/' to completed directories, ` ' to file names. | 1806 | "*If non-nil, add a `/' to completed directories, ` ' to file names. |
| 1807 | If a cons pair, it should be of the form (DIRSUFFIX . FILESUFFIX) where | ||
| 1808 | DIRSUFFIX and FILESUFFIX are strings added on unambiguous or exact completion. | ||
| 1805 | This mirrors the optional behavior of tcsh.") | 1809 | This mirrors the optional behavior of tcsh.") |
| 1806 | 1810 | ||
| 1807 | (defvar comint-completion-recexact nil | 1811 | (defvar comint-completion-recexact nil |
| @@ -1821,6 +1825,11 @@ Note that this applies to `comint-dynamic-complete-filename' only.") | |||
| 1821 | This is used by comint's and shell's completion functions, and by shell's | 1825 | This is used by comint's and shell's completion functions, and by shell's |
| 1822 | directory tracking functions.") | 1826 | directory tracking functions.") |
| 1823 | 1827 | ||
| 1828 | (defvar comint-file-name-quote-list nil | ||
| 1829 | "List of characters to quote with `\' when in a file name. | ||
| 1830 | |||
| 1831 | This is a good thing to set in mode hooks.") | ||
| 1832 | |||
| 1824 | 1833 | ||
| 1825 | (defun comint-directory (directory) | 1834 | (defun comint-directory (directory) |
| 1826 | ;; Return expanded DIRECTORY, with `comint-file-name-prefix' if absolute. | 1835 | ;; Return expanded DIRECTORY, with `comint-file-name-prefix' if absolute. |
| @@ -1834,23 +1843,43 @@ directory tracking functions.") | |||
| 1834 | Word constituents are considered to be those in WORD-CHARS, which is like the | 1843 | Word constituents are considered to be those in WORD-CHARS, which is like the |
| 1835 | inside of a \"[...]\" (see `skip-chars-forward')." | 1844 | inside of a \"[...]\" (see `skip-chars-forward')." |
| 1836 | (save-excursion | 1845 | (save-excursion |
| 1837 | (let ((limit (point)) | 1846 | (let ((non-word-chars (concat "[^\\\\" word-chars "]")) (here (point))) |
| 1838 | (word (concat "[" word-chars "]")) | 1847 | (while (and (re-search-backward non-word-chars nil 'move) |
| 1839 | (non-word (concat "[^" word-chars "]"))) | 1848 | ;(memq (char-after (point)) shell-file-name-quote-list) |
| 1840 | (if (re-search-backward non-word nil 'move) | 1849 | (not (bolp)) (eq (char-after (1- (point))) ?\\)) |
| 1841 | (forward-char 1)) | 1850 | (backward-char 1)) |
| 1842 | ;; Anchor the search forwards. | 1851 | (forward-char 1) |
| 1843 | (if (or (eolp) (looking-at non-word)) | 1852 | (and (< (point) here) (buffer-substring (point) here))))) |
| 1844 | nil | ||
| 1845 | (re-search-forward (concat word "+") limit) | ||
| 1846 | (buffer-substring (match-beginning 0) (match-end 0)))))) | ||
| 1847 | 1853 | ||
| 1848 | 1854 | ||
| 1849 | (defun comint-match-partial-filename () | 1855 | (defun comint-match-partial-filename () |
| 1850 | "Return the filename at point, or nil if non is found. | 1856 | "Return the filename at point, or nil if non is found. |
| 1851 | Environment variables are substituted. See `comint-word'." | 1857 | Environment variables are substituted. See `comint-word'." |
| 1852 | (let ((filename (comint-word "~/A-Za-z0-9+@:_.$#%,={}-"))) | 1858 | (let ((filename (comint-word "~/A-Za-z0-9+@:_.$#%,={}-"))) |
| 1853 | (and filename (substitute-in-file-name filename)))) | 1859 | (and filename (substitute-in-file-name (comint-unquote-filename filename))))) |
| 1860 | |||
| 1861 | |||
| 1862 | (defun comint-quote-filename (filename) | ||
| 1863 | "Return FILENAME with magic characters quoted. | ||
| 1864 | Magic characters are those in `comint-file-name-quote-list'." | ||
| 1865 | (if (null comint-file-name-quote-list) | ||
| 1866 | filename | ||
| 1867 | (let ((regexp | ||
| 1868 | (format "\\(^\\|[^\\]\\)\\([%s]\\)" | ||
| 1869 | (mapconcat 'char-to-string comint-file-name-quote-list "")))) | ||
| 1870 | (save-match-data | ||
| 1871 | (while (string-match regexp filename) | ||
| 1872 | (setq filename (replace-match "\\1\\\\\\2" nil nil filename))) | ||
| 1873 | filename)))) | ||
| 1874 | |||
| 1875 | (defun comint-unquote-filename (filename) | ||
| 1876 | "Return FILENAME with quoted characters unquoted." | ||
| 1877 | (if (null comint-file-name-quote-list) | ||
| 1878 | filename | ||
| 1879 | (save-match-data | ||
| 1880 | (while (string-match "\\\\\\(.\\)" filename) | ||
| 1881 | (setq filename (replace-match "\\1" nil nil filename))) | ||
| 1882 | filename))) | ||
| 1854 | 1883 | ||
| 1855 | 1884 | ||
| 1856 | (defun comint-dynamic-complete () | 1885 | (defun comint-dynamic-complete () |
| @@ -1893,6 +1922,12 @@ See `comint-dynamic-complete-filename'. Returns t if successful." | |||
| 1893 | (file-name-handler-alist nil) | 1922 | (file-name-handler-alist nil) |
| 1894 | (minibuffer-p (window-minibuffer-p (selected-window))) | 1923 | (minibuffer-p (window-minibuffer-p (selected-window))) |
| 1895 | (success t) | 1924 | (success t) |
| 1925 | (dirsuffix (cond ((not comint-completion-addsuffix) "") | ||
| 1926 | ((not (consp comint-completion-addsuffix)) "/") | ||
| 1927 | (t (car comint-completion-addsuffix)))) | ||
| 1928 | (filesuffix (cond ((not comint-completion-addsuffix) "") | ||
| 1929 | ((not (consp comint-completion-addsuffix)) " ") | ||
| 1930 | (t (cdr comint-completion-addsuffix)))) | ||
| 1896 | (filename (or (comint-match-partial-filename) "")) | 1931 | (filename (or (comint-match-partial-filename) "")) |
| 1897 | (pathdir (file-name-directory filename)) | 1932 | (pathdir (file-name-directory filename)) |
| 1898 | (pathnondir (file-name-nondirectory filename)) | 1933 | (pathnondir (file-name-nondirectory filename)) |
| @@ -1902,24 +1937,24 @@ See `comint-dynamic-complete-filename'. Returns t if successful." | |||
| 1902 | (message "No completions of %s" filename) | 1937 | (message "No completions of %s" filename) |
| 1903 | (setq success nil)) | 1938 | (setq success nil)) |
| 1904 | ((eq completion t) ; Means already completed "file". | 1939 | ((eq completion t) ; Means already completed "file". |
| 1905 | (if comint-completion-addsuffix (insert " ")) | 1940 | (insert filesuffix) |
| 1906 | (or minibuffer-p (message "Sole completion"))) | 1941 | (or minibuffer-p (message "Sole completion"))) |
| 1907 | ((string-equal completion "") ; Means completion on "directory/". | 1942 | ((string-equal completion "") ; Means completion on "directory/". |
| 1908 | (comint-dynamic-list-filename-completions)) | 1943 | (comint-dynamic-list-filename-completions)) |
| 1909 | (t ; Completion string returned. | 1944 | (t ; Completion string returned. |
| 1910 | (let ((file (concat (file-name-as-directory directory) completion))) | 1945 | (let ((file (concat (file-name-as-directory directory) completion))) |
| 1911 | (insert (substring (directory-file-name completion) | 1946 | (insert (comint-quote-filename |
| 1912 | (length pathnondir))) | 1947 | (substring (directory-file-name completion) |
| 1948 | (length pathnondir)))) | ||
| 1913 | (cond ((symbolp (file-name-completion completion directory)) | 1949 | (cond ((symbolp (file-name-completion completion directory)) |
| 1914 | ;; We inserted a unique completion. | 1950 | ;; We inserted a unique completion. |
| 1915 | (if comint-completion-addsuffix | 1951 | (insert (if (file-directory-p file) dirsuffix filesuffix)) |
| 1916 | (insert (if (file-directory-p file) "/" " "))) | ||
| 1917 | (or minibuffer-p (message "Completed"))) | 1952 | (or minibuffer-p (message "Completed"))) |
| 1918 | ((and comint-completion-recexact comint-completion-addsuffix | 1953 | ((and comint-completion-recexact comint-completion-addsuffix |
| 1919 | (string-equal pathnondir completion) | 1954 | (string-equal pathnondir completion) |
| 1920 | (file-exists-p file)) | 1955 | (file-exists-p file)) |
| 1921 | ;; It's not unique, but user wants shortest match. | 1956 | ;; It's not unique, but user wants shortest match. |
| 1922 | (insert (if (file-directory-p file) "/" " ")) | 1957 | (insert (if (file-directory-p file) dirsuffix filesuffix)) |
| 1923 | (or minibuffer-p (message "Completed shortest"))) | 1958 | (or minibuffer-p (message "Completed shortest"))) |
| 1924 | ((or comint-completion-autolist | 1959 | ((or comint-completion-autolist |
| 1925 | (string-equal pathnondir completion)) | 1960 | (string-equal pathnondir completion)) |
| @@ -1957,6 +1992,9 @@ Returns `listed' if a completion listing was shown. | |||
| 1957 | 1992 | ||
| 1958 | See also `comint-dynamic-complete-filename'." | 1993 | See also `comint-dynamic-complete-filename'." |
| 1959 | (let* ((completion-ignore-case nil) | 1994 | (let* ((completion-ignore-case nil) |
| 1995 | (suffix (cond ((not comint-completion-addsuffix) "") | ||
| 1996 | ((not (consp comint-completion-addsuffix)) " ") | ||
| 1997 | (t (cdr comint-completion-addsuffix)))) | ||
| 1960 | (candidates (mapcar (function (lambda (x) (list x))) candidates)) | 1998 | (candidates (mapcar (function (lambda (x) (list x))) candidates)) |
| 1961 | (completions (all-completions stub candidates))) | 1999 | (completions (all-completions stub candidates))) |
| 1962 | (cond ((null completions) | 2000 | (cond ((null completions) |
| @@ -1968,7 +2006,7 @@ See also `comint-dynamic-complete-filename'." | |||
| 1968 | (message "Sole completion") | 2006 | (message "Sole completion") |
| 1969 | (insert (substring completion (length stub))) | 2007 | (insert (substring completion (length stub))) |
| 1970 | (message "Completed")) | 2008 | (message "Completed")) |
| 1971 | (if comint-completion-addsuffix (insert " ")) | 2009 | (insert suffix) |
| 1972 | 'sole)) | 2010 | 'sole)) |
| 1973 | (t ; There's no unique completion. | 2011 | (t ; There's no unique completion. |
| 1974 | (let ((completion (try-completion stub candidates))) | 2012 | (let ((completion (try-completion stub candidates))) |
| @@ -1978,7 +2016,7 @@ See also `comint-dynamic-complete-filename'." | |||
| 1978 | (string-equal stub completion) | 2016 | (string-equal stub completion) |
| 1979 | (member completion completions)) | 2017 | (member completion completions)) |
| 1980 | ;; It's not unique, but user wants shortest match. | 2018 | ;; It's not unique, but user wants shortest match. |
| 1981 | (insert " ") | 2019 | (insert suffix) |
| 1982 | (message "Completed shortest") | 2020 | (message "Completed shortest") |
| 1983 | 'shortest) | 2021 | 'shortest) |
| 1984 | ((or comint-completion-autolist | 2022 | ((or comint-completion-autolist |
| @@ -2001,9 +2039,10 @@ See also `comint-dynamic-complete-filename'." | |||
| 2001 | (pathnondir (file-name-nondirectory filename)) | 2039 | (pathnondir (file-name-nondirectory filename)) |
| 2002 | (directory (if pathdir (comint-directory pathdir) default-directory)) | 2040 | (directory (if pathdir (comint-directory pathdir) default-directory)) |
| 2003 | (completions (file-name-all-completions pathnondir directory))) | 2041 | (completions (file-name-all-completions pathnondir directory))) |
| 2004 | (if completions | 2042 | (if (not completions) |
| 2005 | (comint-dynamic-list-completions completions) | 2043 | (message "No completions of %s" filename) |
| 2006 | (message "No completions of %s" filename)))) | 2044 | (comint-dynamic-list-completions |
| 2045 | (mapcar 'comint-quote-filename completions))))) | ||
| 2007 | 2046 | ||
| 2008 | 2047 | ||
| 2009 | (defun comint-dynamic-list-completions (completions) | 2048 | (defun comint-dynamic-list-completions (completions) |