4
0

rebox.el 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852
  1. ;;; Handling of comment boxes.
  2. ;;; Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
  3. ;;; François Pinard <[email protected]>, April 1991.
  4. ;;; I first observed rounded corners, as in style 223 boxes, in code from
  5. ;;; Warren Tucker <[email protected]>, a previous shar maintainer.
  6. ;;; Refilling paragraphs inside comments, stretching or shrinking the
  7. ;;; surrounding box as needed, is a pain to do "by hand". This GNU Emacs
  8. ;;; LISP code eases my life on this and I find it fair, giving all sources
  9. ;;; for a package, to also give the means for nicely modifying comments.
  10. ;;; The function rebox-comment discovers the extent of the boxed comments
  11. ;;; near the cursor, possibly refills the text, then adjusts the comment
  12. ;;; box style. The function rebox-region does the same, except that it
  13. ;;; takes the current region as a boxed comment. Numeric prefixes are
  14. ;;; used to add or remove a box, change its style (language, quality or
  15. ;;; type), or to prevent refilling of its text. A minus sign alone as
  16. ;;; prefix asks for interactive style selection.
  17. ;;; For most Emacs language editing modes, refilling does not make sense
  18. ;;; outside comments, so you may redefine the M-q command and link it to
  19. ;;; this file. For example, I use this in my .emacs file:
  20. ;;; (setq c-mode-hook
  21. ;;; '(lambda ()
  22. ;;; (define-key c-mode-map "\M-q" 'rebox-comment)))
  23. ;;; (autoload 'rebox-comment "rebox" nil t)
  24. ;;; (autoload 'rebox-region "rebox" nil t)
  25. ;;; The cursor should be within a comment before any of these commands,
  26. ;;; or else it should be between two comments, in which case the command
  27. ;;; applies to the next comment. When the command is given without prefix,
  28. ;;; the current comment box style is recognized from the comment itself
  29. ;;; as far as possible, and preserved. A prefix may be used to force
  30. ;;; a particular box style. A style is made up of three attributes: a
  31. ;;; language (the hundreds digit), a quality (the tens digit) and a type
  32. ;;; (the units digit). A zero or negative flag value changes the default
  33. ;;; box style to its absolute value. Zero digits in default style,
  34. ;;; when not overriden in flag, asks for recognition of corresponding
  35. ;;; attributes from the current box. `C-u' avoids refilling the text,
  36. ;;; using the default box style. `C-u -' defines the style interactively.
  37. ;;; Box language is associated with comment delimiters. Values are 100
  38. ;;; for none or unknown, 200 for `/*' and `*/' as in plain C, 300 for
  39. ;;; '//' as in C++, 400 for `#' as in most scripting languages, 500 for
  40. ;;; `;' as in LISP or assembler and 600 for `%' as in TeX or PostScript.
  41. ;;; Box quality differs according to language. For unknown languages (100)
  42. ;;; or for the C language (200), values are 10 for simple, 20 or 30 for
  43. ;;; rounded, and 40 for starred. For all others, box quality indicates
  44. ;;; the thickness in characters of the left and right sides of the box:
  45. ;;; values are 10, 20, 30 or 40 for 1, 2, 3 or 4 characters wide. C++
  46. ;;; quality 10 is always promoted to 20. Roughly said, simple quality
  47. ;;; boxes (10) use comment delimiters to left and right of each comment
  48. ;;; line, and also for the top or bottom line when applicable. Rounded
  49. ;;; quality boxes (20 or 30) try to suggest rounded corners in boxes.
  50. ;;; Starred quality boxes (40) mostly use a left margin of asterisks or
  51. ;;; X'es, and use them also in box surroundings. Experiment a little to
  52. ;;; see what happens.
  53. ;;; Box type values are 1 for fully opened boxes for which boxing is done
  54. ;;; only for the left and right but not for top or bottom, 2 for half
  55. ;;; single lined boxes for which boxing is done on all sides except top,
  56. ;;; 3 for fully single lined boxes for which boxing is done on all sides,
  57. ;;; 4 for half double lined boxes which is like type 2 but more bold,
  58. ;;; or 5 for fully double lined boxes which is like type 3 but more bold.
  59. ;;; The special style 221 or 231 is worth a note, because it is fairly
  60. ;;; common: the whole C comment stays between a single opening `/*'
  61. ;;; and a single closing `*/'. The special style 111 deletes a box.
  62. ;;; The initial default style is 023 so, unless overriden, comments are
  63. ;;; put in single lined boxes, C comments are of rounded quality.
  64. (defvar rebox-default-style 0 "*Preferred style for box comments.")
  65. ;;; Help strings for prompting or error messages.
  66. (defconst REBOX_HELP_FOR_LANGUAGE
  67. "Box language is 100-none, 200-/*, 300-//, 400-#, 500-;, 600-%%")
  68. (defconst REBOX_LANGUAGE_NONE 100)
  69. (defconst REBOX_LANGUAGE_C 200)
  70. (defconst REBOX_LANGUAGE_C++ 300)
  71. (defconst REBOX_LANGUAGE_AWK 400)
  72. (defconst REBOX_LANGUAGE_LISP 500)
  73. (defconst REBOX_LANGUAGE_TEX 600)
  74. (defun rebox-help-string-for-language (language)
  75. (cond ((= language 0) "default language")
  76. ((= language REBOX_LANGUAGE_NONE) "no language")
  77. ((= language REBOX_LANGUAGE_C) "plain C")
  78. ((= language REBOX_LANGUAGE_C++) "C++")
  79. ((= language REBOX_LANGUAGE_AWK) "sh/Perl/make")
  80. ((= language REBOX_LANGUAGE_LISP) "LISP/assembler")
  81. ((= language REBOX_LANGUAGE_TEX) "TeX/PostScript")
  82. (t "<Unknown Language>")))
  83. (defconst REBOX_HELP_FOR_QUALITY
  84. "Box quality/width is 10-simple, 20-rounded, 30-rounded or 40-starred")
  85. (defconst REBOX_QUALITY_SIMPLE_ONE 10)
  86. (defconst REBOX_QUALITY_ROUNDED_TWO 20)
  87. (defconst REBOX_QUALITY_ROUNDED_THREE 30)
  88. (defconst REBOX_QUALITY_STARRED_FOUR 40)
  89. (defun rebox-help-string-for-quality (quality)
  90. (cond ((= quality 0) "default quality")
  91. ((= quality REBOX_QUALITY_SIMPLE_ONE) "square or 1-wide")
  92. ((= quality REBOX_QUALITY_ROUNDED_TWO) "rounded or 2-wide")
  93. ((= quality REBOX_QUALITY_ROUNDED_THREE) "rounded or 3-wide")
  94. ((= quality REBOX_QUALITY_STARRED_FOUR) "starred or 4-wide")
  95. (t "<Unknown Quality>")))
  96. (defconst REBOX_HELP_FOR_TYPE
  97. "Box type is 1-open, 2-half-single, 3-single, 4-half-double or 5-double")
  98. (defconst REBOX_TYPE_OPEN 1)
  99. (defconst REBOX_TYPE_HALF_SINGLE 2)
  100. (defconst REBOX_TYPE_SINGLE 3)
  101. (defconst REBOX_TYPE_HALF_DOUBLE 4)
  102. (defconst REBOX_TYPE_DOUBLE 5)
  103. (defun rebox-help-string-for-type (type)
  104. (cond ((= type 0) "default type")
  105. ((= type REBOX_TYPE_OPEN) "opened box")
  106. ((= type REBOX_TYPE_HALF_SINGLE) "half normal")
  107. ((= type REBOX_TYPE_SINGLE) "full normal")
  108. ((= type REBOX_TYPE_HALF_DOUBLE) "half bold")
  109. ((= type REBOX_TYPE_DOUBLE) "full bold")
  110. (t "<Unknown Type>")))
  111. (defconst REBOX_MAX_LANGUAGE 6)
  112. (defconst REBOX_MAX_QUALITY 4)
  113. (defconst REBOX_MAX_TYPE 5)
  114. ;;; Request the style interactively, using the minibuffer.
  115. (defun rebox-ask-for-style ()
  116. (let (key language quality type)
  117. (while (not language)
  118. (message REBOX_HELP_FOR_LANGUAGE)
  119. (setq key (read-char))
  120. (if (and (>= key ?0) (<= key (+ ?0 REBOX_MAX_LANGUAGE)))
  121. (setq language (- key ?0))))
  122. (while (not quality)
  123. (message REBOX_HELP_FOR_QUALITY)
  124. (setq key (read-char))
  125. (if (and (>= key ?0) (<= key (+ ?0 REBOX_MAX_QUALITY)))
  126. (setq quality (- key ?0))))
  127. (while (not type)
  128. (message REBOX_HELP_FOR_TYPE)
  129. (setq key (read-char))
  130. (if (and (>= key ?0) (<= key (+ ?0 REBOX_MAX_TYPE)))
  131. (setq type (- key ?0))))
  132. (+ (* 100 language) (* 10 quality) type)))
  133. ;;; Write some TEXT followed by an edited STYLE value into the minibuffer.
  134. (defun rebox-show-style (text style)
  135. (message
  136. (concat text (format " (%03d)" style)
  137. ": " (rebox-help-string-for-language (* (/ style 100) 100))
  138. ", " (rebox-help-string-for-quality (* (% (/ style 10) 10) 10))
  139. ", " (rebox-help-string-for-type (% style 10)))))
  140. ;;; Validate FLAG and usually return t if not interrupted by errors.
  141. ;;; But if FLAG is zero or negative, then change default box style and
  142. ;;; return nil.
  143. (defun rebox-validate-flag (flag)
  144. ;; Validate flag.
  145. (if (numberp flag)
  146. (let ((value (if (< flag 0) (- flag) flag)))
  147. (if (> (/ value 100) REBOX_MAX_LANGUAGE)
  148. (error REBOX_HELP_FOR_LANGUAGE))
  149. (if (> (% (/ value 10) 10) REBOX_MAX_QUALITY)
  150. (error REBOX_HELP_FOR_QUALITY))
  151. (if (> (% value 10) REBOX_MAX_TYPE)
  152. (error REBOX_HELP_FOR_TYPE))))
  153. ;; Change default box style if requested.
  154. (if (and (numberp flag) (<= flag 0))
  155. (progn
  156. (setq flag (- flag))
  157. (if (not (zerop (/ flag 100)))
  158. (setq rebox-default-style
  159. (+ (* (/ flag 100) 100)
  160. (% rebox-default-style 100))))
  161. (if (not (zerop (% (/ flag 10) 10)))
  162. (setq rebox-default-style
  163. (+ (* (/ rebox-default-style 100) 100)
  164. (* (% (/ flag 10) 10) 10)
  165. (% rebox-default-style 10))))
  166. (if (not (zerop (% flag 10)))
  167. (setq rebox-default-style
  168. (+ (* (/ rebox-default-style 10) 10)
  169. (% flag 10))))
  170. (rebox-show-style "Default style" rebox-default-style)
  171. nil)
  172. t))
  173. ;;; Return the minimum value of the left margin of all lines, or -1 if
  174. ;;; all lines are empty.
  175. (defun rebox-left-margin ()
  176. (let ((margin -1))
  177. (goto-char (point-min))
  178. (while (not (eobp))
  179. (skip-chars-forward " \t")
  180. (if (not (looking-at "\n"))
  181. (setq margin
  182. (if (< margin 0)
  183. (current-column)
  184. (min margin (current-column)))))
  185. (forward-line 1))
  186. margin))
  187. ;;; Return the maximum value of the right margin of all lines. Any
  188. ;;; sentence ending a line has a space guaranteed before the margin.
  189. (defun rebox-right-margin ()
  190. (let ((margin 0) period)
  191. (goto-char (point-min))
  192. (while (not (eobp))
  193. (end-of-line)
  194. (if (bobp)
  195. (setq period 0)
  196. (backward-char 1)
  197. (setq period (if (looking-at "[.?!]") 1 0))
  198. (forward-char 1))
  199. (setq margin (max margin (+ (current-column) period)))
  200. (forward-char 1))
  201. margin))
  202. ;;; Return a regexp to match the start or end of a comment for some
  203. ;;; LANGUAGE, leaving the comment marks themselves available in \1.
  204. ;; FIXME: Recognize style 1** boxes.
  205. (defun rebox-regexp-start (language)
  206. (cond ((= language 0) "^[ \t]*\\(/\\*\\|//+\\|#+\\|;+\\|%+\\)")
  207. ((= language REBOX_LANGUAGE_NONE) "^\\(\\)")
  208. ((= language REBOX_LANGUAGE_C) "^[ \t]*\\(/\\*\\)")
  209. ((= language REBOX_LANGUAGE_C++) "^[ \t]*\\(//+\\)")
  210. ((= language REBOX_LANGUAGE_AWK) "^[ \t]*\\(#+\\)")
  211. ((= language REBOX_LANGUAGE_LISP) "^[ \t]*\\(;+\\)")
  212. ((= language REBOX_LANGUAGE_TEX) "^[ \t]*\\(%+\\)")))
  213. (defun rebox-regexp-end (language)
  214. (cond ((= language 0) "\\(\\*/\\|//+\\|#+\\|;+\\|%+\\)[ \t]*$")
  215. ((= language REBOX_LANGUAGE_NONE) "\\(\\)$")
  216. ((= language REBOX_LANGUAGE_C) "\\(\\*/\\)[ \t]*$")
  217. ((= language REBOX_LANGUAGE_C++) "\\(//+\\)[ \t]*$")
  218. ((= language REBOX_LANGUAGE_AWK) "\\(#+\\)[ \t]*$")
  219. ((= language REBOX_LANGUAGE_LISP) "\\(;+\\)[ \t]*$")
  220. ((= language REBOX_LANGUAGE_TEX) "\\(%+\\)[ \t]*$")))
  221. ;;; By looking at the text starting at the cursor position, guess the
  222. ;;; language in use, and return it.
  223. (defun rebox-guess-language ()
  224. (let ((language REBOX_LANGUAGE_NONE)
  225. (value (* 100 REBOX_MAX_LANGUAGE)))
  226. (while (not (zerop value))
  227. (if (looking-at (rebox-regexp-start value))
  228. (progn
  229. (setq language value)
  230. (setq value 0))
  231. (setq value (- value 100))))
  232. language))
  233. ;;; Find the limits of the block of comments following or enclosing
  234. ;;; the cursor, or return an error if the cursor is not within such a
  235. ;;; block of comments. Extend it as far as possible in both
  236. ;;; directions, then narrow the buffer around it.
  237. (defun rebox-find-and-narrow ()
  238. (save-excursion
  239. (let (start end temp language)
  240. ;; Find the start of the current or immediately following comment.
  241. (beginning-of-line)
  242. (skip-chars-forward " \t\n")
  243. (beginning-of-line)
  244. (if (not (looking-at (rebox-regexp-start 0)))
  245. (progn
  246. (setq temp (point))
  247. (if (re-search-forward "\\*/" nil t)
  248. (progn
  249. (re-search-backward "/\\*")
  250. (if (> (point) temp)
  251. (error "outside any comment block"))
  252. (setq temp (point))
  253. (beginning-of-line)
  254. (skip-chars-forward " \t")
  255. (if (not (= (point) temp))
  256. (error "text before start of comment"))
  257. (beginning-of-line))
  258. (error "outside any comment block"))))
  259. (setq start (point))
  260. (setq language (rebox-guess-language))
  261. ;; - find the end of this comment
  262. (if (= language REBOX_LANGUAGE_C)
  263. (progn
  264. (search-forward "*/")
  265. (if (not (looking-at "[ \t]*$"))
  266. (error "text after end of comment"))))
  267. (end-of-line)
  268. (if (eobp)
  269. (insert "\n")
  270. (forward-char 1))
  271. (setq end (point))
  272. ;; - try to extend the comment block backwards
  273. (goto-char start)
  274. (while (and (not (bobp))
  275. (if (= language REBOX_LANGUAGE_C)
  276. (progn
  277. (skip-chars-backward " \t\n")
  278. (if (and (looking-at "[ \t]*\n[ \t]*/\\*")
  279. (> (point) 2))
  280. (progn
  281. (backward-char 2)
  282. (if (looking-at "\\*/")
  283. (progn
  284. (re-search-backward "/\\*")
  285. (setq temp (point))
  286. (beginning-of-line)
  287. (skip-chars-forward " \t")
  288. (if (= (point) temp)
  289. (progn (beginning-of-line) t)))))))
  290. (previous-line 1)
  291. (looking-at (rebox-regexp-start language))))
  292. (setq start (point)))
  293. ;; - try to extend the comment block forward
  294. (goto-char end)
  295. (while (looking-at (rebox-regexp-start language))
  296. (if (= language REBOX_LANGUAGE_C)
  297. (progn
  298. (re-search-forward "[ \t]*/\\*")
  299. (re-search-forward "\\*/")
  300. (if (looking-at "[ \t]*$")
  301. (progn
  302. (beginning-of-line)
  303. (forward-line 1)
  304. (setq end (point)))))
  305. (forward-line 1)
  306. (setq end (point))))
  307. ;; - narrow to the whole block of comments
  308. (narrow-to-region start end))))
  309. ;;; After refilling it if REFILL is not nil, while respecting a left
  310. ;;; MARGIN, put the narrowed buffer back into a boxed LANGUAGE comment
  311. ;;; box of a given QUALITY and TYPE.
  312. (defun rebox-reconstruct (refill margin language quality type)
  313. (rebox-show-style "Style" (+ language quality type))
  314. (let (right-margin nw nn ne ww ee sw ss se x xx)
  315. ;; - decide the elements of the box being produced
  316. (cond ((= language REBOX_LANGUAGE_NONE)
  317. ;; - planify a comment for no language in particular
  318. (cond ((= quality REBOX_QUALITY_SIMPLE_ONE)
  319. ;; - planify a simple box
  320. (cond ((= type REBOX_TYPE_OPEN)
  321. (setq nw "") (setq sw "")
  322. (setq ww "") (setq ee ""))
  323. ((= type REBOX_TYPE_HALF_SINGLE)
  324. (setq nw "")
  325. (setq ww "| ") (setq ee " |")
  326. (setq sw "+-") (setq ss ?-) (setq se "-+"))
  327. ((= type REBOX_TYPE_SINGLE)
  328. (setq nw "+-") (setq nn ?-) (setq ne "-+")
  329. (setq ww "| ") (setq ee " |")
  330. (setq sw "+-") (setq ss ?-) (setq se "-+"))
  331. ((= type REBOX_TYPE_HALF_DOUBLE)
  332. (setq nw "")
  333. (setq ww "| ") (setq ee " |")
  334. (setq sw "*=") (setq ss ?=) (setq se "=*"))
  335. ((= type REBOX_TYPE_DOUBLE)
  336. (setq nw "*=") (setq nn ?=) (setq ne "=*")
  337. (setq ww "| ") (setq ee " |")
  338. (setq sw "*=") (setq ss ?=) (setq se "=*"))))
  339. ((or (= quality REBOX_QUALITY_ROUNDED_TWO)
  340. (= quality REBOX_QUALITY_ROUNDED_THREE))
  341. ;; - planify a rounded box
  342. (cond ((= type REBOX_TYPE_OPEN)
  343. (setq nw "") (setq sw "")
  344. (setq ww "| ") (setq ee " |"))
  345. ((= type REBOX_TYPE_HALF_SINGLE)
  346. (setq nw "")
  347. (setq ww "| ") (setq ee " |")
  348. (setq sw "`-") (setq ss ?-) (setq se "-'"))
  349. ((= type REBOX_TYPE_SINGLE)
  350. (setq nw ".-") (setq nn ?-) (setq ne "-.")
  351. (setq ww "| ") (setq ee " |")
  352. (setq sw "`-") (setq ss ?-) (setq se "-'"))
  353. ((= type REBOX_TYPE_HALF_DOUBLE)
  354. (setq nw "")
  355. (setq ww "| " ) (setq ee " |" )
  356. (setq sw "\\=") (setq ss ?=) (setq se "=/" ))
  357. ((= type REBOX_TYPE_DOUBLE)
  358. (setq nw "/=" ) (setq nn ?=) (setq ne "=\\")
  359. (setq ww "| " ) (setq ee " |" )
  360. (setq sw "\\=") (setq ss ?=) (setq se "=/" ))))
  361. ((= quality REBOX_QUALITY_STARRED_FOUR)
  362. ;; - planify a starred box
  363. (cond ((= type REBOX_TYPE_OPEN)
  364. (setq nw "") (setq sw "")
  365. (setq ww "| ") (setq ee ""))
  366. ((= type REBOX_TYPE_HALF_SINGLE)
  367. (setq nw "")
  368. (setq ww "* ") (setq ee " *")
  369. (setq sw "**") (setq ss ?*) (setq se "**"))
  370. ((= type REBOX_TYPE_SINGLE)
  371. (setq nw "**") (setq nn ?*) (setq ne "**")
  372. (setq ww "* ") (setq ee " *")
  373. (setq sw "**") (setq ss ?*) (setq se "**"))
  374. ((= type REBOX_TYPE_HALF_DOUBLE)
  375. (setq nw "")
  376. (setq ww "X ") (setq ee " X")
  377. (setq sw "XX") (setq ss ?X) (setq se "XX"))
  378. ((= type REBOX_TYPE_DOUBLE)
  379. (setq nw "XX") (setq nn ?X) (setq ne "XX")
  380. (setq ww "X ") (setq ee " X")
  381. (setq sw "XX") (setq ss ?X) (setq se "XX"))))))
  382. ((= language REBOX_LANGUAGE_C)
  383. ;; - planify a comment for C
  384. (cond ((= quality REBOX_QUALITY_SIMPLE_ONE)
  385. ;; - planify a simple C comment
  386. (cond ((= type REBOX_TYPE_OPEN)
  387. (setq nw "") (setq sw "")
  388. (setq ww "/* ") (setq ee " */"))
  389. ((= type REBOX_TYPE_HALF_SINGLE)
  390. (setq nw "")
  391. (setq ww "/* ") (setq ee " */")
  392. (setq sw "/* ") (setq ss ?-) (setq se " */"))
  393. ((= type REBOX_TYPE_SINGLE)
  394. (setq nw "/* ") (setq nn ?-) (setq ne " */")
  395. (setq ww "/* ") (setq ee " */")
  396. (setq sw "/* ") (setq ss ?-) (setq se " */"))
  397. ((= type REBOX_TYPE_HALF_DOUBLE)
  398. (setq nw "")
  399. (setq ww "/* ") (setq ee " */")
  400. (setq sw "/* ") (setq ss ?=) (setq se " */"))
  401. ((= type REBOX_TYPE_DOUBLE)
  402. (setq nw "/* ") (setq nn ?=) (setq ne " */")
  403. (setq ww "/* ") (setq ee " */")
  404. (setq sw "/* ") (setq ss ?=) (setq se " */"))))
  405. ((or (= quality REBOX_QUALITY_ROUNDED_TWO)
  406. (= quality REBOX_QUALITY_ROUNDED_THREE))
  407. ;; - planify a rounded C comment
  408. (cond ((= type REBOX_TYPE_OPEN)
  409. ;; ``open rounded'' is a special case
  410. (setq nw "") (setq sw "")
  411. (setq ww " ") (setq ee ""))
  412. ((= type REBOX_TYPE_HALF_SINGLE)
  413. (setq nw "/*") (setq nn ? ) (setq ne " .")
  414. (setq ww "| ") (setq ee " |")
  415. (setq sw "`-") (setq ss ?-) (setq se "*/"))
  416. ((= type REBOX_TYPE_SINGLE)
  417. (setq nw "/*") (setq nn ?-) (setq ne "-.")
  418. (setq ww "| ") (setq ee " |")
  419. (setq sw "`-") (setq ss ?-) (setq se "*/"))
  420. ((= type REBOX_TYPE_HALF_DOUBLE)
  421. (setq nw "/*" ) (setq nn ? ) (setq ne " \\")
  422. (setq ww "| " ) (setq ee " |" )
  423. (setq sw "\\=") (setq ss ?=) (setq se "*/" ))
  424. ((= type REBOX_TYPE_DOUBLE)
  425. (setq nw "/*" ) (setq nn ?=) (setq ne "=\\")
  426. (setq ww "| " ) (setq ee " |" )
  427. (setq sw "\\=") (setq ss ?=) (setq se "*/" ))))
  428. ((= quality REBOX_QUALITY_STARRED_FOUR)
  429. ;; - planify a starred C comment
  430. (cond ((= type REBOX_TYPE_OPEN)
  431. (setq nw "/* ") (setq nn ? ) (setq ne "")
  432. (setq ww " * ") (setq ee "")
  433. (setq sw " */") (setq ss ? ) (setq se ""))
  434. ((= type REBOX_TYPE_HALF_SINGLE)
  435. (setq nw "/* ") (setq nn ? ) (setq ne " *")
  436. (setq ww " * ") (setq ee " *")
  437. (setq sw " **") (setq ss ?*) (setq se "**/"))
  438. ((= type REBOX_TYPE_SINGLE)
  439. (setq nw "/**") (setq nn ?*) (setq ne "**")
  440. (setq ww " * ") (setq ee " *")
  441. (setq sw " **") (setq ss ?*) (setq se "**/"))
  442. ((= type REBOX_TYPE_HALF_DOUBLE)
  443. (setq nw "/* " ) (setq nn ? ) (setq ne " *\\")
  444. (setq ww "|* " ) (setq ee " *|" )
  445. (setq sw "\\**") (setq ss ?*) (setq se "**/" ))
  446. ((= type REBOX_TYPE_DOUBLE)
  447. (setq nw "/**" ) (setq nn ?*) (setq ne "**\\")
  448. (setq ww "|* " ) (setq ee " *|" )
  449. (setq sw "\\**") (setq ss ?*) (setq se "**/" ))))))
  450. (t
  451. ;; - planify a comment for all other things
  452. (if (and (= language REBOX_LANGUAGE_C++)
  453. (= quality REBOX_QUALITY_SIMPLE_ONE))
  454. (setq quality REBOX_QUALITY_ROUNDED_TWO))
  455. (setq x (cond ((= language REBOX_LANGUAGE_C++) ?/)
  456. ((= language REBOX_LANGUAGE_AWK) ?#)
  457. ((= language REBOX_LANGUAGE_LISP) ?\;)
  458. ((= language REBOX_LANGUAGE_TEX) ?%)))
  459. (setq xx (make-string (/ quality 10) x))
  460. (setq ww (concat xx " "))
  461. (cond ((= type REBOX_TYPE_OPEN)
  462. (setq nw "") (setq sw "") (setq ee ""))
  463. ((= type REBOX_TYPE_HALF_SINGLE)
  464. (setq ee (concat " " xx))
  465. (setq nw "")
  466. (setq sw ww) (setq ss ?-) (setq se ee))
  467. ((= type REBOX_TYPE_SINGLE)
  468. (setq ee (concat " " xx))
  469. (setq nw ww) (setq nn ?-) (setq ne ee)
  470. (setq sw ww) (setq ss ?-) (setq se ee))
  471. ((= type REBOX_TYPE_HALF_DOUBLE)
  472. (setq ee (concat " " xx))
  473. (setq xx (make-string (1+ (/ quality 10)) x))
  474. (setq nw "")
  475. (setq sw xx) (setq ss x) (setq se xx))
  476. ((= type REBOX_TYPE_DOUBLE)
  477. (setq ee (concat " " xx))
  478. (setq xx (make-string (1+ (/ quality 10)) x))
  479. (setq nw xx) (setq nn x) (setq ne xx)
  480. (setq sw xx) (setq ss x) (setq se xx)))))
  481. ;; - possibly refill, and adjust margins to account for left inserts
  482. (if (not (and flag (listp flag)))
  483. (let ((fill-prefix (make-string margin ? ))
  484. (fill-column (- fill-column (+ (length ww) (length ee)))))
  485. (fill-region (point-min) (point-max))))
  486. (setq right-margin (+ (rebox-right-margin) (length ww)))
  487. ;; - construct the box comment, from top to bottom
  488. (goto-char (point-min))
  489. (if (and (= language REBOX_LANGUAGE_C)
  490. (or (= quality REBOX_QUALITY_ROUNDED_TWO)
  491. (= quality REBOX_QUALITY_ROUNDED_THREE))
  492. (= type REBOX_TYPE_OPEN))
  493. (progn
  494. ;; - construct an 33 style comment
  495. (skip-chars-forward " " (+ (point) margin))
  496. (insert (make-string (- margin (current-column)) ? )
  497. "/* ")
  498. (end-of-line)
  499. (forward-char 1)
  500. (while (not (eobp))
  501. (skip-chars-forward " " (+ (point) margin))
  502. (insert (make-string (- margin (current-column)) ? )
  503. ww)
  504. (beginning-of-line)
  505. (forward-line 1))
  506. (backward-char 1)
  507. (insert " */"))
  508. ;; - construct all other comment styles
  509. ;; construct one top line
  510. (if (not (zerop (length nw)))
  511. (progn
  512. (indent-to margin)
  513. (insert nw)
  514. (if (or (not (eq nn ? )) (not (zerop (length ne))))
  515. (insert (make-string (- right-margin (current-column)) nn)
  516. ne))
  517. (insert "\n")))
  518. ;; construct one middle line
  519. (while (not (eobp))
  520. (skip-chars-forward " " (+ (point) margin))
  521. (insert (make-string (- margin (current-column)) ? )
  522. ww)
  523. (end-of-line)
  524. (if (not (zerop (length ee)))
  525. (progn
  526. (indent-to right-margin)
  527. (insert ee)))
  528. (beginning-of-line)
  529. (forward-line 1))
  530. ;; construct one bottom line
  531. (if (not (zerop (length sw)))
  532. (progn
  533. (indent-to margin)
  534. (insert sw)
  535. (if (or (not (eq ss ? )) (not (zerop (length se))))
  536. (insert (make-string (- right-margin (current-column)) ss)
  537. se "\n")))))))
  538. ;;; Add, delete or adjust a comment box in the narrowed buffer.
  539. ;;; Various FLAG values are explained at beginning of this file.
  540. (defun rebox-engine (flag)
  541. (let ((undo-list buffer-undo-list)
  542. (marked-point (point-marker))
  543. (language (progn (goto-char (point-min)) (rebox-guess-language)))
  544. (quality 0)
  545. (type 0))
  546. (untabify (point-min) (point-max))
  547. ;; Remove all the comment marks, and move all the text rigidly to the
  548. ;; left for insuring that the left margin stays at the same place.
  549. ;; At the same time, try recognizing the box style, saving its quality
  550. ;; in QUALITY and its type in TYPE. (LANGUAGE is already guessed.)
  551. (let ((indent-tabs-mode nil)
  552. (previous-margin (rebox-left-margin))
  553. actual-margin)
  554. ;; FIXME: Cleanup style 1** boxes.
  555. ;; FIXME: Recognize really all cases of type and quality.
  556. ;; - remove all comment marks
  557. (if (= language REBOX_LANGUAGE_NONE)
  558. nil
  559. (goto-char (point-min))
  560. (while (re-search-forward (rebox-regexp-start language) nil t)
  561. (goto-char (match-beginning 1))
  562. (delete-region (point) (match-end 1))
  563. (insert (make-string (- (match-end 1) (point)) ? )))
  564. (goto-char (point-min))
  565. (while (re-search-forward (rebox-regexp-end language) nil t)
  566. (replace-match "" t t)))
  567. (if (= language REBOX_LANGUAGE_C)
  568. (progn
  569. (goto-char (point-min))
  570. (while (re-search-forward "\\*/ */\\*" nil t)
  571. (replace-match " " t t))
  572. (goto-char (point-min))
  573. (while (re-search-forward "^\\( *\\)|\\*\\(.*\\)\\*| *$" nil t)
  574. (setq quality REBOX_QUALITY_STARRED_FOUR)
  575. (setq type REBOX_TYPE_DOUBLE)
  576. (replace-match "\\1 \\2" t))
  577. (goto-char (point-min))
  578. (while (re-search-forward "^\\( *\\)\\*\\(.*\\)\\* *$" nil t)
  579. (setq quality REBOX_QUALITY_STARRED_FOUR)
  580. (setq type REBOX_TYPE_SINGLE)
  581. (replace-match "\\1 \\2" t))
  582. (goto-char (point-min))
  583. (while (re-search-forward "^\\( *\\)|\\(.*\\)| *$" nil t)
  584. (setq quality REBOX_QUALITY_ROUNDED_TWO)
  585. (replace-match "\\1 \\2" t))
  586. (goto-char (point-min))
  587. (if (zerop quality)
  588. (while (re-search-forward "^\\( +\\)\\* " nil t)
  589. (setq quality REBOX_QUALITY_STARRED_FOUR)
  590. (setq type REBOX_TYPE_OPEN)
  591. (replace-match "\\1 " t)))))
  592. ;; - remove the first dashed or starred line
  593. (goto-char (point-min))
  594. (if (looking-at "^ *\\(--+\\|\\*\\*+\\)[.\+\\]? *\n")
  595. (progn
  596. (setq type REBOX_TYPE_SINGLE)
  597. (replace-match "" t t))
  598. (if (looking-at "^ *\\(==\\|XX+\\|##+\\|;;+\\)[.\+\\]? *\n")
  599. (progn
  600. (setq type REBOX_TYPE_DOUBLE)
  601. (replace-match "" t t))))
  602. ;; - remove the last dashed or starred line
  603. (goto-char (point-max))
  604. (previous-line 1)
  605. (if (looking-at "^ *[`\+\\]?*--+ *\n")
  606. (progn
  607. (if (= type REBOX_TYPE_OPEN)
  608. (setq type REBOX_TYPE_HALF_SINGLE))
  609. (replace-match "" t t))
  610. (if (looking-at "^ *[`\+\\]?*\\(==+\\|##+\\|;;+\\) *\n")
  611. (progn
  612. (if (= type REBOX_TYPE_OPEN)
  613. (setq type REBOX_TYPE_HALF_DOUBLE))
  614. (replace-match "" t t))
  615. (if (looking-at "^ *\\*\\*+[.\+\\]? *\n")
  616. (progn
  617. (setq quality REBOX_QUALITY_STARRED_FOUR)
  618. (setq type REBOX_TYPE_HALF_SINGLE)
  619. (replace-match "" t t))
  620. (if (looking-at "^ *XX+[.\+\\]? *\n")
  621. (progn
  622. (setq quality REBOX_QUALITY_STARRED_FOUR)
  623. (setq type REBOX_TYPE_HALF_DOUBLE)
  624. (replace-match "" t t))))))
  625. ;; - remove all spurious whitespace
  626. (goto-char (point-min))
  627. (while (re-search-forward " +$" nil t)
  628. (replace-match "" t t))
  629. (goto-char (point-min))
  630. (if (looking-at "\n+")
  631. (replace-match "" t t))
  632. (goto-char (point-max))
  633. (skip-chars-backward "\n")
  634. (if (looking-at "\n\n+")
  635. (replace-match "\n" t t))
  636. (goto-char (point-min))
  637. (while (re-search-forward "\n\n\n+" nil t)
  638. (replace-match "\n\n" t t))
  639. ;; - move the text left is adequate
  640. (setq actual-margin (rebox-left-margin))
  641. (if (not (= previous-margin actual-margin))
  642. (indent-rigidly (point-min) (point-max)
  643. (- previous-margin actual-margin))))
  644. ;; Override box style according to FLAG or chosen default style.
  645. ;; Else, use either recognized style elements or built-in defaults.
  646. (cond ((and (numberp flag) (not (zerop (/ flag 100))))
  647. (setq language (* (/ flag 100) 100)))
  648. ((not (zerop (/ rebox-default-style 100)))
  649. (setq language (* (/ rebox-default-style 100) 100))))
  650. (cond ((and (numberp flag) (not (zerop (% (/ flag 10) 10))))
  651. (setq quality (* (% (/ flag 10) 10) 10)))
  652. ((not (zerop (% (/ rebox-default-style 10) 10)))
  653. (setq quality (* (% (/ rebox-default-style 10) 10) 10)))
  654. ((zerop quality)
  655. (setq quality REBOX_QUALITY_ROUNDED_TWO)))
  656. (cond ((and (numberp flag) (not (zerop (% flag 10))))
  657. (setq type (% flag 10)))
  658. ((not (zerop (% rebox-default-style 10)))
  659. (setq type (% rebox-default-style 10)))
  660. ((zerop type)
  661. (setq type 1)))
  662. ;; Possibly refill, then reconstruct the comment box.
  663. (let ((indent-tabs-mode nil))
  664. (rebox-reconstruct (not (and flag (listp flag)))
  665. (rebox-left-margin)
  666. language quality type))
  667. ;; Retabify to the left only (adapted from tabify.el).
  668. (if indent-tabs-mode
  669. (progn
  670. (goto-char (point-min))
  671. (while (re-search-forward "^[ \t][ \t]+" nil t)
  672. (let ((column (current-column)))
  673. (delete-region (match-beginning 0) (point))
  674. (indent-to column)))))
  675. ;; Restore the point position.
  676. (goto-char (marker-position marked-point))
  677. ;; Remove all intermediate boundaries from the undo list.
  678. (if (not (eq buffer-undo-list undo-list))
  679. (let ((cursor buffer-undo-list))
  680. (while (not (eq (cdr cursor) undo-list))
  681. (if (car (cdr cursor))
  682. (setq cursor (cdr cursor))
  683. (rplacd cursor (cdr (cdr cursor)))))))))
  684. ;;; Set or reset the Taarna team's own way for a C style. You do not
  685. ;;; really want to know about this.
  686. (defvar c-mode-taarna-style nil "*Non-nil for Taarna team C-style.")
  687. (defun taarna-mode ()
  688. (interactive)
  689. (if c-mode-taarna-style
  690. (progn
  691. (setq c-mode-taarna-style nil)
  692. (setq c-indent-level 2)
  693. (setq c-continued-statement-offset 2)
  694. (setq c-brace-offset 0)
  695. (setq c-argdecl-indent 5)
  696. (setq c-label-offset -2)
  697. (setq c-tab-always-indent t)
  698. (setq rebox-default-style REBOX_QUALITY_ROUNDED_TWO)
  699. (message "C mode: GNU style"))
  700. (setq c-mode-taarna-style t)
  701. (setq c-indent-level 4)
  702. (setq c-continued-statement-offset 4)
  703. (setq c-brace-offset -4)
  704. (setq c-argdecl-indent 4)
  705. (setq c-label-offset -4)
  706. (setq c-tab-always-indent t)
  707. (setq rebox-default-style
  708. (+ REBOX_QUALITY_SIMPLE_ONE REBOX_TYPE_HALF_SINGLE))
  709. (message "C mode: Taarna style")))
  710. ;;; Rebox the current region.
  711. (defun rebox-region (flag)
  712. (interactive "P")
  713. (if (eq flag '-) (setq flag (rebox-ask-for-style)))
  714. (if (rebox-validate-flag flag)
  715. (save-restriction
  716. (narrow-to-region (region-beginning) (region-end))
  717. (rebox-engine flag))))
  718. ;;; Rebox the surrounding comment.
  719. (defun rebox-comment (flag)
  720. (interactive "P")
  721. (if (eq flag '-) (setq flag (rebox-ask-for-style)))
  722. (if (rebox-validate-flag flag)
  723. (save-restriction
  724. (rebox-find-and-narrow)
  725. (rebox-engine flag))))