[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
feature/capf 0f2a4cd1 2/2: Further improvements
From: |
Arash Esbati |
Subject: |
feature/capf 0f2a4cd1 2/2: Further improvements |
Date: |
Thu, 20 Oct 2022 08:53:28 -0400 (EDT) |
branch: feature/capf
commit 0f2a4cd1b3cba5dbee8270c63b3c7030822f9703
Author: Arash Esbati <arash@gnu.org>
Commit: Arash Esbati <arash@gnu.org>
Further improvements
---
latex-capf.el | 200 +++++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 142 insertions(+), 58 deletions(-)
diff --git a/latex-capf.el b/latex-capf.el
index aca92127..9dd0505f 100644
--- a/latex-capf.el
+++ b/latex-capf.el
@@ -3,17 +3,47 @@
(eval-when-compile
(require 'cl-lib))
-(defun TeX-move-to-previous-arg (&optional bound)
+(defvar LaTeX-completion-macro-delimiters
+ '((?\[ . ?\])
+ (?\{ . ?\})
+ (?\( . ?\))
+ (?\< . ?\>))
+ "List of characters delimiting mandatory and optional arguments.
+Each element in the list is cons with opening char as car and the
+closing char as cdr.")
+
+(defun LaTeX-completion-macro-delimiters (&optional which)
+ "Return elements of the variable `LaTeX-completion-macro-delimiters'.
+If the optional WHICH is the symbol `open', return the car's of
+each element in the variable `LaTeX-completion-macro-delimiters'.
+If it is the symbol `close', return the cdr's. If omitted,
+return all elements."
+ (cond ((eq which 'open)
+ (mapcar #'car LaTeX-completion-macro-delimiters))
+ ((eq which 'close)
+ (mapcar #'cdr LaTeX-completion-macro-delimiters))
+ (t
+ (append
+ (mapcar #'car LaTeX-completion-macro-delimiters)
+ (mapcar #'cdr LaTeX-completion-macro-delimiters)))))
+
+(defun LaTeX-move-to-previous-arg (&optional bound)
"Move backward to the closing parenthesis of the previous argument.
+Closing parenthesis is in this context all characters which can
+be used to delimit an argument. Currently, these are the
+following characters:
+
+ } ] ) >
+
This happens under the assumption that we are in front of a macro
argument. This function understands the splitting of macros over
several lines in TeX."
(cond
;; Just to be quick:
- ((memq (preceding-char) '(?\] ?\})))
- ;; Do a search
+ ((memql (preceding-char) (LaTeX-completion-macro-delimiters 'close)))
+ ;; Do a search:
((re-search-backward
- "[]}][ \t]*[\n\r]?\\([ \t]*%[^\n\r]*[\n\r]\\)*[ \t]*\\=" bound t)
+ "[]})>][ \t]*[\n\r]?\\([ \t]*%[^\n\r]*[\n\r]\\)*[ \t]*\\=" bound t)
(goto-char (1+ (match-beginning 0)))
t)
(t nil)))
@@ -42,26 +72,30 @@ this point. If nil, limit to the previous 15 lines."
(save-restriction
(narrow-to-region (max (point-min) bound) (point-max))
;; Move back out of the current parenthesis
- (let ((forward-sexp-function nil))
- (up-list -1))
- ;; Set the initial value of argument counter
- (setq cnt 1)
- ;; Note that we count also the right opt. or man. arg:
- (setq cnt-opt (if (= (following-char) ?\{) 0 1))
- ;; Record if we're inside a mand. or opt. argument
- (setq type (if (= (following-char) ?\{) 'mandatory 'optional))
- ;; Move back over any touching sexps
- (while (and (TeX-move-to-previous-arg bound)
- (condition-case nil
- (let ((forward-sexp-function nil))
- (backward-sexp) t)
- (error nil)))
- (when (eq (following-char) ?\[)
- (cl-incf cnt-opt))
- (cl-incf cnt))
+ (with-syntax-table (apply #'TeX-search-syntax-table
+ (LaTeX-completion-macro-delimiters))
+ (condition-case nil
+ (let ((forward-sexp-function nil))
+ (up-list -1))
+ (error nil))
+ ;; Set the initial value of argument counter
+ (setq cnt 1)
+ ;; Note that we count also the right opt. or man. arg:
+ (setq cnt-opt (if (= (following-char) ?\{) 0 1))
+ ;; Record if we're inside a mand. or opt. argument
+ (setq type (if (= (following-char) ?\{) 'mandatory 'optional))
+ ;; Move back over any touching sexps
+ (while (and (LaTeX-move-to-previous-arg bound)
+ (condition-case nil
+ (let ((forward-sexp-function nil))
+ (backward-sexp) t)
+ (error nil)))
+ (unless (= (following-char) ?\{)
+ (cl-incf cnt-opt))
+ (cl-incf cnt)))
;; (setq env-or-mac-start (point))
- (when (and (or (= (following-char) ?\[)
- (= (following-char) ?\{))
+ (when (and (memql (following-char) ;; '(?\[ ?\{ ?\( ?<)
+ (LaTeX-completion-macro-delimiters 'open))
(re-search-backward "\\\\[*a-zA-Z]+\\=" nil t))
(setq cmd (TeX-match-buffer 0))
(when (looking-at "\\\\begin{\\([^}]+\\)}")
@@ -83,24 +117,26 @@ this point. If nil, limit to the previous 15 lines."
(save-excursion
(save-restriction
(narrow-to-region (max (point-min) bound) (point-max))
- (let ((forward-sexp-function nil))
- (up-list -1))
- (unless (= (following-char) ?\{)
- (cl-incf cnt-distance))
- (while (and (TeX-move-to-previous-arg bound)
- (condition-case nil
- (let ((forward-sexp-function nil))
- (backward-sexp)
- (/= (following-char) ?\{))
- (error nil)))
- (cl-incf cnt-distance)))))
+ (with-syntax-table (apply #'TeX-search-syntax-table
+ (LaTeX-completion-macro-delimiters))
+ (let ((forward-sexp-function nil))
+ (up-list -1))
+ (unless (= (following-char) ?\{)
+ (cl-incf cnt-distance))
+ (while (and (LaTeX-move-to-previous-arg bound)
+ (condition-case nil
+ (let ((forward-sexp-function nil))
+ (backward-sexp)
+ (/= (following-char) ?\{))
+ (error nil)))
+ (cl-incf cnt-distance))))))
;; Check if we really have a result before adding something new:
(when result
(append result (list cnt-distance)))))
(defun LaTeX-completion-candidates-key-val (key-vals)
- ;; First find out if we're looking for a key or a value: If we're
- ;; after a '=', then a value, otherwise a key:
+ "Return completion candidates from KEY-VALS based on buffer position.
+KEY-VALS is an alist of key-values pairs."
(let ((end (point))
(func (lambda (kv &optional k)
(if k
@@ -108,7 +144,7 @@ this point. If nil, limit to the previous 15 lines."
kv)))
beg key)
(save-excursion
- (re-search-backward "[[{,=]" (line-beginning-position 0) t))
+ (re-search-backward "[[{(<,=]" (line-beginning-position 0) t))
(if (string= (match-string 0) "=")
;; We have to look for a value:
(save-excursion
@@ -154,10 +190,14 @@ this point. If nil, limit to the previous 15 lines."
(funcall func key-vals))))))))
(defun LaTeX-completion-candidates-completing-read-multiple (collection)
+ "Return completion candidates from COLLECTION based on buffer position.
+COLLECTION is an list of strings."
(let ((end (point))
beg list-beg)
(save-excursion
- (up-list -1)
+ (with-syntax-table (apply #'TeX-search-syntax-table
+ (LaTeX-completion-macro-delimiters))
+ (up-list -1))
(setq list-beg (1+ (point))))
(save-excursion
(unless (search-backward "," list-beg t)
@@ -169,10 +209,14 @@ this point. If nil, limit to the previous 15 lines."
collection)))))
(defun LaTeX-completion-candidates-completing-read (collection)
+ "Return completion candidates from COLLECTION based on buffer position.
+COLLECTION is an list of strings."
(let ((end (point))
beg)
(save-excursion
- (up-list -1)
+ (with-syntax-table (apply #'TeX-search-syntax-table
+ (LaTeX-completion-macro-delimiters))
+ (up-list -1))
(forward-char)
(skip-chars-forward "^a-zA-Z0-9" end)
(setq beg (point)))
@@ -190,18 +234,34 @@ this point. If nil, limit to the previous 15 lines."
(mand-num (- total-num opt-num))
(cnt 0)
(again t)
- arg-list result)
+ arg-list
+ arg
+ result)
(setq arg-list (cdr (assoc name (if (eq mac-or-env 'mac)
(TeX-symbol-list)
(LaTeX-environment-list)))))
- ;; FIXME: Check for `TeX-arg-conditional' here and change
- ;; `arg-list' accordingly
- ;;
+
;; Check if there is a `LaTeX-env-args' in the `arg-list' and
;; remove it:
(when (and (eq mac-or-env 'env)
(eq (car arg-list) #'LaTeX-env-args))
(pop arg-list))
+
+ ;; Check for `TeX-arg-conditional' here and change `arg-list'
+ ;; accordingly
+ (when (assq 'TeX-arg-conditional arg-list)
+ (while (and arg-list
+ (setq arg (car arg-list)))
+ (if (and (listp arg) (eq (car arg) 'TeX-arg-conditional))
+ (setq result (append (reverse (if (eval (nth 1 arg) t)
+ (nth 2 arg)
+ (nth 3 arg)))
+ result))
+ (push arg result))
+ (pop arg-list))
+ (setq arg-list (nreverse result)))
+
+ ;; Now parse the `arg-list':
(cond ((and (eq type 'optional)
(= opt-dis 0))
;; Optional arg without mandatory one before: This case is
@@ -263,8 +323,10 @@ this point. If nil, limit to the previous 15 lines."
(defun LaTeX-completion-parse-arg (arg)
"Prepare ARG suitable for further completion processing."
(when (or (and (vectorp arg)
+ (symbolp (elt arg 0))
(fboundp (elt arg 0)))
(and (listp arg)
+ (symbolp (car arg))
(fboundp (car arg)))
(and (symbolp arg)
(fboundp arg)))
@@ -277,17 +339,17 @@ this point. If nil, limit to the previous 15 lines."
(let* ((head (car arg))
(tail (cadr arg))
(fun1 (lambda (elt)
- (cond ((symbolp elt)
- ;; It is a variable name
- (symbol-value elt))
- ;; It is a function call ...
- ((and (listp elt)
+ (cond ((and (listp elt)
(symbolp (car elt))
(fboundp (car elt)))
- ;; ... w/ or w/o args:
- (if (= (length elt) 1)
- (funcall (car elt))
- (eval elt t)))
+ ;; It is a function call:
+ (funcall (car elt)))
+ ;; It is a function object
+ ((functionp elt)
+ (funcall elt))
+ ;; It is a variable name
+ ((symbolp elt)
+ (symbol-value elt))
;; It is a plain list of strings:
(t elt)))))
(cond ((eq head #'TeX-arg-key-val)
@@ -300,7 +362,11 @@ this point. If nil, limit to the previous 15 lines."
(LaTeX-completion-candidates-completing-read
(funcall fun1 tail)))
((assq (car arg) LaTeX-completion-function-map-alist)
- (funcall (cdr (assq (car arg)
LaTeX-completion-function-map-alist))))
+ (LaTeX-completion-candidates-completing-read
+ (funcall (cdr (assq (car arg)
LaTeX-completion-function-map-alist)))))
+ ((eq head #'LaTeX-enumitem-env-with-opts)
+ (LaTeX-completion-candidates-key-val
+ (LaTeX-enumitem-key-val-options)))
(t nil)))))
(defvar LaTeX-completion-function-map-alist
@@ -313,14 +379,32 @@ Each element is a cons with the name of the function which
queries and inserts something in the buffer as car and the name
function delievering completion candidates as cdr.")
+(defun LaTeX-completion-find-argument-boundries (&rest args)
+ "Find the boundries of the current LaTeX argument.
+ARGS are characters passed to the function
+`TeX-search-syntax-table'. If ARGS are omitted, all characters
+defined in the variable `LaTeX-completion-macro-delimiters' are
+taken."
+ (save-restriction
+ (narrow-to-region (line-beginning-position -20)
+ (line-beginning-position 20))
+ (let ((args (or args (LaTeX-completion-macro-delimiters))))
+ (condition-case nil
+ (with-syntax-table (apply #'TeX-search-syntax-table args)
+ (scan-lists (point) 1 1))
+ (error nil)))))
+
(defun LaTeX-arguments-completion-at-point ()
- ;; Exit if not inside a list or a nested list or in a comment:
- (when (or (/= (car (syntax-ppss)) 0)
- (not (TeX-in-comment)))
+ ;; Exit if not inside an argument or in a comment:
+ (when (and (LaTeX-completion-find-argument-boundries)
+ (not (save-match-data
+ (nth 4 (syntax-ppss)))))
(let ((entry (LaTeX-what-macro)))
- (cond ((or (and (eq (nth 1 entry) 'mac)
+ (cond ((or (and entry
+ (eq (nth 1 entry) 'mac)
(assoc (car entry) (TeX-symbol-list)))
- (and (eq (nth 1 entry) 'env)
+ (and entry
+ (eq (nth 1 entry) 'env)
(assoc (car entry) (LaTeX-environment-list))))
;; Check if we find the macro name inside
;; `TeX-symbol-list' or the env name inside
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- feature/capf 0f2a4cd1 2/2: Further improvements,
Arash Esbati <=