summaryrefslogtreecommitdiff
path: root/contrib/texinfo/emacs/texnfo-tex.el
blob: 225ea685c0426a18f380c41eebf13980d114efc5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
;;;; texnfo-tex.el

;;; Texinfo mode TeX and hardcopy printing commands.

;; These commands are for running TeX on a region of a Texinfo file in
;; GNU Emacs, or on the whole buffer, and for printing the resulting
;; DVI file.

;;; Version 2.07    22 October 1991
;;; Robert J. Chassell      
;;; Please send bug reports to:  bug-texinfo@prep.ai.mit.edu

;;; Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.


;;; This file is part of GNU Emacs.

;; GNU Emacs 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, or (at your option)
;; any later version.

;; GNU Emacs 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 GNU Emacs; see the file COPYING.  If not, write to
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,


;;; The Texinfo mode TeX related commands are:

; texinfo-tex-region        to run tex on the current region.
; texinfo-tex-buffer        to run tex on the current buffer.
; texinfo-texindex          to sort unsorted index files.
; texinfo-tex-print         to print the .dvi file made by tex.
; texinfo-kill-tex-job      to kill the currently running tex job.
; texinfo-recenter-tex-output-buffer    to redisplay tex output buffer.
; texinfo-show-tex-print-queue          to show the print queue.


;;; Keys common both to Texinfo mode and to TeX shell.

;; Defined in `texinfo.el'
; (defun texinfo-define-common-keys (keymap)
;   "Define the keys both in Texinfo mode and in the texinfo-tex-shell."
;   (define-key keymap "\C-c\C-t\C-k"    'texinfo-kill-tex-job)
;   (define-key keymap "\C-c\C-t\C-x"    'texinfo-quit-tex-job)
;   (define-key keymap "\C-c\C-t\C-l"    'texinfo-recenter-tex-output-buffer)
;   (define-key keymap "\C-c\C-t\C-d"    'texinfo-delete-from-tex-print-queue)
;   (define-key keymap "\C-c\C-t\C-q"    'texinfo-show-tex-print-queue)
;   (define-key keymap "\C-c\C-t\C-p"    'texinfo-tex-print)
;   (define-key keymap "\C-c\C-t\C-i"    'texinfo-texindex)
;   (define-key keymap "\C-c\C-t\C-r"    'texinfo-tex-region)
;   (define-key keymap "\C-c\C-t\C-b"    'texinfo-tex-buffer))

;; See also texinfo-tex-start-shell. 
;; The following is executed in the `texinfo.el' file
;(texinfo-define-common-keys texinfo-mode-map)


;;; Variable definitions:

