[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[AUCTeX-diffs] feature/capf 255ba0c2: * latex-capf.el: New file.
From: |
auctex-commit |
Subject: |
[AUCTeX-diffs] feature/capf 255ba0c2: * latex-capf.el: New file. |
Date: |
Fri, 6 May 2022 07:51:42 -0400 (EDT) |
branch: feature/capf
commit 255ba0c29975061ead5ac19aab3e947c8104494d
Author: Arash Esbati <arash@gnu.org>
Commit: Arash Esbati <arash@gnu.org>
* latex-capf.el: New file.
---
latex-capf.el | 264 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 264 insertions(+)
diff --git a/latex-capf.el b/latex-capf.el
new file mode 100644
index 00000000..2b65bbd4
--- /dev/null
+++ b/latex-capf.el
@@ -0,0 +1,264 @@
+;; -*- lexical-binding: t; -*-
+
+(eval-when-compile
+ (require 'cl-lib))
+
+(defun TeX-move-to-previous-arg (&optional bound)
+ "Move backward to the closing parenthesis of the previous argument.
+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
+ ((re-search-backward
+ "[]}][ \t]*[\n\r]?\\([ \t]*%[^\n\r]*[\n\r]\\)*[ \t]*\\=" bound t)
+ (goto-char (1+ (match-beginning 0)))
+ t)
+ (t nil)))
+
+(defun LaTeX-what-macro (&optional bound)
+ "Find out if point is within the arguments of any TeX-macro.
+The return value is
+
+ (\"name\" mac-or-env integer type)
+
+\"name\" is the name of the macro (without backslash) or
+ environment as a string.
+mac-or-env is one of the symbols `mac' or `env'.
+integer is the number of the argument where we started.
+type is one of the symbols `mandatory' or `optional'.
+
+If the optional BOUND is an integer, bound backwards directed
+searches to this point. If it is nil, limit to the previous 15
+lines."
+ (catch 'exit
+ ;; Exit if we're not inside a list or inside a nested list:
+ (when (/= (car (syntax-ppss)) 1)
+ (throw 'exit nil))
+ (let ((bound (or bound (line-beginning-position -15)))
+ (env-or-mac 'mac)
+ cmd cnt cnt-opt type)
+ (save-excursion
+ (save-restriction
+ (narrow-to-region (max (point-min) bound) (point-max))
+ ;; Move back out of the current parenthesis
+ (while (condition-case nil
+ (let ((forward-sexp-function nil))
+ (up-list -1) t)
+ (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 (TeX-move-to-previous-arg bound)
+ (condition-case nil
+ (let ((forward-sexp-function nil))
+ (backward-sexp) t)
+ (error nil)))
+ (if (eq (following-char) ?\[) (cl-incf cnt-opt))
+ (cl-incf cnt))
+ (when (and (or (= (following-char) ?\[)
+ (= (following-char) ?\{))
+ (re-search-backward "\\\\[*a-zA-Z]+\\=" nil t))
+ (setq cmd (TeX-match-buffer 0))
+ (when (looking-at "\\\\begin{\\([^}]+\\)}")
+ (setq cmd (TeX-match-buffer 1))
+ (setq env-or-mac 'env)
+ (cl-decf cnt))
+ (if (and cmd (not (string= cmd "")))
+ (throw 'exit
+ (list (if (eq env-or-mac 'mac)
+ ;; Strip leading backslash from
+ ;; the macro
+ (substring cmd 1)
+ cmd)
+ env-or-mac cnt type))
+ (throw 'exit nil)))))))))
+
+(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:
+ (let ((end (point))
+ (func (lambda (kv &optional k)
+ (if k
+ (cadr (assoc k kv))
+ kv)))
+ beg key)
+ (save-excursion
+ (re-search-backward "[[{,=]" (line-beginning-position 0) t))
+ (if (string= (match-string 0) "=")
+ ;; We have to look for a value:
+ (save-excursion
+ ;; Matching the value is easy, just grab everything before the
+ ;; '=' and ...
+ (re-search-backward "=\\([^=]*\\)" (line-beginning-position) t)
+ ;; ... then move forward over any tabs and spaces:
+ (save-excursion
+ (forward-char)
+ (skip-chars-forward " \t" end)
+ (setq beg (point)))
+ ;; Matching the key is less fun: `re-search-backward'
+ ;; doesn't travel enough, so we have to use
+ ;; `skip-chars-backward' and limit the search to the
+ ;; beginning of the previous line:
+ (skip-chars-backward "^,[{" (line-beginning-position 0))
+ ;; Make sure we're not looking at a comment:
+ (when (looking-at-p (concat "[ \t]*" TeX-comment-start-regexp))
+ (forward-line))
+ ;; Now pick up the key, if available:
+ (setq key (string-trim
+ (buffer-substring-no-properties (point)
+ (match-beginning 0))
+ "[ \t\n\r%]+" "[ \t\n\r%]+"))
+ ;; This caters also for the case where nothing is typed yet:
+ (list beg end (completion-table-dynamic
+ (lambda (_)
+ (funcall func key-vals key)))))
+ ;; We have to look for a key:
+ (save-excursion
+ ;; Find the beginning
+ (skip-chars-backward "^,[{" (line-beginning-position 0))
+ ;; Make sure we're not looking at a comment:
+ (when (looking-at-p (concat "[ \t]*" TeX-comment-start-regexp))
+ (forward-line))
+ ;; Now go until the first char or number which would be the
+ ;; start of the key:
+ (skip-chars-forward "^a-zA-Z0-9" end)
+ (setq beg (point))
+ ;; This caters also for the case where nothing is typed yet:
+ (list beg end (completion-table-dynamic
+ (lambda (_)
+ (funcall func key-vals))))))))
+
+(defun LaTeX-completion-candidates-completing-read (collection)
+ (let ((end (point))
+ beg key) ))
+
+(defun LaTeX-completion-candidates-completing-read-multiple (table)
+ nil)
+
+(defun LaTeX-completion-parse-arg (arg)
+ "Prepare ARG suitable for further completion processing."
+ (when (and (or (vectorp arg)
+ (listp arg))
+ (symbolp (elt arg 0))
+ (fboundp (elt arg 0)))
+ ;; Turn a vector into a list:
+ (when (vectorp arg)
+ (setq arg (append arg nil)))
+ (let ((head (car arg))
+ (tail (cadr arg)))
+ (cond ((eq head #'TeX-arg-key-val)
+ (LaTeX-completion-candidates-key-val
+ (cond ((symbolp tail)
+ ;; It is a variable name
+ (symbol-value tail))
+ ;; It is a function call ...
+ ((and (listp tail)
+ (symbolp (car tail))
+ (fboundp (car tail)))
+ ;; ... w/ or w/o args:
+ (if (= (length tail) 1)
+ (funcall (car tail))
+ (eval tail t)))
+ ;; It is a plain list of strings:
+ (t tail))))
+ ) )))
+
+(defun LaTeX-completion-calculate-candidates ()
+ (catch 'exit
+ ;; Exit if not inside a list or a nested list or in a comment:
+ (when (or (/= (car (syntax-ppss)) 1)
+ (TeX-in-comment))
+ (throw 'exit nil))
+ (let ((entry (LaTeX-what-macro))
+ mac env arg head)
+ (cond ((eq (nth 1 entry) 'mac)
+ ;; Feed 'arg' to `LaTeX-completion-parse-arg' only when
+ ;; we find one:
+ (and (setq mac (assoc (car entry) (TeX-symbol-list)))
+ (setq arg (nth (nth 2 entry) mac))
+ (LaTeX-completion-parse-arg arg)))
+ ((eq (nth 1 entry) 'env)
+ ;; Feed 'arg' to `LaTeX-completion-parse-arg' only when
+ ;; we find one:
+ (and (setq env (assoc (car entry) (LaTeX-environment-list)))
+ ;; Shift the number of arg if `LaTeX-env-args' is present:
+ (setq arg (if (eq (cadr env) 'LaTeX-env-args)
+ (nth (1+ (nth 2 entry)) env)
+ (nth (nth 2 entry) env)))
+ (LaTeX-completion-parse-arg arg)))
+ ;; Any other constructs?
+ (t nil)))))
+
+
+
+
+;; (defun LaTeX-calculate-candidates ()
+;; (catch 'exit
+;; ;; Exit if not inside a list or a nested list or in a comment:
+;; (when (or (/= (car (syntax-ppss)) 1)
+;; (TeX-in-comment))
+;; (throw 'exit nil))
+;; (let ((entry (LaTeX-what-macro))
+;; mac env arg head) ;; tail
+;; (cond ((eq (nth 1 entry) 'mac)
+;; (setq mac (assoc (car entry) (TeX-symbol-list)))
+;; (setq arg (nth (nth 2 entry) mac))
+;; (cond ((or (vectorp arg)
+;; (listp arg))
+;; (when (vectorp arg)
+;; (setq arg (append arg nil)))
+;; (setq head (car arg))
+;; (cond ((functionp head)
+;; (cond ((eq head #'TeX-arg-key-val)
+;; (LaTeX-completion-candidates-key-val
(eval (cadr arg) t)))
+;; ;; ((eq head #'TeX-arg-completing-read)
...)
+;; ;; ((eq head #'TeX-arg-crm) ...)
+;; (t nil)))
+;; (t nil)))
+;; ((and (symbolp arg)
+;; (functionp arg)
+;; (fboundp arg))
+;; (LaTeX-completion-candidates-single arg))
+;; (t nil)))
+;; ((eq (nth 1 entry) 'env)
+;; (setq env (assoc (car entry) (LaTeX-environment-list)))
+;; ;; Shift the number of arg if `LaTeX-env-args' is present:
+;; (setq arg (if (eq (cadr env) 'LaTeX-env-args)
+;; (nth (1+ (nth 2 entry)) env)
+;; (nth (nth 2 entry) env)))
+;; (cond ((or (vectorp arg)
+;; (listp arg))
+;; (when (vectorp arg)
+;; (setq arg (append arg nil)))
+;; (setq head (car arg))
+;; (cond ((functionp head)
+;; (cond ((eq head #'TeX-arg-key-val)
+;; (LaTeX-completion-candidates-key-val
(eval (cadr arg) t)))
+;; ;; ((eq head #'TeX-arg-completing-read)
...)
+;; ;; ((eq head #'TeX-arg-crm) ...)
+;; (t nil)))
+;; (t nil)))) )
+;; ;; Any other constructs?
+;; (t nil)))))
+
+
+
+;; (defun LaTeX-completion-candidates-single (func)
+
+;; (let ((end (point))
+;; beg)
+;; (cond ((eq func #'TeX-arg-pagestyle)
+;; (save-excursion
+;; (skip-chars-backward "a-zA-Z0-9")
+;; (setq beg (point)))
+;; (list beg end (completion-table-dynamic
+;; (lambda (_) (LaTeX-pagestyle-list)))))
+;; (t nil))
+;; ))
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [AUCTeX-diffs] feature/capf 255ba0c2: * latex-capf.el: New file.,
auctex-commit <=