[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/bash-completion 6b1be0da4c 048/313: from split to tokenize
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/bash-completion 6b1be0da4c 048/313: from split to tokenize and parse |
Date: |
Sat, 3 Dec 2022 10:59:15 -0500 (EST) |
branch: elpa/bash-completion
commit 6b1be0da4ce2d8cbaf4acdd69ddb8b449ac17dee
Author: Stephane Zermatten <szermatt@gmx.net>
Commit: Stephane Zermatten <szermatt@gmx.net>
from split to tokenize and parse
---
bash-completion.el | 171 ++++++++++++++++++++++++++++++------------------
bash-completion_test.el | 130 ++++++++++++++++++++----------------
2 files changed, 180 insertions(+), 121 deletions(-)
diff --git a/bash-completion.el b/bash-completion.el
index 61f37f2301..7466c859bd 100644
--- a/bash-completion.el
+++ b/bash-completion.el
@@ -48,19 +48,14 @@ Call bash to do the completion."
(let* ( (pos (point))
(start (bash-completion-line-beginning-position))
(end (line-end-position))
- (line (buffer-substring-no-properties start end))
- (wordsplit)
- (cword)
- (words)
- (stub)
+ (parsed (bash-completion-parse-line start end pos))
+ (line (cdr (assq 'line parsed)))
+ (cword (cdr (assq 'cword parsed)))
+ (words (cdr (assq 'words parsed)))
+ (stub (nth cword words))
;; Override configuration for comint-dynamic-simple-complete.
;; Bash adds a space suffix automatically.
(comint-completion-addsuffix nil) )
- (save-excursion
- (setq wordsplit (bash-completion-split start end pos))
- (setq cword (car wordsplit))
- (setq words (cdr wordsplit))
- (setq stub (nth cword words)))
(let ((completions (bash-completion-comm line (- pos start) words cword)))
(if completions
(comint-dynamic-simple-complete stub completions)
@@ -99,103 +94,146 @@ Call bash to do the completion."
word
(replace-regexp-in-string "\\([ '\"]\\)" "\\\\\\1" word)))
-(defun bash-completion-split (start end pos)
- "Split LINE like bash would do, keep track of current word at POS.
-
-Return a list containing the words and the number of the word
-at POS, the current word: ( (word1 word2 ...) . wordnum )"
- (bash-completion-split-postprocess
- (bash-completion-split-raw start end) start pos))
-
-(defun bash-completion-split-strings (accum)
- (mapcar 'bash-completion-split-raw-get-str accum))
-
-(defun bash-completion-split-postprocess (accum start pos)
- (if (null pos)
- (cons nil (bash-completion-split-strings accum))
- ;; find position
- (let ((index 0) (strings nil) (current nil) (accum-rest accum) (cword nil))
- (while accum-rest
- (setq current (car accum-rest))
- (setq accum-rest (cdr accum-rest))
- (unless cword
- (let ((range (bash-completion-split-raw-get-range current)))
- (cond
- ((and (>= pos (car range))
- (<= pos (cdr range)))
- (setq cword index))
- ((< pos (car range))
- (setq cword index)
- (push "" strings)))))
- (push (bash-completion-split-raw-get-str current) strings)
- (setq index (1+ index)))
- (unless cword
- (setq cword index)
- (push "" strings))
- (cons cword (nreverse strings)))))
+(defun bash-completion-parse-line (start end pos)
+ (bash-completion-parse-line-postprocess
+ (bash-completion-parse-current-command
+ (bash-completion-tokenize start end) pos) pos))
-(defsubst bash-completion-split-raw-get-range (current)
+(defun bash-completion-strings-from-tokens (accum)
+ (mapcar 'bash-completion-tokenize-get-str accum))
+
+(defun bash-completion-parse-line-postprocess (accum pos)
+ (let ((index 0) (strings nil) (current nil) (accum-rest accum) (cword nil)
+ (start (car (bash-completion-tokenize-get-range (car accum)))))
+ (while accum-rest
+ (setq current (car accum-rest))
+ (setq accum-rest (cdr accum-rest))
+ (unless cword
+ (let ((range (bash-completion-tokenize-get-range current)))
+ (cond
+ ((and (>= pos (car range))
+ (<= pos (cdr range)))
+ (setq cword index))
+ ((< pos (car range))
+ (setq cword index)
+ (push "" strings)))))
+ (push (bash-completion-tokenize-get-str current) strings)
+ (setq index (1+ index)))
+ (unless cword
+ (setq cword index)
+ (push "" strings))
+ (list
+ (cons 'line (buffer-substring-no-properties start (cdr
(bash-completion-tokenize-get-range current))))
+ (cons 'cword cword)
+ (cons 'words (nreverse strings)))))
+
+(defun bash-completion-parse-current-command (accum pos)
+ (nreverse (catch 'bash-completion-return
+ (let ((command nil) (state 'initial))
+ (dolist (current accum)
+ (let* ((position (bash-completion-tokenize-range-check current pos))
+ (string (bash-completion-tokenize-get-str current))
+ (is-terminal (member string '(";" "&" "|" "&&" "||"))))
+ (cond
+ ((and is-terminal
+ (eq position 'after))
+ (setq state 'initial)
+ (setq command nil))
+
+ (is-terminal
+ (throw 'bash-completion-return command))
+
+ ((and (eq state 'initial)
+ (null (string-match "=" string)))
+ (setq state 'args)
+ (push current command))
+
+ ((and (eq state 'initial)
+ (eq position 'after)))
+
+ ((eq state 'initial)
+ (push current command)
+ (throw 'bash-completion-return command))
+
+ ((eq state 'args)
+ (push current command)))))
+ command))))
+
+(defun bash-completion-tokenize-range-check (current pos)
+ (let ((range (bash-completion-tokenize-get-range current)))
+ (cond
+ ((< pos (car range))
+ 'before)
+
+ ((and (>= pos (car range))
+ (<= pos (cdr range)))
+ 'contains)
+
+ ((> pos (cdr range))
+ 'after))))
+
+(defsubst bash-completion-tokenize-get-range (current)
(cdr current))
-(defsubst bash-completion-split-raw-set-end (current)
+(defsubst bash-completion-tokenize-set-end (current)
(setcdr (cdr current) (point)))
-(defsubst bash-completion-split-raw-append-str (current str)
+(defsubst bash-completion-tokenize-append-str (current str)
(setcar current (concat (car current) str)))
-(defsubst bash-completion-split-raw-get-str (current)
+(defsubst bash-completion-tokenize-get-str (current)
(car current))
-(defun bash-completion-split-raw (start end)
+(defun bash-completion-tokenize (start end)
(save-excursion
(goto-char start)
- (nreverse (bash-completion-split-raw-new-element end nil))))
+ (nreverse (bash-completion-tokenize-new-element end nil))))
-(defun bash-completion-split-raw-new-element (end accum)
+(defun bash-completion-tokenize-new-element (end accum)
(skip-chars-forward " \t\n\r" end)
(if (< (point) end)
- (bash-completion-split-raw-0 end accum (list "" (point)))
+ (bash-completion-tokenize-0 end accum (list "" (point)))
accum))
-(defun bash-completion-split-raw-0 (end accum current)
+(defun bash-completion-tokenize-0 (end accum current)
(let ( (char-start (char-after))
(quote nil) )
(when (and char-start (or (= char-start ?') (= char-start ?\")))
(forward-char)
(setq quote char-start))
- (bash-completion-split-raw-1 end quote accum current)))
+ (bash-completion-tokenize-1 end quote accum current)))
-(defun bash-completion-split-raw-1 (end quote accum current)
+(defun bash-completion-tokenize-1 (end quote accum current)
(let ((local-start (point)))
(when (= (skip-chars-forward "[;&|]" end) 0)
(skip-chars-forward (bash-completion-nonsep quote) end))
- (bash-completion-split-raw-append-str
+ (bash-completion-tokenize-append-str
current
(buffer-substring-no-properties local-start (point))))
(cond
;; an escaped char, skip, whatever it is
((and (char-before) (= ?\\ (char-before)))
(forward-char)
- (let ((straccum (bash-completion-split-raw-get-str current)))
+ (let ((straccum (bash-completion-tokenize-get-str current)))
(aset straccum (1- (length straccum)) (char-before)))
- (bash-completion-split-raw-1 end quote accum current))
+ (bash-completion-tokenize-1 end quote accum current))
;; opening quote
((and (not quote) (char-after) (or (= ?' (char-after)) (= ?\"
(char-after))))
- (bash-completion-split-raw-0 end accum current))
+ (bash-completion-tokenize-0 end accum current))
;; closing quote
((and quote (char-after) (= quote (char-after)))
(forward-char)
- (bash-completion-split-raw-0 end accum current))
+ (bash-completion-tokenize-0 end accum current))
;; space inside a quote
((and quote (char-after) (not (= quote (char-after))))
(forward-char)
- (bash-completion-split-raw-append-str current (char-to-string
(char-before)))
- (bash-completion-split-raw-1 end quote accum current))
+ (bash-completion-tokenize-append-str current (char-to-string
(char-before)))
+ (bash-completion-tokenize-1 end quote accum current))
;; word end
(t
- (bash-completion-split-raw-set-end current)
+ (bash-completion-tokenize-set-end current)
(push current accum)
- (bash-completion-split-raw-new-element end accum))))
+ (bash-completion-tokenize-new-element end accum))))
(defconst bash-completion-nonsep-alist
'((nil . "^ \t\n\r;&|'\"")
@@ -411,7 +449,10 @@ Return `bash-completion-alist'."
(goto-char (point-max))
(while (= 0 (forward-line -1))
(bash-completion-add-to-alist
- (cdr (bash-completion-split (line-beginning-position)
(line-end-position) nil))))))
+ (bash-completion-strings-from-tokens
+ (bash-completion-tokenize
+ (line-beginning-position)
+ (line-end-position)))))))
bash-completion-alist)
(defun bash-completion-add-to-alist (words)
diff --git a/bash-completion_test.el b/bash-completion_test.el
index bfa6dea1ab..edc28eff1c 100644
--- a/bash-completion_test.el
+++ b/bash-completion_test.el
@@ -48,94 +48,106 @@ cases. That's why they need to be enabled manually.")
(bash-completion-join '("a" "hello world" "b" "c"))
"a 'hello world' b c")
- ("bash-completion-split simple"
+ ("bash-completion-tokenize simple"
(sz-testutils-with-buffer
'("a hello world b c")
- (bash-completion-split 1 (line-end-position) nil))
- '(nil . ("a" "hello" "world" "b" "c")))
+ (bash-completion-strings-from-tokens
+ (bash-completion-tokenize 1 (line-end-position))))
+ '("a" "hello" "world" "b" "c"))
- ("bash-completion-split simple extra spaces"
+ ("bash-completion-tokenize simple extra spaces"
(sz-testutils-with-buffer
'(" a hello \n world \t b \r c ")
- (bash-completion-split 1 (line-end-position 2) nil))
- '(nil . ("a" "hello" "world" "b" "c")))
+ (bash-completion-strings-from-tokens
+ (bash-completion-tokenize 1 (line-end-position 2))))
+ '("a" "hello" "world" "b" "c"))
- ("bash-completion-split escaped space"
+ ("bash-completion-tokenize escaped space"
(sz-testutils-with-buffer
'("a hello\\ world b c")
- (bash-completion-split 1 (line-end-position) nil))
- '(nil . ("a" "hello world" "b" "c")))
+ (bash-completion-strings-from-tokens
+ (bash-completion-tokenize 1 (line-end-position))))
+ '("a" "hello world" "b" "c"))
- ("bash-completion-split double quotes"
+ ("bash-completion-tokenize double quotes"
(sz-testutils-with-buffer
'("a \"hello world\" b c")
- (bash-completion-split 1 (line-end-position) nil))
- '(nil . ("a" "hello world" "b" "c")))
+ (bash-completion-strings-from-tokens
+ (bash-completion-tokenize 1 (line-end-position))))
+ '("a" "hello world" "b" "c"))
- ("bash-completion-split double quotes escaped"
+ ("bash-completion-tokenize double quotes escaped"
(sz-testutils-with-buffer
'("a \"-\\\"hello world\\\"-\" b c")
- (bash-completion-split 1 (line-end-position) nil))
- '(nil . ("a" "-\"hello world\"-" "b" "c")))
+ (bash-completion-strings-from-tokens
+ (bash-completion-tokenize 1 (line-end-position))))
+ '("a" "-\"hello world\"-" "b" "c"))
- ("bash-completion-split single quotes"
+ ("bash-completion-tokenize single quotes"
(sz-testutils-with-buffer
'("a \"hello world\" b c")
- (bash-completion-split 1 (line-end-position) nil))
- '(nil . ("a" "hello world" "b" "c")))
+ (bash-completion-strings-from-tokens
+ (bash-completion-tokenize 1 (line-end-position))))
+ '("a" "hello world" "b" "c"))
- ("bash-completion-split single quotes escaped"
+ ("bash-completion-tokenize single quotes escaped"
(sz-testutils-with-buffer
'("a '-\\'hello world\\'-' b c")
- (bash-completion-split 1 (line-end-position) nil))
- '(nil . ("a" "-'hello world'-" "b" "c")))
+ (bash-completion-strings-from-tokens
+ (bash-completion-tokenize 1 (line-end-position))))
+ '("a" "-'hello world'-" "b" "c"))
- ("bash-completion-split complex quote mix"
+ ("bash-completion-tokenize complex quote mix"
(sz-testutils-with-buffer
'("a hel\"lo w\"o'rld b'c d")
- (bash-completion-split 1 (line-end-position) nil))
- '(nil . ("a" "hello world bc" "d")))
+ (bash-completion-strings-from-tokens
+ (bash-completion-tokenize 1 (line-end-position))))
+ '("a" "hello world bc" "d"))
- ("bash-completion-split cursor at end of word"
- (sz-testutils-with-buffer
- '("a hello world" cursor " b c")
- (bash-completion-split 1 (line-end-position) (point)))
- '(2 . ("a" "hello" "world" "b" "c")))
-
- ("bash-completion-split cursor in the middle of a word"
- (sz-testutils-with-buffer
- '("a hello wo" cursor "rld b c")
- (bash-completion-split 1 (line-end-position) (point)))
- '(2 . ("a" "hello" "world" "b" "c")))
-
- ("bash-completion-split-raw unescaped semicolon"
+ ("bash-completion-tokenize unescaped semicolon"
(sz-testutils-with-buffer
"to infinity;and\\ beyond"
- (bash-completion-split-strings
- (bash-completion-split-raw 1 (line-end-position))))
+ (bash-completion-strings-from-tokens
+ (bash-completion-tokenize 1 (line-end-position))))
'("to" "infinity" ";" "and beyond"))
- ("bash-completion-split-raw unescaped &&"
+ ("bash-completion-tokenize unescaped &&"
(sz-testutils-with-buffer
"to infinity&&and\\ beyond"
- (bash-completion-split-strings
- (bash-completion-split-raw 1 (line-end-position))))
+ (bash-completion-strings-from-tokens
+ (bash-completion-tokenize 1 (line-end-position))))
'("to" "infinity" "&&" "and beyond"))
- ("bash-completion-split-raw unescaped ||"
+ ("bash-completion-tokenize unescaped ||"
(sz-testutils-with-buffer
"to infinity||and\\ beyond"
- (bash-completion-split-strings
- (bash-completion-split-raw 1 (line-end-position))))
+ (bash-completion-strings-from-tokens
+ (bash-completion-tokenize 1 (line-end-position))))
'("to" "infinity" "||" "and beyond"))
- ("bash-completion-split-raw quoted ;&|"
+ ("bash-completion-tokenize quoted ;&|"
(sz-testutils-with-buffer
"to \"infinity;&|and\" beyond"
- (bash-completion-split-strings
- (bash-completion-split-raw 1 (line-end-position))))
+ (bash-completion-strings-from-tokens
+ (bash-completion-tokenize 1 (line-end-position))))
'("to" "infinity;&|and" "beyond"))
+ ("bash-completion-parse-line cursor at end of word"
+ (sz-testutils-with-buffer
+ '("a hello world" cursor " b c")
+ (bash-completion-parse-line 1 (line-end-position) (point)))
+ '((line . "a hello world b c")
+ (cword . 2)
+ (words . ("a" "hello" "world" "b" "c"))))
+
+ ("bash-completion-parse-line cursor in the middle of a word"
+ (sz-testutils-with-buffer
+ '("a hello wo" cursor "rld b c")
+ (bash-completion-parse-line 1 (line-end-position) (point)))
+ '((line . "a hello world b c")
+ (cword . 2)
+ (words . ("a" "hello" "world" "b" "c"))))
+
;; ("bash-completion-split cursor at the beginning"
;; (sz-testutils-with-buffer
;; '(" " cursor " a hello world b c")
@@ -148,23 +160,29 @@ cases. That's why they need to be enabled manually.")
;; (bash-completion-split 1 (line-end-position) (point)))
;; '(2 . ("a" "hello" "" "world" "b" "c")))
- ("bash-completion-split cursor at end"
+ ("bash-completion-parse-line cursor at end"
(sz-testutils-with-buffer
'("a hello world b c" cursor)
- (bash-completion-split 1 (line-end-position) (point)))
- '(4 . ("a" "hello" "world" "b" "c")))
+ (bash-completion-parse-line 1 (line-end-position) (point)))
+ '((line . "a hello world b c")
+ (cword . 4)
+ (words . ("a" "hello" "world" "b" "c"))))
("bash-completion-split cursor after end"
(sz-testutils-with-buffer
'("a hello world b c " cursor)
- (bash-completion-split 1 (line-end-position) (point)))
- '(5 . ("a" "hello" "world" "b" "c" "")))
+ (bash-completion-parse-line 1 (line-end-position) (point)))
+ '((line . "a hello world b c")
+ (cword . 5)
+ (words . ("a" "hello" "world" "b" "c" ""))))
("bash-completion-split with escaped quote"
(sz-testutils-with-buffer
- '("cd /vcr/shows/Dexter\\'" cursor)
- (bash-completion-split 1 (line-end-position) (point)))
- '(1 . ("cd" "/vcr/shows/Dexter'")))
+ '("cd /vcr/shows/Dexter\\'s" cursor)
+ (bash-completion-parse-line 1 (line-end-position) (point)))
+ '((line . "cd /vcr/shows/Dexter\\'s")
+ (cword . 1)
+ (words . ("cd" "/vcr/shows/Dexter's"))))
("bash-completion-add-to-alist garbage"
(let ((bash-completion-alist nil))
- [nongnu] elpa/bash-completion a78fd6b587 044/313: turn off mailwarn and checkjobs, continue if this failed, (continued)
- [nongnu] elpa/bash-completion a78fd6b587 044/313: turn off mailwarn and checkjobs, continue if this failed, ELPA Syncer, 2022/12/03
- [nongnu] elpa/bash-completion 0ffaad3ef0 035/313: wordbreak-split, ELPA Syncer, 2022/12/03
- [nongnu] elpa/bash-completion 80cd654c35 043/313: turn off mailwarn and checkjobs, continue if this failed, ELPA Syncer, 2022/12/03
- [nongnu] elpa/bash-completion 1c6b2efb67 040/313: enormous test, ELPA Syncer, 2022/12/03
- [nongnu] elpa/bash-completion fc96b621e2 034/313: pass all tests in bash-completion, new test for -send, ELPA Syncer, 2022/12/03
- [nongnu] elpa/bash-completion e77c841dac 107/313: Merge pull request #3 from seanmcl/master, ELPA Syncer, 2022/12/03
- [nongnu] elpa/bash-completion 062acfab3e 052/313: updated documentation, ELPA Syncer, 2022/12/03
- [nongnu] elpa/bash-completion 75e5de1494 066/313: fix initial completion, ELPA Syncer, 2022/12/03
- [nongnu] elpa/bash-completion ffe8bc46a2 097/313: Ignore 'cd' stdout, in case someone (like me) is crazy enough to override the builtin command, ELPA Syncer, 2022/12/03
- [nongnu] elpa/bash-completion b1ff763566 104/313: Clear PROMPT_COMMAND when creating bash process, ELPA Syncer, 2022/12/03
- [nongnu] elpa/bash-completion 6b1be0da4c 048/313: from split to tokenize and parse,
ELPA Syncer <=
- [nongnu] elpa/bash-completion 679d6f7765 075/313: bugfix at try afterbreak, ELPA Syncer, 2022/12/03
- [nongnu] elpa/bash-completion 8cc9c2fdc6 074/313: bugfix, ELPA Syncer, 2022/12/03
- [nongnu] elpa/bash-completion 96d764fb18 095/313: removed unnecessary quote escapes in documentation, ELPA Syncer, 2022/12/03
- [nongnu] elpa/bash-completion db0545f469 093/313: Add a markdown README file, ELPA Syncer, 2022/12/03
- [nongnu] elpa/bash-completion 3eb77ec9c4 086/313: Moved shell configuration into config. Got rid of */init.el, going, ELPA Syncer, 2022/12/03
- [nongnu] elpa/bash-completion abeee42e65 112/313: Set comint-completion-addsuffix again in pre-emacs-24.1 mode., ELPA Syncer, 2022/12/03
- [nongnu] elpa/bash-completion 920bbc25bf 121/313: Run integration tests successfully on system where "hel" expand to more, ELPA Syncer, 2022/12/03
- [nongnu] elpa/bash-completion bac0fb55f1 124/313: More integration test cleanup made possible by the move to ert., ELPA Syncer, 2022/12/03
- [nongnu] elpa/bash-completion b49dbe1457 127/313: Don't require obsolete and unused cl., ELPA Syncer, 2022/12/03
- [nongnu] elpa/bash-completion 0af9a70ff9 130/313: Merge pull request #16 from tarsius/master, ELPA Syncer, 2022/12/03