(require 'shell)

(defvar texinfo-tex-shell-cd-command "cd"
  "Command to give to shell running TeX to change directory.")

(defvar texinfo-tex-command "tex"
  "*Command used by  texinfo-tex-region  to run tex on a region.")

(defvar texinfo-texindex-command "texindex"
  "*Command used by  texinfo-texindex  to sort unsorted index files.")

(defvar texinfo-tex-dvi-print-command "lpr -d"
  "*Command string used by \\[tex-print] to print a .dvi file.")

(defvar texinfo-show-tex-queue-command "lpq"
  "*Command string used to show the Texinfo TeX print queue.
Command is used by \\[texinfo-show-tex-print-queue] and it
should show the queue that \\[texinfo-tex-print] puts jobs on.")

(defvar texinfo-delete-from-print-queue-command "lprm"
  "*Command string used to delete a job from the line printer queue.
Command is used by \\[texinfo-delete-from-tex-print-queue] based on
number provided by a previous \\[texinfo-show-tex-print-queue]
command.")

(defvar texinfo-tex-trailer "@bye"
  "String appended after a region sent to TeX by texinfo-tex-region.")

(defvar texinfo-tex-original-file ""
  "Original name of file on which to run TeX.")

(defvar texinfo-tex-temp-file nil
  "Temporary file name used for text being sent as input to TeX.")

(defvar texinfo-tex-root-temp-file nil
  "Temporary file name used for text being sent as input to TeX.")


;;; Texinfo TeX main functions

(defun texinfo-tex-region (beginning end)
  "Run tex on the current region. 

A temporary file is written in the default directory, and tex is run
in that directory.  The first line of the file is copied to the
temporary file; and if the buffer has a header, it is written to the
temporary file before the region itself.  The buffer's header is all
lines between the strings defined by texinfo-start-of-header and
texinfo-end-of-header inclusive.  The header must start in the first 100
lines.  The value of texinfo-tex-trailer is appended to the temporary file
after the region."
  
  (interactive "r")
  (if (get-buffer "*texinfo-tex-shell*")
      (quit-process (get-process "texinfo-tex-shell") t)
    (texinfo-tex-start-shell))
  
  (setq texinfo-tex-root-temp-file
        (expand-file-name 
         (make-temp-name
          (prin1-to-string (read (buffer-name))))))
  
  (let ((texinfo-tex-temp-file (concat texinfo-tex-root-temp-file ".tex")))
    (save-excursion
      (save-restriction
        (widen)
        (goto-char (point-min))
        (forward-line 100)
        (let ((search-end (point))
              (header-beginning (point-min)) (header-end (point-min)))
          (goto-char (point-min))
          ;; Copy first line, the `\input texinfo' line, to temp file
          (write-region (point) 
                        (save-excursion (forward-line 1) (point))
                        texinfo-tex-temp-file nil nil)
          ;; Don't copy first line twice if region includes it.
          (forward-line 1)
          (if (< beginning  (point)) (setq beginning  (point)))
          ;; Initialize the temp file with either the header or nothing
          (if (search-forward texinfo-start-of-header search-end t)
              (progn
                (beginning-of-line)
                (setq header-beginning (point)) ; Mark beginning of header.
                (if (search-forward texinfo-end-of-header nil t)
                    (progn (beginning-of-line)
                           (setq header-end (point)))   ; Mark end of header.
                  (setq header-beginning (point-min))))) ; Else no header.
          ;; Copy  header  to temp file.
          (write-region
           (min header-beginning beginning )
           header-end
           texinfo-tex-temp-file t nil)
          ;; Copy  region  to temp file.
          (write-region
           (max beginning  header-end)
           end
           texinfo-tex-temp-file t nil)
          ;; This is a kludge to insert the texinfo-tex-trailer into the
          ;; texinfo-tex-temp-file.  We have to create a special buffer
          ;; in which to insert the texinfo-tex-trailer first because there is
          ;; no function with which to append a literal string directly
          ;; to a file.
          (let ((local-tex-trailer texinfo-tex-trailer)
                (temp-buffer (get-buffer-create " texinfo-trailer-buffer")))
            (set-buffer temp-buffer)
            (erase-buffer)
            ;; make sure trailer isn't hidden by a comment
            (insert-string "\n")
            (if local-tex-trailer (insert local-tex-trailer))
            (write-region (point-min) (point-max) 
                          texinfo-tex-temp-file t nil)))
        (set-process-sentinel (get-process "texinfo-tex-shell") 
                              'texinfo-tex-shell-sentinel)
        (send-string "texinfo-tex-shell"
                     (concat texinfo-tex-shell-cd-command " "
                             default-directory "\n"))
        (send-string "texinfo-tex-shell"
                     (concat texinfo-tex-command " "
                             texinfo-tex-temp-file "\n  "))
        (texinfo-recenter-tex-output-buffer 0)))))

(defun texinfo-tex-buffer (buffer)
  "Run TeX on current buffer.
After running TeX the first time, you may have to run \\[texinfo-texindex]
and then \\[texinfo-tex-buffer] again."
  (interactive 
   (list
    ;; Sometimes you put point into *texinfo-tex-shell*; this prompts
    ;; you for the correct file regardless.
    (if (and 
         (string= (buffer-name (current-buffer)) "*texinfo-tex-shell*")
         texinfo-tex-root-temp-file)
        (read-string (format "Run TeX on: ")
                     texinfo-tex-original-file)
      (read-string (format "Run TeX on: ") (buffer-name (current-buffer))))))
  
  ;; Set to original buffer if in *texinfo-tex-shell*; otherwise,
  ;; record name of current buffer.
  (if (string= (buffer-name (current-buffer)) "*texinfo-tex-shell*")
      (set-buffer buffer)
    (setq texinfo-tex-original-file
           (buffer-name (current-buffer))))

  (if (get-buffer "*texinfo-tex-shell*")
      (quit-process (get-process "texinfo-tex-shell") t)
    (texinfo-tex-start-shell))
  (cond ((null buffer-file-name)
         (error "Buffer not visiting any file!"))
        ((buffer-modified-p)
         (error "Buffer has been modified since last saved!"))
        (t (set-process-sentinel (get-process "texinfo-tex-shell") 
                                 'texinfo-tex-shell-sentinel)
           (send-string "texinfo-tex-shell"
                        (concat texinfo-tex-shell-cd-command 
                                " "
                                (file-name-directory
                                 (buffer-file-name
                                  (get-buffer buffer)))
                                "\n"))
           (send-string "texinfo-tex-shell"
                        (concat texinfo-tex-command " " buffer "\n  "))
           
           ;; so the texinfo-tex-print command works
           (setq texinfo-tex-root-temp-file
                 (substring buffer 0
                            (or (string-match "\\.tex" buffer)
                                (length buffer))))
           
           (texinfo-recenter-tex-output-buffer 0))))

(defun texinfo-texindex ()
  "Run texindex on unsorted index files.
The index files are made by \\[texinfo-tex-region] or \\[texinfo-tex-buffer].
Runs the shell command defined by texinfo-texindex-command."
  (interactive)
  (send-string "texinfo-tex-shell"
               (concat texinfo-texindex-command
                       " " texinfo-tex-root-temp-file ".??" "\n"))
  (texinfo-recenter-tex-output-buffer nil))

(defun texinfo-tex-print ()
  "Print .dvi file made by \\[texinfo-tex-region] or \\[texinfo-tex-buffer].
Runs the shell command defined by texinfo-tex-dvi-print-command."
  (interactive)
  (send-string "texinfo-tex-shell"
               (concat texinfo-tex-dvi-print-command
                       " " texinfo-tex-root-temp-file ".dvi" "\n"))
  (texinfo-recenter-tex-output-buffer nil))


;;; Texinfo TeX utility functions

(defun texinfo-tex-start-shell ()
  (save-excursion
    (require 'texinfo)
    (set-buffer (make-shell "texinfo-tex-shell" "/bin/sh" nil "-v"))
    (setq texinfo-tex-shell-map (copy-keymap shell-mode-map))
    (texinfo-define-common-keys texinfo-tex-shell-map)
    (use-local-map texinfo-tex-shell-map)
    (run-hooks 'texinfo-tex-shell-hook)
    (if (zerop (buffer-size))
        (sleep-for 1))))

(defun texinfo-quit-tex-job ()
  "Quit currently running TeX job, by sending an `x' to it."
  (interactive)
  (if (not (get-process "texinfo-tex-shell"))
      (error "No TeX shell running."))
  (save-excursion
    (set-buffer (get-buffer "*texinfo-tex-shell*"))
    (goto-char (point-max))
    (insert "x")
    (shell-send-input)))

(defun texinfo-kill-tex-job ()
  "Kill the currently running TeX job."
  (interactive)
  (if (get-process "texinfo-tex-shell")
        ;; Use `texinfo-tex-shell-sentinel' to restart
        ;; texinfo-tex-shell after it is killed.
        (kill-process (get-process "texinfo-tex-shell"))))

(defun texinfo-tex-shell-sentinel (process event)
  "Restart texinfo-tex-shell after it is killed."
  (if (equal event "killed\n")
      (save-excursion
        (set-buffer  "*texinfo-tex-shell*")
        (insert "\n")
        (texinfo-tex-start-shell))))

(defun texinfo-recenter-tex-output-buffer (linenum)
  "Redisplay buffer of TeX job output so that most recent output can be seen.
The last line of the buffer is displayed on
line LINE of the window, or centered if LINE is nil."
  (interactive "P")
  (let ((texinfo-tex-shell (get-buffer "*texinfo-tex-shell*"))
        (old-buffer (current-buffer)))
    (if (null texinfo-tex-shell)
        (message "No TeX output buffer")
      (pop-to-buffer texinfo-tex-shell)
      (bury-buffer texinfo-tex-shell)
      (goto-char (point-max))
      (recenter (if linenum
                    (prefix-numeric-value linenum)
                  (/ (window-height) 2)))
      (pop-to-buffer old-buffer)
      )))

(defun texinfo-show-tex-print-queue ()
  "Show the print queue that \\[texinfo-tex-print] put your job on.
Runs the shell command defined by texinfo-show-tex-queue-command."
  (interactive)
  (if (not (texinfo-tex-shell-running-p))
      (texinfo-tex-start-shell))
  (send-string "texinfo-tex-shell"
               (concat texinfo-show-tex-queue-command "\n"))
  (texinfo-recenter-tex-output-buffer nil))

(defun texinfo-delete-from-tex-print-queue (job-number)
  "Delete job from the line printer spooling queue.
You are prompted for the job number (shown by a previous
\\[texinfo-show-tex-print-queue] command."
  (interactive "nPrinter job number for deletion: ")
  (if (texinfo-tex-shell-running-p)
      (texinfo-kill-tex-job)
    (texinfo-tex-start-shell))
  (send-string "texinfo-tex-shell"
               (concat 
                texinfo-delete-from-print-queue-command
                " "
                job-number"\n"))
  (texinfo-recenter-tex-output-buffer nil))

(defun texinfo-tex-shell-running-p ()
  (and (get-process "texinfo-tex-shell")
       (eq (process-status (get-process "texinfo-tex-shell")) 'run)))


;;; Place `provide' at end of file.
(provide 'texnfo-tex)
;;;;;;;;;;;;;;;; end texnfo-tex.el ;;;;;;;;;;;;;;;;