| 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 |
(defgroup nroff nil |
|---|
| 40 |
"Nroff mode." |
|---|
| 41 |
:link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces) |
|---|
| 42 |
:group 'wp |
|---|
| 43 |
:prefix "nroff-") |
|---|
| 44 |
|
|---|
| 45 |
|
|---|
| 46 |
(defcustom nroff-electric-mode nil |
|---|
| 47 |
"Non-nil means automatically closing requests when you insert an open." |
|---|
| 48 |
:group 'nroff |
|---|
| 49 |
:type 'boolean) |
|---|
| 50 |
|
|---|
| 51 |
(defvar nroff-mode-map |
|---|
| 52 |
(let ((map (make-sparse-keymap))) |
|---|
| 53 |
(define-key map "\t" 'tab-to-tab-stop) |
|---|
| 54 |
(define-key map "\es" 'center-line) |
|---|
| 55 |
(define-key map "\e?" 'nroff-count-text-lines) |
|---|
| 56 |
(define-key map "\n" 'nroff-electric-newline) |
|---|
| 57 |
(define-key map "\en" 'nroff-forward-text-line) |
|---|
| 58 |
(define-key map "\ep" 'nroff-backward-text-line) |
|---|
| 59 |
map) |
|---|
| 60 |
"Major mode keymap for `nroff-mode'.") |
|---|
| 61 |
|
|---|
| 62 |
(defvar nroff-mode-syntax-table |
|---|
| 63 |
(let ((st (copy-syntax-table text-mode-syntax-table))) |
|---|
| 64 |
|
|---|
| 65 |
|
|---|
| 66 |
|
|---|
| 67 |
(modify-syntax-entry ?\" "\" 2" st) |
|---|
| 68 |
|
|---|
| 69 |
(modify-syntax-entry ?\\ "\\ 1" st) |
|---|
| 70 |
(modify-syntax-entry ?\n ">" st) |
|---|
| 71 |
st) |
|---|
| 72 |
"Syntax table used while in `nroff-mode'.") |
|---|
| 73 |
|
|---|
| 74 |
(defvar nroff-imenu-expression |
|---|
| 75 |
|
|---|
| 76 |
'((nil "^\\.SH \"?\\([^\"\n]*\\)\"?$" 1))) |
|---|
| 77 |
|
|---|
| 78 |
(defcustom nroff-font-lock-keywords |
|---|
| 79 |
(list |
|---|
| 80 |
|
|---|
| 81 |
|
|---|
| 82 |
|
|---|
| 83 |
|
|---|
| 84 |
"^[.']\\s-*\\sw+" |
|---|
| 85 |
|
|---|
| 86 |
|
|---|
| 87 |
|
|---|
| 88 |
|
|---|
| 89 |
|
|---|
| 90 |
(concat "\\\\" |
|---|
| 91 |
"\\(" |
|---|
| 92 |
(mapconcat 'identity |
|---|
| 93 |
'("[f*n]*\\[.+?]" |
|---|
| 94 |
"(.." |
|---|
| 95 |
"[^(\"]" |
|---|
| 96 |
) "\\|") |
|---|
| 97 |
"\\)") |
|---|
| 98 |
) |
|---|
| 99 |
"Font-lock highlighting control in `nroff-mode'." |
|---|
| 100 |
:group 'nroff |
|---|
| 101 |
:type '(repeat regexp)) |
|---|
| 102 |
|
|---|
| 103 |
(defcustom nroff-mode-hook nil |
|---|
| 104 |
"Hook run by function `nroff-mode'." |
|---|
| 105 |
:type 'hook |
|---|
| 106 |
:group 'nroff) |
|---|
| 107 |
|
|---|
| 108 |
|
|---|
| 109 |
(define-derived-mode nroff-mode text-mode "Nroff" |
|---|
| 110 |
"Major mode for editing text intended for nroff to format. |
|---|
| 111 |
\\{nroff-mode-map} |
|---|
| 112 |
Turning on Nroff mode runs `text-mode-hook', then `nroff-mode-hook'. |
|---|
| 113 |
Also, try `nroff-electric-mode', for automatically inserting |
|---|
| 114 |
closing requests for requests that are used in matched pairs." |
|---|
| 115 |
(set (make-local-variable 'font-lock-defaults) |
|---|
| 116 |
|
|---|
| 117 |
|
|---|
| 118 |
|
|---|
| 119 |
'(nroff-font-lock-keywords nil t nil backward-paragraph)) |
|---|
| 120 |
(set (make-local-variable 'outline-regexp) "\\.H[ ]+[1-7]+ ") |
|---|
| 121 |
(set (make-local-variable 'outline-level) 'nroff-outline-level) |
|---|
| 122 |
|
|---|
| 123 |
(set (make-local-variable 'page-delimiter) "^\\.\\(bp\\|SK\\|OP\\)") |
|---|
| 124 |
(set (make-local-variable 'paragraph-start) |
|---|
| 125 |
(concat "[.']\\|" paragraph-start)) |
|---|
| 126 |
(set (make-local-variable 'paragraph-separate) |
|---|
| 127 |
(concat "[.']\\|" paragraph-separate)) |
|---|
| 128 |
|
|---|
| 129 |
(set (make-local-variable 'comment-start) "\\\" ") |
|---|
| 130 |
(set (make-local-variable 'comment-start-skip) "\\\\\"[ \t]*") |
|---|
| 131 |
(set (make-local-variable 'comment-column) 24) |
|---|
| 132 |
(set (make-local-variable 'comment-indent-function) 'nroff-comment-indent) |
|---|
| 133 |
(set (make-local-variable 'indent-line-function) 'nroff-indent-line-function) |
|---|
| 134 |
(set (make-local-variable 'imenu-generic-expression) nroff-imenu-expression)) |
|---|
| 135 |
|
|---|
| 136 |
(defun nroff-outline-level () |
|---|
| 137 |
(save-excursion |
|---|
| 138 |
(looking-at outline-regexp) |
|---|
| 139 |
(skip-chars-forward ".H ") |
|---|
| 140 |
(string-to-number (buffer-substring (point) (+ 1 (point)))))) |
|---|
| 141 |
|
|---|
| 142 |
|
|---|
| 143 |
|
|---|
| 144 |
(defun nroff-comment-indent () |
|---|
| 145 |
"Compute indent for an nroff/troff comment. |
|---|
| 146 |
Puts a full-stop before comments on a line by themselves." |
|---|
| 147 |
(let ((pt (point))) |
|---|
| 148 |
(unwind-protect |
|---|
| 149 |
(progn |
|---|
| 150 |
(skip-chars-backward " \t") |
|---|
| 151 |
(if (bolp) |
|---|
| 152 |
(progn |
|---|
| 153 |
(setq pt (1+ pt)) |
|---|
| 154 |
(insert ?.) |
|---|
| 155 |
1) |
|---|
| 156 |
(if (save-excursion |
|---|
| 157 |
(backward-char 1) |
|---|
| 158 |
(looking-at "^[.']")) |
|---|
| 159 |
1 |
|---|
| 160 |
(max comment-column |
|---|
| 161 |
(* 8 (/ (+ (current-column) |
|---|
| 162 |
9) 8)))))) |
|---|
| 163 |
(goto-char pt)))) |
|---|
| 164 |
|
|---|
| 165 |
|
|---|
| 166 |
|
|---|
| 167 |
|
|---|
| 168 |
|
|---|
| 169 |
|
|---|
| 170 |
(defun nroff-indent-line-function () |
|---|
| 171 |
"Function for `indent-line-function' in `nroff-mode'." |
|---|
| 172 |
(save-excursion |
|---|
| 173 |
(forward-line 0) |
|---|
| 174 |
(when (looking-at "[ \t]*\\\\\"[ \t]*") |
|---|
| 175 |
(delete-horizontal-space) |
|---|
| 176 |
(insert ?.)))) |
|---|
| 177 |
|
|---|
| 178 |
(defun nroff-count-text-lines (start end &optional print) |
|---|
| 179 |
"Count lines in region, except for nroff request lines. |
|---|
| 180 |
All lines not starting with a period are counted up. |
|---|
| 181 |
Interactively, print result in echo area. |
|---|
| 182 |
Noninteractively, return number of non-request lines from START to END." |
|---|
| 183 |
(interactive "r\np") |
|---|
| 184 |
(if print |
|---|
| 185 |
(message "Region has %d text lines" (nroff-count-text-lines start end)) |
|---|
| 186 |
(save-excursion |
|---|
| 187 |
(save-restriction |
|---|
| 188 |
(narrow-to-region start end) |
|---|
| 189 |
(goto-char (point-min)) |
|---|
| 190 |
(- (buffer-size) (nroff-forward-text-line (buffer-size))))))) |
|---|
| 191 |
|
|---|
| 192 |
(defun nroff-forward-text-line (&optional cnt) |
|---|
| 193 |
"Go forward one nroff text line, skipping lines of nroff requests. |
|---|
| 194 |
An argument is a repeat count; if negative, move backward." |
|---|
| 195 |
(interactive "p") |
|---|
| 196 |
(if (not cnt) (setq cnt 1)) |
|---|
| 197 |
(while (and (> cnt 0) (not (eobp))) |
|---|
| 198 |
(forward-line 1) |
|---|
| 199 |
(while (and (not (eobp)) (looking-at "[.'].")) |
|---|
| 200 |
(forward-line 1)) |
|---|
| 201 |
(setq cnt (- cnt 1))) |
|---|
| 202 |
(while (and (< cnt 0) (not (bobp))) |
|---|
| 203 |
(forward-line -1) |
|---|
| 204 |
(while (and (not (bobp)) |
|---|
| 205 |
(looking-at "[.'].")) |
|---|
| 206 |
(forward-line -1)) |
|---|
| 207 |
(setq cnt (+ cnt 1))) |
|---|
| 208 |
cnt) |
|---|
| 209 |
|
|---|
| 210 |
(defun nroff-backward-text-line (&optional cnt) |
|---|
| 211 |
"Go backward one nroff text line, skipping lines of nroff requests. |
|---|
| 212 |
An argument is a repeat count; negative means move forward." |
|---|
| 213 |
(interactive "p") |
|---|
| 214 |
(nroff-forward-text-line (- cnt))) |
|---|
| 215 |
|
|---|
| 216 |
(defconst nroff-brace-table |
|---|
| 217 |
'((".(b" . ".)b") |
|---|
| 218 |
(".(l" . ".)l") |
|---|
| 219 |
(".(q" . ".)q") |
|---|
| 220 |
(".(c" . ".)c") |
|---|
| 221 |
(".(x" . ".)x") |
|---|
| 222 |
(".(z" . ".)z") |
|---|
| 223 |
(".(d" . ".)d") |
|---|
| 224 |
(".(f" . ".)f") |
|---|
| 225 |
(".LG" . ".NL") |
|---|
| 226 |
(".SM" . ".NL") |
|---|
| 227 |
(".LD" . ".DE") |
|---|
| 228 |
(".CD" . ".DE") |
|---|
| 229 |
(".BD" . ".DE") |
|---|
| 230 |
(".DS" . ".DE") |
|---|
| 231 |
(".DF" . ".DE") |
|---|
| 232 |
(".FS" . ".FE") |
|---|
| 233 |
(".KS" . ".KE") |
|---|
| 234 |
(".KF" . ".KE") |
|---|
| 235 |
(".LB" . ".LE") |
|---|
| 236 |
(".AL" . ".LE") |
|---|
| 237 |
(".BL" . ".LE") |
|---|
| 238 |
(".DL" . ".LE") |
|---|
| 239 |
(".ML" . ".LE") |
|---|
| 240 |
(".RL" . ".LE") |
|---|
| 241 |
(".VL" . ".LE") |
|---|
| 242 |
(".RS" . ".RE") |
|---|
| 243 |
(".TS" . ".TE") |
|---|
| 244 |
(".EQ" . ".EN") |
|---|
| 245 |
(".PS" . ".PE") |
|---|
| 246 |
(".BS" . ".BE") |
|---|
| 247 |
(".G1" . ".G2") |
|---|
| 248 |
(".na" . ".ad b") |
|---|
| 249 |
(".nf" . ".fi") |
|---|
| 250 |
(".de" . ".."))) |
|---|
| 251 |
|
|---|
| 252 |
(defun nroff-electric-newline (arg) |
|---|
| 253 |
"Insert newline for nroff mode; special if electric-nroff mode. |
|---|
| 254 |
In `electric-nroff-mode', if ending a line containing an nroff opening request, |
|---|
| 255 |
automatically inserts the matching closing request after point." |
|---|
| 256 |
(interactive "P") |
|---|
| 257 |
(let ((completion (save-excursion |
|---|
| 258 |
(beginning-of-line) |
|---|
| 259 |
(and (null arg) |
|---|
| 260 |
nroff-electric-mode |
|---|
| 261 |
(<= (point) (- (point-max) 3)) |
|---|
| 262 |
(cdr (assoc (buffer-substring (point) |
|---|
| 263 |
(+ 3 (point))) |
|---|
| 264 |
nroff-brace-table))))) |
|---|
| 265 |
(needs-nl (not (looking-at "[ \t]*$")))) |
|---|
| 266 |
(if (null completion) |
|---|
| 267 |
(newline (prefix-numeric-value arg)) |
|---|
| 268 |
(save-excursion |
|---|
| 269 |
(insert "\n\n" completion) |
|---|
| 270 |
(if needs-nl (insert "\n"))) |
|---|
| 271 |
(forward-char 1)))) |
|---|
| 272 |
|
|---|
| 273 |
(define-minor-mode nroff-electric-mode |
|---|
| 274 |
"Toggle `nroff-electric-newline' minor mode. |
|---|
| 275 |
`nroff-electric-newline' forces Emacs to check for an nroff request at the |
|---|
| 276 |
beginning of the line, and insert the matching closing request if necessary. |
|---|
| 277 |
This command toggles that mode (off->on, on->off), with an argument, |
|---|
| 278 |
turns it on if arg is positive, otherwise off." |
|---|
| 279 |
:lighter " Electric" |
|---|
| 280 |
(or (derived-mode-p 'nroff-mode) (error "Must be in nroff mode"))) |
|---|
| 281 |
|
|---|
| 282 |
|
|---|
| 283 |
(define-obsolete-function-alias 'count-text-lines 'nroff-count-text-lines "22.1") |
|---|
| 284 |
(define-obsolete-function-alias 'forward-text-line 'nroff-forward-text-line "22.1") |
|---|
| 285 |
(define-obsolete-function-alias 'backward-text-line 'nroff-backward-text-line "22.1") |
|---|
| 286 |
(define-obsolete-function-alias 'electric-nroff-newline 'nroff-electric-newline "22.1") |
|---|
| 287 |
(define-obsolete-function-alias 'electric-nroff-mode 'nroff-electric-mode "22.1") |
|---|
| 288 |
|
|---|
| 289 |
(provide 'nroff-mode) |
|---|
| 290 |
|
|---|
| 291 |
|
|---|
| 292 |
|
|---|
| 293 |
|
|---|