summaryrefslogtreecommitdiff
path: root/lisp/textmodes/texinfo.el
blob: ebe0769a71c1b650a4e33f77cc13666ecd620b9c (plain)
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
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
;;;; texinfo.el
;;;; Major mode for editing Texinfo files.

;;;; Version 2.00   14 Dec 1990

;; Copyright (C) 1985, 1988, 1989, 1990 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 1, 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
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.

(require 'texnfo-upd)
(require 'tex-mode)
(provide 'texinfo)

(defvar texinfo-mode-syntax-table nil)

(if texinfo-mode-syntax-table
    nil
  (setq texinfo-mode-syntax-table (make-syntax-table))
  (modify-syntax-entry ?\" " " texinfo-mode-syntax-table)
  (modify-syntax-entry ?\\ " " texinfo-mode-syntax-table)
  (modify-syntax-entry ?@ "\\" texinfo-mode-syntax-table)
  (modify-syntax-entry ?\^q "\\" texinfo-mode-syntax-table)
  (modify-syntax-entry ?\[ "(]" texinfo-mode-syntax-table)
  (modify-syntax-entry ?\] ")[" texinfo-mode-syntax-table)
  (modify-syntax-entry ?{ "(}" texinfo-mode-syntax-table)
  (modify-syntax-entry ?} "){" texinfo-mode-syntax-table)
  (modify-syntax-entry ?\' "w" texinfo-mode-syntax-table))

(defvar texinfo-mode-map nil)

;; Mode documentation displays commands in reverse order 
;; from how they are listed in the texinfo-mode-map.
(if texinfo-mode-map
    nil
  (setq texinfo-mode-map (make-sparse-keymap))

  (define-key texinfo-mode-map "\C-c\C-t\C-k"    'tex-kill-job)
  (define-key texinfo-mode-map "\C-c\C-t\C-l"    'tex-recenter-output-buffer)
  (define-key texinfo-mode-map "\C-c\C-t\C-q"    'tex-show-print-queue)
  (define-key texinfo-mode-map "\C-c\C-t\C-p"    'texinfo-tex-print)
  (define-key texinfo-mode-map "\C-c\C-t\C-i"    'texinfo-texindex)
  (define-key texinfo-mode-map "\C-c\C-t\C-t"    'texinfo-tex-buffer)
  (define-key texinfo-mode-map "\C-c\C-t\C-r"    'texinfo-tex-region)

  (define-key texinfo-mode-map "\C-c\C-i\C-r"    'texinfo-format-region)
  (define-key texinfo-mode-map "\C-c\C-i\C-b"    'texinfo-format-buffer)

  (define-key texinfo-mode-map "\C-c\C-u\C-m"   'texinfo-make-menu)
  (define-key texinfo-mode-map "\C-c\C-u\C-n"   'texinfo-update-node)
  (define-key texinfo-mode-map "\C-c\C-u\C-e"   'texinfo-every-node-update)
  (define-key texinfo-mode-map "\C-c\C-u\C-a"   'texinfo-all-menus-update)

  (define-key texinfo-mode-map "\C-c\C-s"     'texinfo-show-structure)

  (define-key texinfo-mode-map "\""           'tex-insert-quote)
  (define-key texinfo-mode-map "\e}"          'up-list)
  (define-key texinfo-mode-map "\e{"          'texinfo-insert-braces)

  (define-key texinfo-mode-map "\C-c\C-cv"    'texinfo-insert-@var)
  (define-key texinfo-mode-map "\C-c\C-cs"    'texinfo-insert-@samp)
  (define-key texinfo-mode-map "\C-c\C-co"    'texinfo-insert-@noindent)
  (define-key texinfo-mode-map "\C-c\C-cn"    'texinfo-insert-@node)
  (define-key texinfo-mode-map "\C-c\C-ck"    'texinfo-insert-@kbd)
  (define-key texinfo-mode-map "\C-c\C-ci"    'texinfo-insert-@item)
  (define-key texinfo-mode-map "\C-c\C-cx"    'texinfo-insert-@example)
  (define-key texinfo-mode-map "\C-c\C-ce"    'texinfo-insert-@end-example)
  (define-key texinfo-mode-map "\C-c\C-cd"    'texinfo-insert-@dfn)
  (define-key texinfo-mode-map "\C-c\C-cc"    'texinfo-insert-@code))

(defun texinfo-insert-@var ()
  "Insert the string @var in a texinfo buffer."
  (interactive)
  (insert "@var{}")
  (backward-char))

(defun texinfo-insert-@samp ()
  "Insert the string @samp in a texinfo buffer."
  (interactive)
  (insert "@samp{}")
  (backward-char))

(defun texinfo-insert-@noindent ()
  "Insert the string @noindent in a texinfo buffer."
  (interactive)
  (insert "@noindent\n"))

(defun texinfo-insert-@node ()
  "Insert the string @node in a texinfo buffer, 
along with a comment indicating the arguments to @node."
  (interactive)
  (insert "@node \n@comment  node-name,  next,  previous,  up")
  (forward-line -1)
  (forward-char 6))

(defun texinfo-insert-@kbd ()
  "Insert the string @kbd in a texinfo buffer."
  (interactive)
  (insert "@kbd{}")
  (backward-char))

(defun texinfo-insert-@item ()
  "Insert the string @item in a texinfo buffer."
  (interactive)
  (insert "@item")
  (newline))

(defun texinfo-insert-@example ()
  "Insert the string @example in a texinfo buffer."
  (interactive)
  (insert "@example\n"))

(defun texinfo-insert-@end-example ()
  "Insert the string @end example in a texinfo buffer."
  (interactive)
  (insert "@end example\n"))

(defun texinfo-insert-@dfn ()
  "Insert the string @dfn in a texinfo buffer."
  (interactive)
  (insert "@dfn{}")
  (backward-char))

(defun texinfo-insert-@code ()
  "Insert the string @code in a texinfo buffer."
  (interactive)
  (insert "@code{}")
  (backward-char))

(defun texinfo-insert-braces ()
  "Make a pair of braces and be poised to type inside of them.
Use \\[up-list] to move forward out of the braces."
  (interactive)
  (insert "{}")
  (backward-char))

(defun texinfo-mode ()
  "Major mode for editing Texinfo files.

  It has these extra commands:
\\{texinfo-mode-map}

  These are files that are used as input for TeX to make printed manuals
and also to be turned into Info files by \\[texinfo-format-buffer] or
`makeinfo'.  These files must be written in a very restricted and
modified version of TeX input format.

  Editing commands are like text-mode except that the syntax table is
set up so expression commands skip Texinfo bracket groups.  To see
what the Info version of a region of the Texinfo file will look like,
use \\[texinfo-format-region].  This command runs Info on the current region
of the Texinfo file and formats it properly.

  You can show the structure of a Texinfo file with \\[texinfo-show-structure].
This command shows the structure of a Texinfo file by listing the
lines with the @-sign commands for @chapter, @section, and the like.
These lines are displayed in another window called the *Occur* window.
In that window, you can position the cursor over one of the lines and
use \\[occur-mode-goto-occurrence], to jump to the corresponding spot
in the Texinfo file.

  In addition, Texinfo mode provides commands that insert various
frequently used @-sign commands into the buffer.  You can use these
commands to save keystrokes.  And you can insert balanced braces with
\\[texinfo-insert-braces] and later use the command \\[up-list] to
move forward past the closing brace.

Also, Texinfo mode provides functions for automatically creating or
updating menus and node pointers.  These functions

  * insert the `Next', `Previous' and `Up' pointers of a node,
  * insert or update the menu for a section, and
  * create a master menu for a Texinfo source file.

Here are the functions:

    texinfo-update-node                \\[texinfo-update-node]
    texinfo-every-node-update          \\[texinfo-every-node-update]
    texinfo-sequential-node-update 

    texinfo-make-menu                  \\[texinfo-make-menu]
    texinfo-all-menus-update           \\[texinfo-all-menus-update]
    texinfo-master-menu

    texinfo-indent-menu-description (column &optional region-p)

The `texinfo-column-for-description' variable specifies the column to
which menu descriptions are indented. 

Passed an argument (a prefix argument, if interactive), the
`texinfo-update-node' and `texinfo-make-menu' functions do their jobs
in the region.

To use the updating commands, you must structure your Texinfo file
hierarchically, such that each `@node' line, with the exception of the
Top node, is accompanied by some kind of section line, such as an
`@chapter' or `@section' line.

If the file has a `top' node, it must be called `top' or `Top' and
be the first node in the file.

Entering Texinfo mode calls the value of text-mode-hook, and then the
value of texinfo-mode-hook."
  (interactive)
  (text-mode)
  (setq mode-name "texinfo")
  (setq major-mode 'texinfo-mode)
  (use-local-map texinfo-mode-map)
  (set-syntax-table texinfo-mode-syntax-table)
  (make-local-variable 'require-final-newline)
  (setq require-final-newline t)
  (make-local-variable 'paragraph-separate)
  (setq paragraph-separate (concat "^\b\\|^@[a-zA-Z]*[ \n]\\|" paragraph-separate))
  (make-local-variable 'paragraph-start)
  (setq paragraph-start (concat "^\b\\|^@[a-zA-Z]*[ \n]\\|" paragraph-start))
  (make-local-variable 'fill-column)
  (setq fill-column 72)
  (make-local-variable 'comment-start)
  (setq comment-start "@c ")
  (make-local-variable 'comment-start-skip)
  (setq comment-start-skip "@c +")
  (make-local-variable 'words-include-escapes)
  (setq words-include-escapes t)
  (make-local-variable 'tex-start-of-header)
  (setq tex-start-of-header "%**start of header")
  (make-local-variable 'tex-end-of-header)
  (setq tex-end-of-header "%**end of header")
  (make-local-variable 'tex-trailer)
  (setq tex-trailer "@bye\n")
  (run-hooks 'text-mode-hook 'texinfo-mode-hook))


;;; Texinfo file structure

; The following is defined in `texnfo-upd.el'
; (defvar texinfo-section-types-regexp
;   "^@\\(chapter \\|sect\\|sub\\|unnum\\|major\\|heading \\|appendix\\)"
;   "Regexp matching chapter, section, other headings (but not the top node).")

(defun texinfo-show-structure (&optional nodes-too) 
  "Show the structure of a Texinfo file.
List the lines in the file that begin with the @-sign commands for
@chapter, @section, and the like.

With optional argument (prefix if interactive), list both the lines
with @-sign commands for @chapter, @section, and the like, and list
@node lines.

Lines with structuring commands beginning in them are displayed in
another window called the *Occur* window.  In that window, you can
position the cursor over one of the lines and use
\\[occur-mode-goto-occurrence], 
to jump to the corresponding spot in the Texinfo file."

  (interactive "P")
  (save-excursion 
    (goto-char (point-min))
    (if nodes-too
        (occur (concat "\\(^@node\\)\\|" texinfo-section-types-regexp))
      (occur texinfo-section-types-regexp)))
  (pop-to-buffer "*Occur*")
  (goto-char (point-min))
  (flush-lines "-----"))


;;; 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.  The three commands are:

; texinfo-tex-region    to run tex on the current region.
; texinfo-tex-buffer    to run tex on the current buffer.
; texinfo-tex-print     to print the .dvi file made by tex

;;; Other useful functions

; These functions are provided by `tex-mode.el' but are bound to keys
; in texinfo mode.

; tex-kill-job                  to kill the currently running tex job
; tex-recenter-output-buffer    to redisplay tex job output buffer
; tex-show-print-queue          to show the print queue

; Various variables are provided by `tex-mode.el'

; tex mode variable         Default Value 

; tex-dvi-print-command         "lpr -d"
; tex-directory                 "/tmp/"   
; tex-show-queue-command        "lpq"     
; tex-shell-cd-command          "cd"      
; tex-zap-file                  nil   (created  as needed)


;;; The  tex  and  print  function definitions:

(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.")

(defun texinfo-tex-region (beg end)
  "Run tex on the current region.  A temporary file (tex-zap-file) is
written in directory tex-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 tex-start-of-header and tex-end-of-header
inclusive.  The header must start in the first 100 lines.  The value
of tex-trailer is appended to the temporary file after the region."
  (interactive "r")
  (if (get-buffer "*tex-shell*")
      (tex-kill-job)
    (tex-start-shell))
  (or tex-zap-file (setq tex-zap-file (make-temp-name "#tz")))
  (let ((tex-out-file (concat tex-zap-file ".tex"))
	(temp-buffer (get-buffer-create " tex-Output-Buffer"))
	(zap-directory
         (file-name-as-directory (expand-file-name tex-directory))))
    (save-excursion
      (save-restriction
	(widen)
	(goto-char (point-min))
	(forward-line 100)
	(let ((search-end (point))
	      (hbeg (point-min)) (hend (point-min))
	      (default-directory zap-directory))
	  (goto-char (point-min))
          
          ;; Copy first line, the `\input texinfo' line, to temp file
	  (write-region (point) 
                        (save-excursion (end-of-line) (point))
                        tex-out-file nil nil)
          
          ;; Don't copy first line twice if region includes it.
          (forward-line 1)
          (if (< beg (point)) (setq beg (point)))
          
          ;; Initialize the temp file with either the header or nothing
          (if (search-forward tex-start-of-header search-end t)
              (progn
                (beginning-of-line)
                (setq hbeg (point))	; Mark beginning of header.
                (if (search-forward tex-end-of-header nil t)
                    (progn (beginning-of-line)
                           (setq hend (point)))	; Mark end of header.
                  (setq hbeg (point-min))))) ; Else no header.
          
          ;; Copy  header  to temp file.
          (write-region (min hbeg beg) hend tex-out-file t nil)
          
          ;; Copy  region  to temp file.
          (write-region (max beg hend) end tex-out-file t nil))
        
        ;; This is  a kludge to insert the tex-trailer into the tex-out-file.
        ;;  We have to create a special buffer in which to insert
        ;;  the tex-trailer first because there is no function with
        ;;  which to append a literal string directly to a file.
        (let ((local-tex-trailer tex-trailer))
          (set-buffer temp-buffer)
          (erase-buffer)
          ;; make sure trailer isn't hidden by a comment
          (insert-string "\n")
          (if local-tex-trailer (insert-string local-tex-trailer))
          (set-buffer-directory temp-buffer zap-directory)
          (write-region (point-min) (point-max) tex-out-file t nil))))
    
    (set-buffer-directory "*tex-shell*" zap-directory)
    (send-string "tex-shell" (concat tex-shell-cd-command " "
                                     zap-directory "\n"))
    (send-string "tex-shell" (concat texinfo-tex-command " "
                                     tex-out-file "\n")))
  (tex-recenter-output-buffer 0))

(defun texinfo-tex-buffer ()
  "Run tex on current buffer.  
See \\[texinfo-tex-region] for more information."
  (interactive)
  (texinfo-tex-region (point-min) (point-max)))

(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 "tex-shell"
	       (concat texinfo-texindex-command
                       " " tex-zap-file ".??" "\n"))
  (tex-recenter-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 tex-dvi-print-command."
  (interactive)
  (send-string "tex-shell"
	       (concat tex-dvi-print-command
                       " " tex-zap-file ".dvi" "\n"))
  (tex-recenter-output-buffer nil))