# HG changeset patch # User Stefan Monnier # Date 1258671341 0 # Node ID cff2b8b6d64e581bc1819931f8b53fdafdeba3f6 # Parent 5e6998ac1a2e083a5ccfd5cbab30aeb632439647 (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. diff -r 5e6998ac1a2e -r cff2b8b6d64e lisp/ChangeLog --- a/lisp/ChangeLog Thu Nov 19 22:10:40 2009 +0000 +++ b/lisp/ChangeLog Thu Nov 19 22:55:41 2009 +0000 @@ -1,5 +1,12 @@ 2009-11-19 Stefan Monnier + * 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 -r 5e6998ac1a2e -r cff2b8b6d64e lisp/textmodes/tex-mode.el --- a/lisp/textmodes/tex-mode.el Thu Nov 19 22:10:40 2009 +0000 +++ b/lisp/textmodes/tex-mode.el Thu Nov 19 22:55:41 2009 +0000 @@ -1420,6 +1420,116 @@ \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 ;;;;