summaryrefslogtreecommitdiff
path: root/lisp
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2009-11-19 22:55:41 +0000
committerStefan Monnier <monnier@iro.umontreal.ca>2009-11-19 22:55:41 +0000
commiteff77808b45d25ad6afd10df5616db9c5c9c7f1c (patch)
tree31497a69e8ced84de38eba57984eaaba5977c450 /lisp
parent8ab1650ee30cf51b9756f093975d4f58b7839688 (diff)
downloademacs-eff77808b45d25ad6afd10df5616db9c5c9c7f1c.tar.gz
(latex-complete-bibtex-cache, latex-complete-alist): New vars.
(latex-string-prefix-p, latex-complete-bibtex-keys, latex-complete-data) (latex-complete-envnames, latex-complete-refkeys): New functions. (latex-complete, latex-indent-or-complete): New commands.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/ChangeLog7
-rw-r--r--lisp/textmodes/tex-mode.el110
2 files changed, 117 insertions, 0 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index f14e545a5de..b868ce22626 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,12 @@
2009-11-19 Stefan Monnier <monnier@iro.umontreal.ca>
+ * textmodes/tex-mode.el (latex-complete-bibtex-cache)
+ (latex-complete-alist): New vars.
+ (latex-string-prefix-p, latex-complete-bibtex-keys)
+ (latex-complete-envnames, latex-complete-refkeys)
+ (latex-complete-data): New functions.
+ (latex-complete, latex-indent-or-complete): New commands.
+
* window.el (display-buffer-mark-dedicated): New var.
(display-buffer): Obey it.
* minibuffer.el (minibuffer-completion-help): Use it.
diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el
index 9f7ff975e56..3cbd6e19e73 100644
--- a/lisp/textmodes/tex-mode.el
+++ b/lisp/textmodes/tex-mode.el
@@ -1420,6 +1420,116 @@ Puts point on a blank line between them."
\n "\\item " >)
+;;;; LaTeX completion.
+
+(defvar latex-complete-bibtex-cache nil)
+
+(defun latex-string-prefix-p (str1 str2)
+ (eq t (compare-strings str1 nil nil str2 0 (length str1))))
+
+(defvar bibtex-reference-key)
+(declare-function reftex-get-bibfile-list "reftex-cite.el" ())
+
+(defun latex-complete-bibtex-keys ()
+ (when (bound-and-true-p reftex-mode)
+ (lambda (key pred action)
+ (let ((re (concat "^[ \t]*@\\([a-zA-Z]+\\)[ \t\n]*\\([{(][ \t\n]*\\)"
+ (regexp-quote key)))
+ (files (reftex-get-bibfile-list))
+ keys)
+ (if (and (eq (car latex-complete-bibtex-cache)
+ (reftex-get-bibfile-list))
+ (latex-string-prefix-p (nth 1 latex-complete-bibtex-cache)
+ key))
+ ;; Use the cache.
+ (setq keys (nth 2 latex-complete-bibtex-cache))
+ (dolist (file files)
+ (with-current-buffer (find-file-noselect file)
+ (goto-char (point-min))
+ (while (re-search-forward re nil t)
+ (goto-char (match-end 2))
+ (when (and (not (member-ignore-case (match-string 1)
+ '("c" "comment" "string")))
+ (looking-at bibtex-reference-key))
+ (push (match-string-no-properties 0) keys)))))
+ ;; Fill the cache.
+ (set (make-local-variable 'latex-complete-bibtex-cache)
+ (list files key keys)))
+ (complete-with-action action keys key pred)))))
+
+(defun latex-complete-envnames ()
+ (append latex-block-names latex-standard-block-names))
+
+(defun latex-complete-refkeys ()
+ (when (boundp 'reftex-docstruct-symbol)
+ (symbol-value reftex-docstruct-symbol)))
+
+(defvar latex-complete-alist
+ ;; TODO: Add \begin, \end, \ref, ...
+ '(("\\`\\\\\\(short\\)?cite\\'" . latex-complete-bibtex-keys)
+ ("\\`\\\\\\(begin\\|end\\)\\'" . latex-complete-envnames)
+ ("\\`\\\\[vf]?ref\\'" . latex-complete-refkeys)))
+
+(defun latex-complete-data ()
+ "Get completion-data at point."
+ (save-excursion
+ (let ((pt (point)))
+ (skip-chars-backward "^ {}\n\t\\\\")
+ (case (char-before)
+ ((nil ?\s ?\n ?\t ?\}) nil)
+ (?\\
+ ;; TODO: Complete commands.
+ nil)
+ (?\{
+ ;; Complete args to commands.
+ (let* ((cmd
+ (save-excursion
+ (forward-char -1)
+ (skip-chars-backward " \n")
+ (buffer-substring (point)
+ (progn
+ (skip-chars-backward "a-zA-Z@*")
+ (let ((n (skip-chars-backward "\\\\")))
+ (forward-char (* 2 (/ n 2))))
+ (point)))))
+ (start (point))
+ (_ (progn (goto-char pt) (skip-chars-backward "^," start)))
+ (comp-beg (point))
+ (_ (progn (goto-char pt) (skip-chars-forward "^, {}\n\t\\\\")))
+ (comp-end (point))
+ (table
+ (funcall
+ (let ((f (lambda () t)))
+ (dolist (comp latex-complete-alist)
+ (if (string-match (car comp) cmd)
+ (setq f (cdr comp))))
+ f))))
+ (if (eq table t)
+ ;; Unknown command.
+ nil
+ (list comp-beg comp-end table))))))))
+
+(defun latex-complete ()
+ "Perform completion at point for LaTeX mode.
+Return non-nil if we found what to complete."
+ (interactive)
+ (let ((data (latex-complete-data)))
+ (when data
+ (apply 'completion-in-region data)
+ t)))
+
+(defun latex-indent-or-complete ()
+ "Perform completion at point or indentation, according to DWIM.
+The heuristic is to try indentation, if that fails try completion,
+if that fails insert a tab."
+ (interactive)
+ (let ((undo buffer-undo-list)
+ (pos (point)))
+ (indent-according-to-mode)
+ (or (not (and (eq pos (point)) (eq undo buffer-undo-list)))
+ (latex-complete)
+ (insert-tab))))
+
;;;;
;;;; LaTeX syntax navigation
;;;;