diff options
Diffstat (limited to 'Build/source/texk/xdvik/xdvi-search.el')
-rw-r--r-- | Build/source/texk/xdvik/xdvi-search.el | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/Build/source/texk/xdvik/xdvi-search.el b/Build/source/texk/xdvik/xdvi-search.el new file mode 100644 index 00000000000..75e86d3bb35 --- /dev/null +++ b/Build/source/texk/xdvik/xdvi-search.el @@ -0,0 +1,345 @@ +;;; (X)Emacs frontend to forward search with xdvi(k). +;;; Requires xdvi(k) >= 22.38. +;;; +;;; See http://xdvi.sourceforge.net/inverse-search.html and the section +;;; `FORWARD SEARCH' in the xdvi man page for more information on forward search. +;;; +;;; This file is available from: http://xdvi.sourceforge.net/xdvi-search.el +;;; +;;; $Revision: 1.15.2.43 $, tested with Emacs 20.4 to 21.2 and Xemacs 21.1 to 21.5 +;;; +;;; This program is free software; you can redistribute it and/or +;;; modify it under the terms of the GNU General Public License +;;; as published by the Free Software Foundation; either version 2 +;;; of the License, or (at your option) any later version. +;;; +;;; This program is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with this program; if not, write to the Free Software +;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +;;; +;;; +;;; Usage: +;;; +;;; - Add this file to some place where emacs can find it +;;; (e.g. put it into a directory ~/emacs/, which you add to your +;;; load path by putting the following line into your .emacs file: +;;; +;;; (add-to-list 'load-path (expand-file-name "~/emacs/")) +;;; +;;; Then, add the following line to your .emacs file: +;;; +;;; (require 'xdvi-search) +;;; +;;; After compiling your .tex file with source specials activated, you should +;;; be able to use +;;; M-x xdvi-jump-to-line +;;; to make xdvi jump to the current location of the cursor. +;;; +;;; You could also bind this command to a key, e.g. by adding +;;; a binding to tex-mode-hook: +;;; +;;; (add-hook 'tex-mode-hook (lambda () +;;; (local-set-key "\C-c\C-j" 'xdvi-jump-to-line))) +;;; +;;; (without AucTeX; use LaTeX-mode-hook instead of tex-mode-hook with AucTeX. +;;; Note that with AucTeX, C-c C-j is already bound to LaTeX-insert-item, so +;;; you might want to use a different key combination instead.) +;;; +;;; - Note that with xdvik < 22.74.2, you may need to use one of the +;;; functions xdvi-jump-to-line-fullpath() or xdvi-jump-to-line-relpath() +;;; instead of xdvi-jump-to-line(), depending on the type of paths contained +;;; in your \include{} commands. See the docstring of xdvi-jump-to-line() +;;; for more information. +;;; +;;; Please send bug reports, improvements etc. to +;;; <stefanulrich@users.sourceforge.net>. +;;; + + +;;; +;;; Customizable stuff +;;; +(defgroup xdvi-search nil + "Support for inverse search with (La)TeX and DVI previewers." + :group 'languages) + +(defcustom explicit-shell-file-name nil + "*If non-nil, file name to use for explicitly requested inferior shell." + :type '(choice (const :tag "nil" nil) file) + :group 'xdvi-search) + +(defcustom xdvi-bin "xdvi" + "*Name of the xdvi executable." + :type '(choice (const "xdvi") file) + :group 'xdvi-search) + +(defcustom xdvi-logfile "~/.xdvi-log" + "*Write xdvi output to this file, or throw away output if set to nil." + :type '(choice (const :tag "nil" nil) file) + :group 'xdvi-search) + + +;;; +;;; global variables/constants +;;; +(defvar xdvi-version-number 0 + "*Version of xdvi(k) you're using; only set this to override the built-in +version recognition if that fails. +The version number is computed as: major * 1000000 + minor * 1000 + patchlevel, +where alphabetic characters are ignored; e.g. 22040000 equals version 22.40c; + 22077002 equals version 22.77.2.") + +(defvar xdvi-is-xdvik nil + "Whether we're really using xdvik instead of xdvi.") + +(defconst xdvik-new-search-version 22074001 + "First version of xdvik to implement new search algorithm that ignores .tex suffixes and +has a -nofork option.") + + +;;; +;;; exported functions +;;; +(defun xdvi-jump-to-line-fullpath () + (interactive) + "See `xdvi-jump-to-line' for documentation." + (xdvi-jump-to-line 3)) + +(defun xdvi-jump-to-line-relpath () + (interactive) + "See `xdvi-jump-to-line' for documentation." + (xdvi-jump-to-line 2)) + +(defun xdvi-jump-to-line (flag) + "Call xdvi to perform a `forward search' for current file and line number. +Xdvi needs three pieces of information for this: + +- the current line number +- the name of the current input file +- the name of the master .tex file. + +The `master' .tex file (following AucTeX's terminology) is the same +as `\jobname' and determines the name of the DVI file. It is either +obtained by using AucTeX's function `TeX-master-file' or, in case +AucTeX isn't available, by calling `xdvi-master-file-name', a function +which tries to mimick AucTeX's behaviour to obtain this filename. + +For the current input file name, we need to rely on the DVI viewer to +make a smart matching of path suffixes with the file names that +actually occur in the specials, since specials inserted by TeX's +`-src' option may contain absolute or relative paths, depending on +whether TeX is called with a relative or absolute filename. (Similarly +for srcltx.sty, which can't expand paths.) + +Note to users of older versions of xdvik (< 22.74.2), or non-k xdvi: + +There are various ways of specifying an input file path for LaTeX's +\\input{} commands (which will end up in the source specials): + + (1) Filename only: \\input{chapter1} + (2) Relative path name: \\input{chapters/chapter1} + (3) Full path name: \\input{/home/user/tex/diss/chapters/chapter1} + +Versions of xdvik < 22.74.2 and plain xdvi will not match pathname suffixes. +With these versions, `xdvi-jump-to-line' will only work with variant (1); +for (2) or (3) you will need to use one of `xdvi-jump-to-line-relpath' (for 2) +or `xdvi-jump-to-line-fullpath' (for 3) instead. +" + (interactive "P") + (save-excursion + (save-restriction + (widen) + (beginning-of-line 1) + (if (not flag) + (setq flag 1)) + (let* (;;; Current line in file. + ;;; `count-lines' yields different results at beginning and in the + ;;; middle of a line, so we normalize by going to BOL first and + ;;; then adding 1 + (curr-line (+ 1 (count-lines (point-min) (point)))) + ;;; name of master .tex file, to be used as DVI basename: + (master-file (if (fboundp 'TeX-master-file) + (TeX-master-file t) + (xdvi-get-masterfile (xdvi-master-file-name)))) + (xdvi-version-info (xdvi-get-version-number xdvi-version-number)) + ;;; DVI file name: + (dvi-file (concat (file-name-sans-extension master-file) ".dvi")) + ;;; Current source filename + (filename (get-source-filename (buffer-file-name) (car xdvi-version-info) flag))) + (if (xdvi-has-no-inverse-search (car xdvi-version-info)) + (error "Your xdvi version is too old; see http://xdvi.sourceforge.net/inverse-search.html for more information.")) + (if (not (file-exists-p dvi-file)) + (message "File %s does not exist; maybe you need to run latex first?" dvi-file) + (save-window-excursion + (if (xdvi-has-nofork (car xdvi-version-info) (car (cdr xdvi-version-info))) + (progn + (setq proc + (start-process "xdvi" "*xdvi output*" + xdvi-bin + "-nofork" + "-sourceposition" + (concat (int-to-string curr-line) " " filename) + dvi-file)) + (set-process-sentinel proc 'xdvi-process-sentinel)) + ;;; + ;;; More complicated if we don't have nofork: start a + ;;; subshell, since otherwise there's no way of viewing + ;;; the stderr/stdout output of the xdvi child process + ;;; without having either xdvi freezing, Emacs freezing, + ;;; or Emacs killing the xdvi child process (which is + ;;; forked when running with -sourceposition). + ;;; + ;;; Obtain the type of I/O-redirection needed for current shell: + (let* ((default-shell + (or (and (boundp 'explicit-shell-file-name) explicit-shell-file-name) + (getenv "ESHELL") + (getenv "SHELL") + "/bin/sh")) + (shell-redirection + (cond ((string-match "/bin/t?csh" default-shell) + (list ">&" "")) + ;; bash/ksh/sh + ((list ">" "2>&1"))))) + (cond ((string-match "XEmacs" emacs-version) + (shell)) + ((< emacs-major-version 21) + (shell)) + ((shell "*xdvi-shell*"))) + (comint-send-input) + (insert xdvi-bin + " -sourceposition '" (int-to-string curr-line) " " filename "' " + dvi-file + " " + ;;; we could probably do without the logfile, but it's an easy + ;;; way for toggling between /dev/null and logging. + (if xdvi-logfile + (let ((xdvi-logfile-fullname (expand-file-name xdvi-logfile))) + ;;; to avoid problems with `noclobber' + (if (file-exists-p xdvi-logfile-fullname) + (delete-file xdvi-logfile-fullname)) + (car shell-redirection) + " " + xdvi-logfile-fullname + " " + (car (cdr shell-redirection)) + ) + ) + " &") + (if xdvi-logfile + (message "Writing xdvi output to \"%s\"." xdvi-logfile)) + (comint-send-input))))))))) + +;;; +;;; internal functions +;;; +(defun xdvi-has-no-inverse-search (version) + (< version 22038000)) + +(defun xdvi-has-nofork (version is-xdvik) + (if is-xdvik + ; xdvik got -nofork in version 22.74.1 + (>= version 22074001) + (>= version 22061000))) + +(defun get-source-filename (fname version flag) + (if (> flag 1) + (if (> flag 2) + ;;; full path name, for use with TeX patch and when using the + ;;; full path in \input or \include with srcltx.sty: + (expand-file-name (buffer-file-name)) + ;;; relative path name: if current path and path of master file match partly, + ;;; use the rest of this path; else use buffer name. This can treat both the + ;;; cases when a relative path is used in \input{}, or when just the filename + ;;; is used and the file is located in the current directory (suggested by + ;;; frisk@isy.liu.se). + (if (string-match (concat "^" (regexp-quote (file-name-directory master-file))) + (buffer-file-name)) + (substring (buffer-file-name) (match-end 0)) + (buffer-file-name))) + ;;; buffer file name without path: + (file-name-nondirectory (buffer-file-name)))) + +(defun xdvi-get-version-number (default) + "Return a tuple of (version-number xdvi-is-xdvik), or (default nil) if default != 0." + (if (not (= default 0)) + (list default nil) + (save-window-excursion + (switch-to-buffer "*xdvi-version*") + (erase-buffer) + (call-process xdvi-bin nil "*xdvi-version*" nil "-version") + (goto-char (point-min)) + (if (not (re-search-forward "xdvi\\((?k)?\\)? version \\([0-9]+\\)\\.\\([0-9]+\\)\\(\\.\\([0-9]+\\)\\)?" nil t)) + (error "Unable to get xdvi version number - please check value of `xdvi-bin', or set it manually via `xdvi-version-number'.") + (let* ((major (string-to-int (buffer-substring (match-beginning 2) (match-end 2)))) + (minor (string-to-int (buffer-substring (match-beginning 3) (match-end 3)))) + (patchlevel (if (match-beginning 5) + (string-to-int (buffer-substring (match-beginning 5) (match-end 5))) + 0)) + (xdvi-is-xdvik (if (match-beginning 1) t nil)) + (version (+ (* 1000 minor) (* 1000000 major) patchlevel))) + (kill-buffer "*xdvi-version*") +;;; (message "Xdvi%s version: major %d, minor %d, version %d" (if xdvi-is-xdvik "k" "") major minor version) + (list version xdvi-is-xdvik) + ))))) + +(defun xdvi-process-sentinel (process signal) + (let ((retmsg (substring signal 0 -1))) + (if (string-match "abnormally" retmsg) + (progn + (message "XDvi: %s" retmsg) + (pop-to-buffer (process-buffer process))) + (message "XDvi: %s" retmsg)))) + +(defun xdvi-get-masterfile (file) + "Small helper function for AucTeX compatibility. +Converts the special value t that TeX-master might be set to +into a real file name." + (if (eq file t) + (buffer-file-name) + file)) + + +(defun xdvi-master-file-name () + "Emulate AucTeX's TeX-master-file function. +Partly copied from tex.el's TeX-master-file and TeX-add-local-master." + (if (boundp 'TeX-master) + TeX-master + (let ((master-file (read-file-name "Master file (default this file): "))) + (if (y-or-n-p "Save info as local variable? ") + (progn + (goto-char (point-max)) + (if (re-search-backward "^\\([^\n]+\\)Local Variables:" nil t) + (let* ((prefix (if (match-beginning 1) + (buffer-substring (match-beginning 1) (match-end 1)) + "")) + (start (point))) + (re-search-forward (regexp-quote (concat prefix "End:")) nil t) + (if (re-search-backward (regexp-quote (concat prefix "TeX-master")) start t) + ;;; if TeX-master line exists already, replace it + (progn + (beginning-of-line 1) + (kill-line 1)) + (beginning-of-line 1)) + (insert prefix "TeX-master: " (prin1-to-string master-file) "\n")) + (insert "\n%%% Local Variables: " +;;; mode is of little use without AucTeX ... +;;; "\n%%% mode: " (substring (symbol-name major-mode) 0 -5) + "\n%%% TeX-master: " (prin1-to-string master-file) + "\n%%% End: \n")) + (save-buffer) + (message "(local variables written.)")) + (message "(nothing written.)")) + (set (make-local-variable 'TeX-master) master-file)))) + + +(provide 'xdvi-search) + +;;; page break to avoid "Local variables entry is missing the prefix" error for previous stuff + + +;;; xdvi-search.el ends here |