auctex-diffs
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]