;;; expands tex-mode.el, distributed with Emacs 21.2.1, with ;;; ConTeXt awareness. ;;; NOTE: THIS MODE IS OBSOLETE, USE THE LATEST AUCTEX MODE WHICH HAS ;;; GOOD CONTEXT SUPPORT. ;;; Also has some functionality to make tex-mode more ;;; usable on systems without a unix shell like Win98 or NT. ;;; Has imenu and outline support. ;;; Created by Berend de Boer on 1999-may-12 ;;; ;;; Latest versions can be fount at: ;;; http://www.pobox.com/~berend/emacs/ ;;; Note: had to override tex-mode and tex-send-command, so be aware ;;; for updates in tex-mode.el that change these commands. They have ;;; to be copied to this file also. ;;; Usage: ;;; put context in your emacs site-lisp path, for example: ;;; /usr/local/share/emacs/site-lisp ;;; or ;;; c:\emacs\site-lisp ;;; ;;; add this command to your ~/.emacs file: ;;; (load "context") ;;; ;;; place this in your ~/.emacs file if you want context mode to be ;;; your default tex-mode: ;;; (setq tex-default-mode 'context-mode) ;;; ;;; If you want to use pdf viewing set this: ;;; (setq tex-output-extension ".pdf") ;;; (setq tex-dvi-view-command "acroread *") ;;; ;;; if you run a msdos shell (you use Win98/NT) to compile your ;;; tex/context files, this setting might be useful: ;;; (setq tex-using-dosshell t) ;;; ;;; This is useful if you want ispell to recognize your ConTeXt mode: ;;; (add-hook 'tex-mode-hook (function (lambda () (setq ispell-parser 'tex)))) ;;; Known bugs/todo: ;;; - tex-context-sections should probably be run after running the hook ;;; redefining the sections probably doesn't work for the first ;;; file in this manner. (require 'tex-mode) (require 'imenu) (require 'outline) ;;;###autoload (defcustom tex-using-dosshell nil "If t then assume dosshell so do path conversion from / to \\" :type 'boolean :group 'tex-run) ;;;###autoload ;; if you don't use texexec try "context -interaction=errorstopmode" ;; instead of texexec (defcustom context-run-command "texexec *" "*Command used to run ConTeXt subjob. ConTeXt Mode sets `tex-command' to this string. See the documentation of that variable." :type 'string :group 'tex-run) (defvar standard-context-nl-block-names '("achtergrond" "bijlagen" "buffer" "citaat" "combinatie" "encoding" "formule" "gegeven" "hoofdteksten" "inleidingen" "kadertekst" "kantlijn" "kleur" "kolommen" "legenda" "lokalevoetnoten" "mapping" "margeblok" "mode" "notmode" "omgeving" "onderdeel" "opelkaar" "opmaak" "opsomming" "positioneren" "produkt" "project" "raster" "regel" "regelcorrectie" "regelnummeren" "regels" "register" "smaller" "standaardopmaak" "tabel" "tabulatie" "tekst" "typen" "uitleidingen" "uitlijnen" "uitstellen" "verbergen") "Standard ConTeXt dutch block names.") (defvar standard-context-en-block-names '("alignment" "appendices" "background" "backmatter" "bodymatter" "bodypart" "buffer" "color" "columns" "combination" "component" "EIFFEL" "encoding" "environment" "extroductions" "fact" "FLOWcell" "FLOWchart" "formula" "framedtext" "frontmatter" "helptext" "hiding" "itemize" "JAVA" "JAVASCRIPT" "legend" "line" "linecorrection" "linenumbering" "lines" "localenvironment" "localfootnotes" "makeup" "mapping" "marginblock" "marginedge" "marginrule" "mode" "MP" "narrower" "notmode" "opposite" "packed" "PASCAL" "PERL" "positioning" "postponing" "product" "project" "quotation" "raster" "register" "SQL" "standardmakeup" "table" "tabulate" "TEX" "text" "typing" "unpacked" "XML") "Standard ConTeXt english block names.") ;;;###autoload (defcustom context-block-names nil "*User defined ConTeXt block names. Combined with `standard-context-en-block-names' for minibuffer completion." :type '(repeat string) :group 'tex-run) ;;;###autoload (defcustom tex-texutil-references-command "texutil --references" "*Command used to create a ConTeXt tuo file If this string contains an asterisk (`*'), that is replaced by the file name; otherwise, the file name, preceded by blank, is added at the end." :type 'string :group 'tex-run) ;;;###autoload (defcustom tex-texutil-figures-command "texutil --figures" "*Command used to create a ConTeXt texutil.tuf file which contains size information about pictures in the current directory." :type 'string :group 'tex-run) ;;;###autoload (defcustom tex-texutil-figures-command "texutil --figures *.png" "*Command used to create a ConTeXt texutil.tuf file which contains size information about all .png files in the current directory." :type 'string :group 'tex-run) ;;;###autoload (defcustom tex-output-extension ".dvi" "*User defined TeX output extension. Is for example .dvi or .pdf." :type 'string :group 'tex-run) ;;; dutch sections (defvar tex-context-nl-section-levels '( ("deel" . 0) ("hoofdstuk" . 1) ("paragraaf" . 2) ("subparagraaf" . 3) ("subsubparagraaf" . 4) ("subsubsubparagraaf" . 5) ("subsubsubsubparagraaf" . 6) )) ;;; english sections (defvar tex-context-en-section-levels '( ("part" . 0) ("chapter" . 1) ("title" . 1) ("section" . 2) ("subject" . 2) ("subsection" . 3) ("subsubsection" . 4) ("subsubsubsection" . 5) ("subsubsubsubsection" . 6) )) (defvar tex-context-nl-matter "\\\\\\(startinleidingen\\|starthoofdteksten\\|startbijlagen\\|startuitleidingen\\)\\b") (defvar tex-context-en-matter "\\\\\\(startfrontmatter\\|startbodymatter\\|startappendices\\|startbackmatter\\)\\b") ;;; outline support (defvar tex-context-en-outline-regexp "\\\\\\(start\\(frontmatter\\|bodymatter\\|appendices\\|backmatter\\)\\|chapter\\|\\(sub\\)*section\\)\\b") (defvar tex-context-nl-outline-regexp "\\\\\\(start\\(inleidingen\\|hoofdteksten\\|appendices\\|uitleidingen\\)\\|hoofdstuk\\|\\(sub\\)*paragraaf\\)\\b") (defvar tex-context-en-section-list '(("starttext" 1) ("startfrontmatter" 1) ("startbodymatter" 1) ("startbackmatter" 1) ("startappendices" 1) ("chapter" 2) ("subject" 2) ("section" 3) ("subsection" 4) ("subsubsection" 5)) "Alist of english sectioning commands and their relative level.") (defvar tex-context-nl-section-list '(("starttekst" 1) ("startinleidingen" 1) ("starthoofdteksten" 1) ("startuitleidingen" 1) ("startappendices" 1) ("hoofdstuk" 2) ("onderwerp" 2) ("paragraaf" 3) ("subparagraaf" 4) ("subsubparagraaf" 5)) "Alist of dutch sectioning commands and their relative level.") (defcustom tex-context-section-list tex-context-en-section-list "ConTeXt outline minor mode sections." :type '(repeat string) :group 'tex-run) (defun tex-context-outline-level () ;; Calculate level of current ConTeXt outline heading. (save-excursion (if (bobp) 0 (forward-char 1) (let* ((word (buffer-substring-no-properties (point) (progn (forward-word 1) (point)))) (entry (assoc word tex-context-section-list))) (if entry (nth 1 entry) 5))))) ;;;###autoload (defcustom standard-context-block-names standard-context-en-block-names "*Standard ConTeXt block names. Combined with `context-block-names' for minibuffer completion." :type '(repeat string) :group 'tex-run) (defcustom tex-context-section-levels tex-context-en-section-levels "Commands and levels used for defining sections in the document. The car of each cons cell is the name of the section macro. The cdr is a number indicating its level. A negative level means the same as the positive value, but the section will never get a number." :type '(repeat (cons (string :tag "sectioning macro" "") (number :tag "level " 0))) :group 'tex-run) (defvar tex-context-sections) (defcustom tex-context-matter tex-context-en-matter "ConTeXt text divisions like frontmatter, bodymatter, backmatter and such." :type 'string :group 'tex-run) ;;;###autoload (defcustom context-imenu-indent-string " . " "*String to add repeated in front of nested sectional units for Imenu." :type 'string :group 'tex) (defun context-imenu-create-index () "Generates an alist for imenu from a ConTeXt buffer." (let (i0 menu prev-pos) (save-excursion ;; Find the top-most level in this file but don't allow it to be ;; any deeper than "section" (which is top-level in an article). (goto-char (point-min)) (imenu-progress-message prev-pos 0) (if (search-forward-regexp "\\\\deel\\*?[ \t]*{" nil t) (setq i0 0) (if (search-forward-regexp "\\\\hoofdstuk\\*?[ \t]*{" nil t) (setq i0 1) (if (search-forward-regexp "\\\\part\\*?[ \t]*{" nil t) (setq i0 0) (if (search-forward-regexp "\\\\chapter\\*?[ \t]*{" nil t) (setq i0 1) (setq i0 2))))) ;; Look for chapters and sections. (goto-char (point-min)) (while (search-forward-regexp tex-context-sections nil t) (imenu-progress-message prev-pos nil t) (let ((start (match-beginning 0)) (here (point)) (i (cdr (assoc (buffer-substring-no-properties (match-beginning 1) (match-end 1)) tex-context-section-levels)))) (backward-char 1) (condition-case err (progn ;; Using sexps allows some use of matching {...} inside ;; titles. (forward-sexp 1) (setq menu (cons (cons (concat (apply 'concat (make-list (max 0 (- i i0)) context-imenu-indent-string)) (buffer-substring-no-properties here (1- (point)))) start) menu)) ) (error nil)))) ;; Look for included material. (goto-char (point-min)) (while (search-forward-regexp "\\\\\\(input\\|typefile\\|onderdeel||\component\\)[ \t]*{\\([^}\n]+\\)}" nil t) (setq menu (cons (cons (concat "<<" (buffer-substring-no-properties (match-beginning 2) (match-end 2)) (if (= (char-after (match-beginning 1)) ?b) ".bbl" ".tex")) (match-beginning 0)) menu))) ;; Look for \startinleidingen, \starthoofdteksten, \startbijlagen, and \startuitleidingen. (goto-char (point-min)) (while (search-forward-regexp tex-context-matter nil t) (setq menu (cons (cons "--" (match-beginning 0)) menu))) (imenu-progress-message prev-pos 100) ;; Sort in increasing buffer position order. (sort menu (function (lambda (a b) (< (cdr a) (cdr b))))) ) ) ) (defvar context-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map tex-mode-map) (define-key map "\C-c\C-t" 'tex-texutil-references-file) (define-key map "\C-c\C-o" 'tex-context-block) (define-key map "\C-c\C-e" 'tex-close-context-block) (define-key map "\C-c\C-u" 'tex-goto-last-unclosed-context-block) (define-key map "\C-c\C-t" 'tex-texutil-references-file) (define-key map "\C-c/" 'tex-close-xml-tag) map) "Keymap for `context-mode'. See also `tex-mode-map'.") ;; mode hook (defvar context-mode-hook nil "List of functions to call when entering ConTeXt mode.") ;;; I needed to override tex-mode, else always plain-tex-mode would be used ;;; when loading a ConTeXt file. Now if you set tex-default-mode to ;;; context-mode, ConTeXt is the default when it is not a LaTeX file. ;;; ;;; This would be a lot simpler if we just used a regexp search, ;;; but then it would be too slow. ;;;###autoload (defun tex-mode () "Major mode for editing files of input for TeX, ConTeXt, LaTeX, or SliTeX. Tries to determine (by looking at the beginning of the file) whether this file is for plain TeX, ConTeXt, LaTeX, or SliTeX and calls `tex-default-mode', `context-mode', `latex-mode', or `slitex-mode', respectively. If it cannot be determined, such as if there are no commands in the file, the value of `tex-default-mode' says which mode to use." (interactive) (let ((mode tex-default-mode) slash comment) (save-excursion (goto-char (point-min)) (while (and (setq slash (search-forward "\\" nil t)) (setq comment (let ((search-end (point))) (save-excursion (beginning-of-line) (search-forward "%" search-end t)))))) (when (and slash (not comment)) (setq mode (if (looking-at (eval-when-compile (concat (regexp-opt '("documentstyle" "documentclass" "begin" "section" "part" "chapter") 'words) "\\|NeedsTeXFormat{LaTeX"))) (if (looking-at "document\\(style\\|class\\)\\(\\[.*\\]\\)?{slides}") 'slitex-mode 'latex-mode) tex-default-mode)))) (funcall mode))) ;;;###autoload ;; 'inherit' from plain-tex-mode or text-mode?? (define-derived-mode context-nl-mode text-mode "ConTeXt-nl" "Major mode for editing files of input for ConTeXt. Makes $ and } display the characters they match. Makes \" insert `` when it seems to be the beginning of a quotation, and '' when it appears to be the end; it inserts \" only after a \\. Use \\[tex-region] to run ConTeXt on the current region, plus a \"header\" copied from the top of the file (containing macro definitions, etc.), running ConTeXt under a special subshell. \\[tex-buffer] does the whole buffer. \\[tex-file] saves the buffer and then processes the file. \\[tex-print] prints the .dvi file made by any of these. \\[tex-view] previews the .dvi file made by any of these. \\[tex-bibtex-file] runs bibtex on the file of the current buffer. Use \\[validate-tex-buffer] to check buffer for sections containing mismatched $'s or braces. Special commands: \\{tex-mode-map} Mode variables: context-run-command Command string used by \\[tex-region] or \\[tex-buffer]. tex-directory Directory in which to create temporary files for TeX jobs run by \\[tex-region] or \\[tex-buffer]. tex-dvi-print-command Command string used by \\[tex-print] to print a .dvi file. tex-alt-dvi-print-command Alternative command string used by \\[tex-print] (when given a prefix argument) to print a .dvi file. tex-dvi-view-command Command string used by \\[tex-view] to preview a .dvi file. tex-show-queue-command Command string used by \\[tex-show-print-queue] to show the print queue that \\[tex-print] put your job on. Entering ConTeXt-tex mode runs the hook `text-mode-hook', then the hook `tex-mode-hook', and finally the hook `context-mode-hook'. When the special subshell is initiated, the hook `tex-shell-hook' is run." (tex-common-initialization) (setq tex-command context-run-command) (setq tex-start-of-header "%\\*\\*start of header") (setq tex-end-of-header "\\\\starttekst") (setq tex-trailer "\\stoptekst\n") ;; A line containing just $$ is treated as a paragraph separator. ;; A line starting with $$ starts a paragraph, ;; but does not separate paragraphs if it has more stuff on it. (setq paragraph-start "[ \t]*$\\|[\f%]\\|[ \t]*\\$\\$\\|\ [ \t]*\\\\start[a-z]*\\|[ \t]*\\\\stop[a-z]*\\|\ \\\\plaats[a-z]*\\|\\\\\\[\\|\\\\\\]\\|\ \\\\hoofdstuk\\>\\|\\\\paragraaf\\>\\|\ \\\\subparagraaf\\>\\|\\\\subsubparagraaf\\>\\|\ \\\\subsubsubparagraaf\\>\\|\\\\subsubsubsubparagraaf\\>\\|\ [ \t]*\\\\som\\>\\|\\\\noindent\\>\\|\ \\\\pagina\\>\\|\\\\voetnoot\\>") (setq paragraph-separate "[ \t]*$\\|[\f%]\\|[ \t]*\\$\\$[ \t]*$\\|\ [ \t]*\\\\start[a-z]*\\|[ \t]*\\\\stop[a-z]*\\|\ \\\\plaats[a-z]*\\|\\\\\\[\\|\\\\\\]\\|\ \\\\hoofdstuk\\>\\|\\\\paragraaf\\>\\|\ \\\\subparagraaf\\>\\|\\\\subsubparagraaf\\>\\|\ \\\\subsubsubparagraaf\\>\\|\\\\subsubsubsubparagraaf\\>\\|\ \\([ \t]*\\\\som\\)[ \t]*\\($\\|%\\)") ;; " (use-local-map context-mode-map) (make-local-variable 'imenu-create-index-function) (setq imenu-create-index-function 'context-imenu-create-index) (make-local-variable 'standard-context-block-names) ;;(context-define-keys) (setq tex-context-section-levels tex-context-nl-section-levels) (setq tex-context-sections (concat "\\\\\\(" (mapconcat 'car tex-context-section-levels "\\|") "\\)[ \t]*\\(\\[[^]]*\\]\\)?{")) (setq standard-context-block-names standard-context-nl-block-names) (setq tex-context-matter tex-context-nl-matter) ;; menu additions (define-key tex-mode-map [menu-bar tex context] (cons "ConTeXt" (make-sparse-keymap "ConTeXt"))) (define-key tex-mode-map [menu-bar tex context tex-mktexlsr] '("Maak TeX hash" . tex-mktexlsr)) (define-key tex-mode-map [menu-bar tex context tex-texexec-make] '("Maak format files" . tex-texexec-make)) (define-key tex-mode-map [menu-bar tex context tex-texexec-make-metafun] '("Maak metafun format" . tex-texexec-make-metafun)) (define-key tex-mode-map [menu-bar tex context tex-texutil-references-file] '("TeXUtil --references" . tex-texutil-references-file)) (define-key tex-mode-map [menu-bar tex context context-nl-mode] '("ConTeXt dutch interface" . context-nl-mode)) (define-key tex-mode-map [menu-bar tex context context-en-mode] '("ConTeXt english interface" . context-en-mode)) (define-key tex-mode-map [menu-bar tex context imenu-add-menubar-index] '("Build imenu" . imenu-add-menubar-index)) ;; indent support (set (make-local-variable 'indent-line-function) 'context-indent) (set (make-local-variable 'fill-indent-according-to-mode) t) ;; outline support (setq outline-regexp tex-context-nl-outline-regexp) (setq tex-context-section-list tex-context-nl-section-list) (make-local-variable 'outline-level) (setq outline-level 'tex-context-outline-level) (run-hooks 'text-mode-hook 'tex-mode-hook 'context-mode-hook)) ;; context english mode (define-derived-mode context-en-mode text-mode "ConTeXt-en" "Major mode for editing files of input for ConTeXt. Makes $ and } display the characters they match. Makes \" insert `` when it seems to be the beginning of a quotation, and '' when it appears to be the end; it inserts \" only after a \\. Use \\[tex-region] to run ConTeXt on the current region, plus a \"header\" copied from the top of the file (containing macro definitions, etc.), running ConTeXt under a special subshell. \\[tex-buffer] does the whole buffer. \\[tex-file] saves the buffer and then processes the file. \\[tex-print] prints the .dvi file made by any of these. \\[tex-view] previews the .dvi file made by any of these. \\[tex-bibtex-file] runs bibtex on the file of the current buffer. Use \\[validate-tex-buffer] to check buffer for paragraphs containing mismatched $'s or braces. Special commands: \\{tex-mode-map} Mode variables: context-run-command Command string used by \\[tex-region] or \\[tex-buffer]. tex-directory Directory in which to create temporary files for TeX jobs run by \\[tex-region] or \\[tex-buffer]. tex-dvi-print-command Command string used by \\[tex-print] to print a .dvi file. tex-alt-dvi-print-command Alternative command string used by \\[tex-print] (when given a prefix argument) to print a .dvi file. tex-dvi-view-command Command string used by \\[tex-view] to preview a .dvi file. tex-show-queue-command Command string used by \\[tex-show-print-queue] to show the print queue that \\[tex-print] put your job on. Entering ConTeXt-tex mode runs the hook `text-mode-hook', then the hook `tex-mode-hook', and finally the hook `context-mode-hook'. When the special subshell is initiated, the hook `tex-shell-hook' is run." ;; had to disable this for emacs20?? need to retest with emacs21. (tex-common-initialization) (setq tex-command context-run-command) (setq tex-start-of-header "%\\*\\*start of header") (setq tex-end-of-header "\\\\starttext") (setq tex-trailer "\\stoptext\n") ;; A line containing just $$ is treated as a paragraph separator. ;; A line starting with $$ starts a paragraph, ;; but does not separate paragraphs if it has more stuff on it. (setq paragraph-start (concat "[\f%]\\|[ \t]*\\($\\|\\$\\$\\|" "\\\\[][]\\|" "\\\\" (regexp-opt (append (mapcar 'car tex-context-en-section-levels) '("item" "crlf" "page" "footnote" "NR" "SR" "FR" "MR" "blank")) t) "\\>\\|\\\\start[a-zA-Z]*\\|\\\\stop[a-zA-Z]*" "\\>\\)")) (setq paragraph-separate (concat "[\f%]\\|[ \t]*\\($\\|" "\\\\[][]\\|" "\\\\" (regexp-opt (append (mapcar 'car tex-context-en-section-levels) '("start" "stop" )) t) "\\>\\|\\\\\\(" (regexp-opt '("item" "crlf" "blank" "page" "footnote")) "\\|\\$\\$\\|\\\\start[a-zA-Z]*\\|\\\\stop[a-zA-Z]*\\|place[a-zA-Z]*" "\\>\\)[ \t]*\\($\\|%\\)\\)")) ;; (setq paragraph-start "[ \t]*$\\|[\f%]\\|[ \t]*\\$\\$\\|\ ;; [ \t]*\\\\start[a-z]*\\|[ \t]*\\\\stop[a-z]*\\|\ ;; \\\\place[a-z]*\\|\\\\\\[\\|\\\\\\]\\|\ ;; \\\\chapter\\>\\|\\\\section\\>\\|\ ;; \\\\subsection\\>\\|\\\\subsubsection\\>\\|\ ;; \\\\subsubsubsection\\>\\|\\\\subsubsubsubsection\\>\\|\ ;; [ \t]*\\\\item\\>\\|\\\\noindent\\>\\|\ ;; \\\\page\\>\\>") ;; (setq paragraph-separate "[ \t]*$\\|[\f%]\\|[ \t]*\\$\\$[ \t]*$\\|\ ;; [ \t]*\\\\start[a-z]*\\|[ \t]*\\\\stop[a-z]*\\|\ ;; \\\\place[a-z]*\\|\\\\\\[\\|\\\\\\]\\|\ ;; \\\\chapter\\>\\|\\\\section\\>\\|\ ;; \\\\subsection\\>\\|\\\\subsubparagraaf\\>\\|\ ;; \\\\subsubsubsection\\>\\|\\\\subsubsubsubsection\\>\\|\ ;; \\([ \t]*\\\\item\\)[ \t]*\\($\\|%\\)") ;; " (make-local-variable 'imenu-create-index-function) (setq imenu-create-index-function 'context-imenu-create-index) (use-local-map context-mode-map) (setq tex-context-section-levels tex-context-en-section-levels) (setq tex-context-sections (concat "\\\\\\(" (mapconcat 'car tex-context-section-levels "\\|") "\\)[ \t]*\\(\\[[^]]*\\]\\)?{")) (setq standard-context-block-names standard-context-en-block-names) (setq tex-context-matter tex-context-en-matter) ;; menu additions (define-key tex-mode-map [menu-bar tex context] (cons "ConTeXt" (make-sparse-keymap "ConTeXt"))) (define-key tex-mode-map [menu-bar tex context tex-mktexlsr] '("Rebuild TeX hash" . tex-mktexlsr)) (define-key tex-mode-map [menu-bar tex context tex-texexec-make] '("Make format files" . tex-texexec-make)) (define-key tex-mode-map [menu-bar tex context tex-texexec-make-metafun] '("Make metafun format" . tex-texexec-make-metafun)) (define-key tex-mode-map [menu-bar tex context tex-texutil-references-file] '("TeXUtil --references" . tex-texutil-references-file)) (define-key tex-mode-map [menu-bar tex context context-nl-mode] '("ConTeXt dutch interface" . context-nl-mode)) (define-key tex-mode-map [menu-bar tex context context-en-mode] '("ConTeXt english interface" . context-en-mode)) (define-key tex-mode-map [menu-bar tex context imenu-add-menubar-index] '("Build imenu" . imenu-add-menubar-index)) ;; indent support (set (make-local-variable 'indent-line-function) 'context-indent) (set (make-local-variable 'fill-indent-according-to-mode) t) ;; outline support (setq outline-regexp tex-context-en-outline-regexp) (setq tex-context-section-list tex-context-en-section-list) (make-local-variable 'outline-level) (setq outline-level 'tex-context-outline-level) (run-hooks 'text-mode-hook 'tex-mode-hook 'context-mode-hook)) ;;;###autoload (defalias 'context-mode 'context-en-mode) (defalias 'ConTeXt-mode 'context-en-mode) (defvar context-block-default "itemize") ;;; Like tex-insert-braces, but for ConTeXt. (define-skeleton tex-context-block "Create a matching pair of lines \\startNAME[OPT] and \\stopNAME at point. Puts point on a blank line between them." (let ((choice (completing-read (format "ConTeXt block name [%s]: " context-block-default) (mapcar 'list (append standard-context-block-names context-block-names)) nil nil nil nil context-block-default))) (setq context-block-default choice) (unless (or (member choice standard-context-block-names) (member choice context-block-names)) ;; Remember new block names for later completion. (push choice context-block-names)) choice) "\\start" str ?\[ (skeleton-read "[options]: ") & ?\] | -1 \n (beginning-of-line) _ \n "\\stop" str (context-indent)) ;; (completing-read "ConTeXt block name: " ;; (mapcar 'list ;; (append standard-context-block-names ;; context-block-names))) (defun tex-last-unended-start () "Leave point at the beginning of the last `\\start...' that is unstopped." (while (and (re-search-backward "\\\\start[a-zA-Z]*\\|\\\\stop[a-zA-Z]*") (looking-at "\\\\stop[a-zA-Z]*")) (tex-last-unended-start))) (defun tex-close-context-block () "Creates an \\stop... to match the last unclosed \\start...." (interactive "*") (let ((new-line-needed (bolp)) text indentation) (save-excursion (condition-case nil (tex-last-unended-start) (error (error "Couldn't find unended \\start"))) (setq indentation (current-column)) (re-search-forward "\\\\start[a-zA-Z]*") (setq text (buffer-substring (+ (match-beginning 0) 6) (match-end 0)))) (indent-to indentation) (insert "\\stop" text) (if new-line-needed (insert ?\n)))) (defun tex-goto-last-unclosed-context-block () "Move point to the last unclosed \\start.... Mark is left at original location." (interactive) (let ((spot)) (save-excursion (condition-case nil (tex-last-unended-start) (error (error "Couldn't find unended \\start"))) (setq spot (point))) (push-mark) (goto-char spot))) (defun tex-texutil-references-file () "Run texutil --references on the current buffer's file." (interactive) (if (tex-shell-running) (tex-kill-job) (tex-start-shell)) (let (shell-dirtrack-verbose (tex-out-file (tex-append (file-name-nondirectory (buffer-file-name)) "")) (file-dir (file-name-directory (buffer-file-name)))) (tex-send-command tex-shell-cd-command file-dir) (tex-send-command tex-texutil-references-command tex-out-file)) (tex-display-shell)) (defun tex-texexec-make () "Run texexec --make." (interactive) (if (tex-shell-running) (tex-kill-job) (tex-start-shell)) (let (shell-dirtrack-verbose (tex-out-file (tex-append (file-name-nondirectory (buffer-file-name)) "")) (file-dir (file-name-directory (buffer-file-name)))) (tex-send-command tex-shell-cd-command file-dir) (tex-send-command "texexec" "--make")) (tex-display-shell)) (defun tex-texexec-make-metafun () "Run texexec --make metafun." (interactive) (if (tex-shell-running) (tex-kill-job) (tex-start-shell)) (let (shell-dirtrack-verbose (tex-out-file (tex-append (file-name-nondirectory (buffer-file-name)) "")) (file-dir (file-name-directory (buffer-file-name)))) (tex-send-command tex-shell-cd-command file-dir) (tex-send-command "texexec" "--make metafun")) (tex-display-shell)) (defun tex-mktexlsr () "Run mktexlsr." (interactive) (if (tex-shell-running) (tex-kill-job) (tex-start-shell)) (let (shell-dirtrack-verbose (tex-out-file (tex-append (file-name-nondirectory (buffer-file-name)) "")) (file-dir (file-name-directory (buffer-file-name)))) (tex-send-command tex-shell-cd-command file-dir) (tex-send-command "mktexlsr")) (tex-display-shell)) ;; enable the following command (defun tex-send-command (command &optional file background) "Send COMMAND to TeX shell process, substituting optional FILE for *. Do this in background if optional BACKGROUND is t. If COMMAND has no *, FILE will be appended, preceded by a blank, to COMMAND. If FILE is nil, no substitution will be made in COMMAND. COMMAND can be any expression that evaluates to a command string. Return the process in which TeX is running." (save-excursion (if (and file tex-using-dosshell) (while (string-match "/" file) (aset file (match-beginning 0) ?\\))) (if (and file tex-using-dosshell) (setq file (concat "\"" file "\""))) (let* ((cmd (eval command)) (proc (or (get-process "tex-shell") (error "No TeX subprocess"))) (buf (process-buffer proc)) (star (string-match "\\*" cmd)) (string (concat (if file (if star (concat (substring cmd 0 star) file (substring cmd (1+ star))) (concat cmd " " file)) cmd) (if background "&" "")))) ;; Switch to buffer before checking for subproc output in it. (set-buffer buf) ;; If text is unchanged since previous tex-send-command, ;; we haven't got any output. So wait for output now. (if (= (buffer-modified-tick buf) tex-send-command-modified-tick) (accept-process-output proc)) (goto-char (process-mark proc)) (insert string) (comint-send-input) (setq tex-send-command-modified-tick (buffer-modified-tick buf)) proc))) ;; the following redefinition makes sure the cd command is quoted, so ;; spaces in directory names happen to work. (defun tex-file () "Prompt to save all buffers and run TeX (or ConTeXt) on current buffer's file. This function is more useful than \\[tex-buffer] when you need the `.aux' file of LaTeX to have the correct name." (interactive) (let ((source-file (or tex-main-file (if (buffer-file-name) (file-name-nondirectory (buffer-file-name)) (error "Buffer does not seem to be associated with any file")))) (file-dir (file-name-directory (buffer-file-name)))) (if tex-offer-save (save-some-buffers)) (if (tex-shell-running) (tex-kill-job) (tex-start-shell)) (let (shell-dirtrack-verbose) (tex-send-command (concat tex-shell-cd-command " \"" file-dir "\""))) (tex-start-tex tex-command source-file) (tex-display-shell) (setq tex-last-buffer-texed (current-buffer)) (setq tex-print-file (expand-file-name source-file)))) ;; the following redefinition of tex-print makes the extension ;; settable to be .pdf or .dvi (defun tex-print (&optional alt) "Print the .dvi file made by \\[tex-region], \\[tex-buffer] or \\[tex-file]. Runs the shell command defined by `tex-dvi-print-command'. If prefix argument is provided, use the alternative command, `tex-alt-dvi-print-command'." (interactive "P") (let ((print-file-name-dvi (tex-append tex-print-file tex-output-extension)) test-name) (if (and (not (equal (current-buffer) tex-last-buffer-texed)) (buffer-file-name) ;; Check that this buffer's printed file is up to date. (file-newer-than-file-p (setq test-name (tex-append (buffer-file-name) tex-output-extension)) (buffer-file-name))) (setq print-file-name-dvi test-name)) (if (not (file-exists-p print-file-name-dvi)) (error (concat "No appropriate `" tex-output-extension "' file could be found")) (if (tex-shell-running) (tex-kill-job) (tex-start-shell)) (tex-send-command (if alt tex-alt-dvi-print-command tex-dvi-print-command) print-file-name-dvi t)))) ;; XML inside ConTeXt support (defun tex-last-unended-start-xml () "Leave point at the beginning of the last `tag' that is unstopped." (while (and (re-search-backward "<[_A-Za-z][-:._A-Za-z0-9]*\\([ \t\r\n]\\|[_A-Za-z][-:._A-Za-z0-9]*\=\"[^\"]*\"\\)*>\\|") (looking-at "")) (tex-last-unended-start-xml))) (defun tex-close-xml-tag () "Creates an to match the last unclosed <...>. Not fool-proof." (interactive "*") (let ((new-line-needed (bolp)) text indentation) (save-excursion (condition-case nil (tex-last-unended-start-xml) (error (error "Couldn't find unended XML tag"))) (setq indentation (current-column)) (re-search-forward "<\\([_A-Za-z][-:._A-Za-z0-9]*\\)") (setq text (buffer-substring (match-beginning 1) (match-end 1))) ) (indent-to indentation) (insert "") (if new-line-needed (insert ?\n)) ) ) ;;;; ;;;; ConTeXt indentation ;;;; Code copied from LaTeX indentation and hacked. No idea what it does. ;;;; What's multi-char element?? ;;;; (defun context-syntax-after () "Like (char-syntax (char-after)) but aware of multi-char elements." (if (looking-at "\\\\stop[a-zA-Z]*\\>") ?\) (char-syntax (following-char)))) (defun context-skip-close-parens () "Like (skip-syntax-forward \" )\") but aware of multi-char elements." (let ((forward-sexp-function nil)) (while (progn (skip-syntax-forward " )") (looking-at "\\\\stop[a-zA-Z]*\\>")) (forward-sexp 2)))) (defun context-backward-sexp-1 () "Like (backward-sexp 1) but aware of multi-char elements." (let ((pos (point)) (forward-sexp-function)) (backward-sexp 1) (if (looking-at "\\\\start[a-zA-Z]*\\>") (signal 'scan-error (list "Containing expression ends prematurely" (point) (prog1 (point) (goto-char pos)))) (when (eq (char-after) ?{) (let ((newpos (point))) (when (ignore-errors (backward-sexp 1) t) (if (looking-at "\\\\stop[a-zA-Z]\\>") (tex-last-unended-begin) (goto-char newpos)))))))) (defun context-down-list () "Like (down-list 1) but aware of multi-char elements." (forward-comment (point-max)) (let ((forward-sexp-function nil)) (if (not (looking-at "\\\\start[a-zA-Z]\\>")) (down-list 1) (forward-sexp 1) ;; Skip arguments. (while (looking-at "[ \t]*\\s(") (forward-sexp))))) (defvar tex-context-indent-allhanging t) (defvar tex-context-indent-arg 2) (defvar tex-context-indent-basic 2) (defvar tex-context-indent-item tex-context-indent-basic) (defvar tex-context-indent-item-re "\\\\\\\(item\\|setup[a-zA-Z]*\\)\\>") (easy-mmode-defsyntax tex-context-indent-syntax-table '((?$ . ".") (?\( . ".") (?\) . ".")) "Syntax table used while computing indentation." :copy tex-mode-syntax-table) (defun context-indent (&optional arg) (with-syntax-table tex-context-indent-syntax-table ;; TODO: Rather than ignore $, we should try to be more clever about it. (let ((indent (save-excursion (beginning-of-line) (context-find-indent)))) (if (< indent 0) (setq indent 0)) (if (<= (current-column) (current-indentation)) (indent-line-to indent) (save-excursion (indent-line-to indent)))))) (defun context-find-indent (&optional virtual) "Find the proper indentation of text after point. VIRTUAL if non-nil indicates that we're only trying to find the indentation in order to determine the indentation of something else. There might be text before point." (save-excursion (skip-chars-forward " \t") (or ;; Trust the current indentation, if such info is applicable. (and virtual (>= (current-indentation) (current-column)) (current-indentation)) ;; Put leading close-paren where the matching open brace would be. (and (eq (context-syntax-after) ?\)) (ignore-errors (save-excursion (context-skip-close-parens) (context-backward-sexp-1) (context-find-indent 'virtual)))) ;; Default (maybe an argument) (let ((pos (point)) (char (char-after)) ;; Outdent \item if necessary. (indent (if (looking-at tex-context-indent-item-re) (- tex-context-indent-item) 0)) up-list-pos) ;; Find the previous point which determines our current indentation. (condition-case err (progn (context-backward-sexp-1) (while (> (current-column) (current-indentation)) (context-backward-sexp-1))) (scan-error (setq up-list-pos (nth 2 err)))) (cond ((= (point-min) pos) 0) ; We're really just indenting the first line. ((integerp up-list-pos) ;; Have to indent relative to the open-paren. (goto-char up-list-pos) (if (and (not tex-context-indent-allhanging) (> pos (progn (context-down-list) (forward-comment (point-max)) (point)))) ;; Align with the first element after the open-paren. (current-column) ;; We're the first element after a hanging brace. (goto-char up-list-pos) (+ indent tex-context-indent-basic (context-find-indent 'virtual)))) ;; We're now at the "beginning" of a line. ((not (and (not virtual) (eq (char-after) ?\\))) ;; Nothing particular here: just keep the same indentation. (+ indent (current-column))) ;; We're now looking at a macro call. ((looking-at tex-context-indent-item-re) ;; Indenting relative to an item, have to re-add the outdenting. (+ indent (current-column) tex-context-indent-item)) (t (let ((col (current-column))) (if (not (eq (char-syntax char) ?\()) ;; If the first char was not an open-paren, there's ;; a risk that this is really not an argument to the ;; macro at all. (+ indent col) (forward-sexp 1) (if (< (line-end-position) (save-excursion (forward-comment (point-max)) (point))) ;; we're indenting the first argument. (min (current-column) (+ tex-context-indent-arg col)) (skip-syntax-forward " ") (current-column)))))))))) ;; allow users to (require 'context) (provide 'context) ;;; context.el ends here