]> git.donarmstrong.com Git - lib.git/blob - emacs_el/tiny-tools/tiny/tinycomment.el
add tiny-tools
[lib.git] / emacs_el / tiny-tools / tiny / tinycomment.el
1 ;;; tinycomment.el --- Smart comment setting utility
2
3 ;; This file is not part of Emacs
4
5 ;;{{{ Id
6
7 ;; Copyright (C) 1994-2007 Jari Aalto
8 ;; Keywords:     extensions
9 ;; Author:       Jari Aalto
10 ;; Maintainer:   Jari Aalto
11 ;;
12 ;; To get information on this program use ident(1) or call M-x
13 ;; tinycomment-version Look at the code with folding.el
14
15 ;; COPYRIGHT NOTICE
16 ;;
17 ;; This program is free software; you can redistribute it and/or modify it
18 ;; under the terms of the GNU General Public License as published by the Free
19 ;; Software Foundation; either version 2 of the License, or (at your option)
20 ;; any later version.
21 ;;
22 ;; This program is distributed in the hope that it will be useful, but
23 ;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
25 ;; for more details.
26 ;;
27 ;; You should have received a copy of the GNU General Public License
28 ;; along with program; see the file COPYING. If not, write to the
29 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
30 ;; Boston, MA 02110-1301, USA.
31 ;;
32 ;; Visit <http://www.gnu.org/copyleft/gpl.html> for more information
33
34 ;;}}}
35 ;;{{{ Installation
36
37 ;; ........................................................ &t-install ...
38 ;; - Put this file on your Emacs-Lisp load path, add following into your
39 ;;   ~/.emacs startup file
40 ;;
41 ;;      (require            'tinycomment)
42 ;;      (global-set-key     "\M-;" 'tinycomment-indent-for-comment)
43 ;;      (setq-default       comment-column 48)
44 ;;
45 ;;   Or use autoload and your .emacs starts quicker
46 ;;
47 ;;      (global-set-key  "\M-;" 'tinycomment-indent-for-comment)
48 ;;      (autoload 'tinycomment-indent-for-comment "tinycomment" "" t)
49 ;;
50 ;;   If you have any questions, use this function to contact author
51 ;;
52 ;;          M-x tinycomment-submit-bug-report
53
54 ;;}}}
55 ;;{{{ Commentary
56
57 ;;; Commentary:
58
59 ;;}}}
60 ;;{{{ Documentation
61
62 ;;  Preface, Sep 1994
63 ;;
64
65 ;;      In 1994-10-18 Era Eriksson wrote in gnu.emacs.help that he didn't
66 ;;      like 'modes' because they redefined his tab key strangely. What he
67 ;;      wanted was tab 8 in _every possible case_. He wrote: "..if mode
68 ;;      messes with tab key, I don't want it". He also wanted his comments
69 ;;      always to be positioned at column 56 (tab #7). The problem was that
70 ;;      how he could he add comments with tab key, when the mode occied it
71 ;;      already. He also always used to program using `fundamental-mode';
72 ;;      what a cool dude. As a result this package was born. The
73 ;;      original lisp file sent  to Era was posted under name
74 ;;      general-comment.el.
75 ;;
76 ;;  What's this all about, short introduction
77 ;;
78 ;;      Let's see...You're in C/C++ mode, and want to switch to better mode
79 ;;      before starting to adjust comments. But wait, the new mode doesn't
80 ;;      know about C++-comments! Or if you're editing ~/.Xdefauls, there is
81 ;;      no mode for it (at the time of writing), no-one to know the comment
82 ;;      syntax. Boom. Now it's time to give this packet a run. It hooks
83 ;;      itself directly to `\M-;' replacing any previous function. The
84 ;;      packages defines comment syntax and position on the fly when it can
85 ;;      identify the file name. If the file isn't known then it passes
86 ;;      control to mode to handle the commenting. This is handy in
87 ;;      temporary buffers that do not have filename: e.g. *scratch* buffer.
88 ;;      Repetitive calls to `M-;' shift between comment *classes*: comment
89 ;;      is adjusted according to previous one, or move it on the line.
90 ;;
91 ;;  Overview of features
92 ;;
93 ;;      o   Replaces `M-;' comment key. Suitable for any major mode.
94 ;;      o   Determine comment variables on the fly, no matter where you
95 ;;          are or what mode you are using.
96 ;;      o   There is no-list that tells not to touch this mode's commenting.
97 ;;          This is for modes that has `comment-end' which aren't supported.
98 ;;      o   Repetitive `M-;' converts single comment into *bigger* *classes*.
99 ;;      o   Position new comment on empty line by looking at previous
100 ;;          comment.
101 ;;      o   It is possible to define column position for those comments
102 ;;          that are not allowed to move This handy for long lines
103 ;;          or special comments.
104 ;;      o   If there are multiple so called comments, like $#var # comment
105 ;;          in `perl-mode', the last # char is treated as a comment.
106 ;;
107 ;;  Limitations
108 ;;
109 ;;      This isn't designed for modes that have `comment-end', you get
110 ;;      only '/* */' string e.g. in C-mode and no comment class shifting.
111 ;;
112 ;;  Examples
113 ;;
114 ;;      At the end of file there is simple general editing mode, which can
115 ;;      be used for perl, shells, awk, C++ [sometimes]
116
117 ;;}}}
118
119 ;;; Change Log:
120
121 ;;; Code:
122
123 ;;{{{ setup: require
124
125 ;;; ......................................................... &require ...
126
127 (require 'tinylibm)
128
129 (eval-when-compile
130   (ti::package-use-dynamic-compilation))
131
132 (ti::package-defgroup-tiny TinyComment tinycomment-: extensions
133   "Smart comment setting utility
134   Overview of features:
135
136         o   Replaces M-; commenting key. Suitable for any major-mode
137         o   Determines comment variables on the fly, no matter where you
138             are or what mode you are.
139         o   There is no-list that tells not to touch this mode's commenting.
140             This is for modes that has comment-end. TIC can't handle those.
141         o   Repetitive M-; converts single comments into 'bigger classes'
142         o   Positions new comment on empty line by looking at previous
143             comment.
144         o   You can define column position for those comments that are not
145             allowed to move This handy for long lines or special comments.
146         o   If there are multiple 'comments' , like $#var # comment
147             in perl-mode, TIC picks the last # char and treats
148             it as a comment. Emacs commention cope similar situations.")
149
150 ;;}}}
151 ;;{{{ setup:
152
153 ;;; ......................................................... &v-hooks ...
154
155 (defcustom tinycomment-:load-hook nil
156   "*Hook run when package has been loaded."
157   :type 'hook
158   :group 'TinyComment)
159
160 ;;; ........................................................ &v-public ...
161 ;;; User configurable
162
163 (defcustom tinycomment-:not-comment-re ".*[$]\\(#\\)[a-zA-Z]"
164   "*Reject comment position according to subexpression 1.
165 When searching for comment position, the position found will be
166 rejected, if comment subexpression 1 match's position is the same as
167 initially found comment position. The test will be done with `looking-at' at
168 the beginnning of line.
169
170       $#variable_in_csh
171 0123456789 123456789 12345       ;columns
172        *                         ;found comment pos, reject it.")
173
174 (defcustom tinycomment-:tab-call-no-alist
175   '(fundamental-mode
176     text-mode)
177   "*List of modes which enable using TIC's own indent-for-code algorithm.
178
179 Most programming modes supply function that knows how to indent the
180 statement.  But in some cases mode does not supply it's own indent
181 function placed on variable `indent-line-function', which is called by
182 tab key."
183   :type '(repeat (function :tag "Mode function"))
184   :group 'TinyComment)
185
186 (defcustom tinycomment-:adj-no-alist
187   '(lisp-interaction-mode
188     lisp-mode
189     emacs-lisp-mode
190     c-mode ;; we use use // in c++, not /* */
191     pascal-mode)
192   "*List of modes which disable converting comment class.
193
194 The function `tinycomment-adjust-comment' isn't suitable for all possible
195 modes. Eg. Lisp has it's own idea about placing comments according
196 to comment used.
197       ;     --> comment column
198       ;;    --> right to code level
199       ;;;+  --> left margin.
200
201 This defines list of mode names where `tinycomment-adjust-comment' is suppressed
202 and the normal `indent-for-comment' is used."
203   :type '(repeat (function :tag "Mode function"))
204   :group 'TinyComment)
205
206 (defcustom tinycomment-:comment-notify nil
207   "*If non-nil allow printing notify messages.
208 When the comment syntax wasn't found according to file name.
209 The message is _not_ displayed when `buffer-name' contains '*'.
210
211 You may want to set this to 't for awhile, so that you can add all
212 those files that are missing from the list. When you're satisfied,
213 you can turn off the warning."
214   :type 'boolean
215   :group 'TinyComment)
216
217 (defcustom tinycomment-:def-com-pos 'code
218   "*Default comment position for empty lines.
219 Possible choices are:
220
221   'code            code level indent [usually as previous code line]
222   'cpos            normal `comment-column'
223
224 Note that 'cpos doesn't always put comment where you would expect, because
225 it looks back until it finds code. In spite of that, it normally works
226 well _inside_ functions"
227   :type  '(choice
228            (const code)
229            (const cpos))
230   :group 'TinyComment)
231
232 (defcustom tinycomment-:comment-extra-arg 1
233   "*See documentation of `tinycomment-:comment-extra'."
234   :type 'integer
235   :group 'TinyComment)
236
237 (defcustom tinycomment-:comment-extra-stop 63 ;TAB position 64
238   "*See documentation of `tinycomment-:comment-extra'.
239 The comment movement is not done if `current-column' > this variable."
240   :type 'integer
241   :group 'TinyComment)
242
243 (defcustom tinycomment-:comment-extra 'tab
244   "*This affects function `tinycomment-set-com'. Let's see an example:
245
246     abcd abcd abcd abcd abcd abcd[x] abcd abcd # COMMENT
247
248 You have line, where line exeeds the comment column[x] and your
249 comment is at the end. This variable determines how such
250 line is handled when you now hit M-;
251
252 Current choices are:
253     'tab      Insert tab between code and comment, so that they get
254               separated. Any previous whitespace is deleted.
255     'spc      Same, but insert space instead. The number or spaces inserted
256               is told in variable  `tinycomment-:comment-extra-arg'
257
258 None of these actions are carried out if the comment was placed in
259 column `tinycomment-:comment-extra-stop' +1 or further. Such comment is
260 left untouched, because adjusting may push it out of the window edge."
261   :type  '(choice
262            (const tab)
263            (const spc))
264   :group 'TinyComment)
265
266 ;;}}}
267 ;;{{{ setup: -- version notice
268
269 ;;; ....................................................... &v-version ...
270
271 ;;;###autoload (autoload 'tinycomment-version "tinycomment" "Display commentary." t)
272 (eval-and-compile
273   (ti::macrof-version-bug-report
274    "tinycomment.el"
275    "tinycomment"
276    tinycomment-:version-id
277    "$Id: tinycomment.el,v 2.38 2007/05/01 17:20:42 jaalto Exp $"
278    '(tinycomment-:version-id
279      tinycomment-:not-comment-re
280      tinycomment-:tab-call-no-alist
281      tinycomment-:adj-no-alist
282      tinycomment-:comment-notify
283      tinycomment-:def-com-pos
284      tinycomment-:comment-extra-arg
285      tinycomment-:comment-extra-stop
286      tinycomment-:comment-extra)))
287
288 ;;}}}
289
290 ;;; ########################################################### &Funcs ###
291
292 ;;{{{ code: misc
293
294 ;;; ----------------------------------------------------------------------
295 ;;;
296 (defun tinycomment-find-prev-com-col (com-start &optional not-this-col CF)
297   "Look upward to find previous comment column.
298
299 Input:
300
301   COM-START     comment start string.
302   NOT-THIS-COL  if given,  scan backward until different column
303                 is found.
304   CF            tell that comment searched must reside further in
305                 in the line than this column.
306
307 Return:
308
309   nil   unable to find previous comment
310   col"
311   (let* ((re        com-start)
312          (loop      t)
313          ret
314          found)
315     (save-excursion
316       (while loop
317         (beginning-of-line)
318         (setq ret nil found nil)
319         (if (setq found (re-search-backward re nil t))
320             (setq ret (current-column)))
321         (setq loop nil)                 ;default
322         (if (or (null found)
323                 (null not-this-col))
324             nil
325           (if (not (= ret not-this-col))
326               (setq loop nil)                   ;this will do !
327             (setq loop t found nil)))           ;keep searching
328
329         (if (or (null found)
330                 (null CF))
331             nil
332           (if (> ret CF)                ;this IS suitable !
333               (setq loop nil)
334             (setq loop t found nil))))) ;keep going
335     ret))
336
337 ;;; ----------------------------------------------------------------------
338 ;;;
339 (defun tinycomment-find-com-col ()
340   "Look current line to find `comment-start'.
341
342 Return:
343
344    nil
345    nbr  column."
346   (let ((no-com   (or tinycomment-:not-comment-re   "dummy"))
347         (max      (save-excursion (end-of-line) (point)))
348         (clen     (length comment-start))
349         (re       comment-start)
350         ret found
351         not-pos
352         cp)
353     (save-excursion
354       (beginning-of-line)
355       ;;  is there restrictions ?
356       (setq not-pos (if (and (looking-at no-com)
357                              (match-beginning 1))
358                         (match-beginning 1)
359                       nil))
360       (while (re-search-forward re  max t) ; find last comment
361         (setq found t))
362       (if (null found)
363           nil
364         (backward-char clen)
365         (setq cp (point))
366         (if (eq cp not-pos)
367             nil                         ;cannot use this
368           (setq ret (current-column))))
369       ret)))
370
371 ;;}}}
372 ;;{{{ positions
373
374 ;;; ----------------------------------------------------------------------
375 ;;;
376 (defun tinycomment-check-line (mode &optional arg)
377   "Few commands to use to determine line data according to MODE and ARG.
378
379 Return:
380
381   Depends heavily on the MODE"
382   (let* (ret
383          re
384          re2
385          bp
386          p
387          p2)
388     (if (null (symbolp mode)) nil       ;handle literals
389       (cond
390
391        ;;  ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
392        ((and (eq 'code-last-col mode) comment-start)
393         (setq re comment-start)
394         (save-excursion
395           (beginning-of-line)
396           (setq bp (point))
397
398           (if (null (re-search-backward comment-start bp t))
399               nil                       ;not moved anywhere
400             (goto-char (match-beginning 0)))
401           (skip-syntax-backward " " bp)
402           (setq ret (current-column))))
403
404        ;;  ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
405        ;;   find *last* comment start pos
406        ;;   like '// i = 1000;   // temporarily commented out'
407
408        ((and (eq 'com-last-col mode) comment-start)
409         ;;  the '.*' always matches up till last one
410         (setq re (concat ".*\\(" comment-start  "\\)"  ))
411         (save-excursion
412           (beginning-of-line)
413           (if (not (looking-at re))
414               nil
415             (goto-char (match-beginning 1))
416             (setq ret (current-column)))))
417
418        ;;  ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
419        ;;  whole line is 'alone' comment, so that there is no
420        ;;  double comments, return it's starting position
421        ;;  Double comment is like the previous cond-case
422
423        ((and (eq 'com-alone-col mode) comment-start)
424         (setq re (concat "[ \t]*\\(" comment-start  "\\)"  ))
425
426         ;;  notice COM + SPC in re2
427         ;;  - user may write '// this is separator /////////////////////'
428         ;;    But that's one comment
429         ;;  - '// i = MaxPos; // commented'. There is SPC in second
430         ;;    comment, so it has to be Double Commented line.
431
432         (setq re2 (concat ".*\\(" comment-start  " \\)"  ))
433
434         (save-excursion
435           (beginning-of-line)
436           (if (not (looking-at re))
437               nil
438             (setq p (match-beginning 1))
439             (if (not (looking-at re2))
440                 (progn                  ;only single comment
441                   (goto-char p)
442                   (setq ret (current-column)))
443               (setq p2 (match-beginning 1))
444               (if (not (eq p p2))       ;Double Commented
445                   nil
446                 (goto-char p)           ;same comment hit twice
447                 (setq ret (current-column)))))))
448
449        ;;  ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
450        ((eq 'eolpos mode)
451         (save-excursion (end-of-line) (setq ret (point))))
452
453        ;;  ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
454        ((eq 'bolpos mode)
455         (save-excursion (beginning-of-line) (setq ret (point))))
456
457        ;;  ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
458        ((eq 'emptyEol mode)
459         ;; If the rest of line empty ?
460         (setq ret (looking-at "[ \t]*")))))
461     ret))
462
463 ;;; ----------------------------------------------------------------------
464 ;;;
465 (defun tinycomment-find-comment-col (com-start)
466   "Look upward to find possible COM-START position."
467   (save-excursion
468     (if (re-search-backward (regexp-quote com-start) nil t)
469         (current-column))))
470
471 ;;; ----------------------------------------------------------------------
472 ;;;
473 (defun tinycomment-find-code-col (com-start)
474   "Look upward to find possible code indent column. Use COM-START.
475 Eg.
476
477    echo something
478                      # ridiculous comment
479    <now press ESC ;> # inserts comment here
480
481 The problem is that the first comment is considered as indent
482 for code by normal Lisp functions, when it should be the 'echo' line.
483 We look upward till there is code line that isn't full comment line.
484
485 NOTE:
486
487   This doesn't work on C/C++, or any mode that has `comment-end',
488   because we can't keep track of multiline comments.
489
490 Return:
491
492   nbr           found code, proposed column returned.
493   nil           unable to find proper code indent"
494   (let* ((re-com  (concat
495                    "^[ \t]*" (regexp-quote com-start)
496                    "\\|^[ \t]*$"))      ;skip empty lines.
497          (move t)
498          p                              ;point mark
499          ret)
500     (save-excursion
501       (while (and move (eq ret nil))    ;while RET is not set
502         (re-search-backward "[^ \t]+" nil t)
503         (if (save-excursion
504               (beginning-of-line)
505               (looking-at re-com))      ;ignore full comment lines.
506             (if (eq (point) p)          ;have we moved since?
507                 (setq move nil))        ;we're stucked .. :-C
508           ;; Maybe this real code line?
509
510           (setq ret (1+ (current-column)))) ;1+ due to re-search
511         (setq p (point))))
512     ret))
513
514 ;;}}}
515
516 ;;; ######################################################### &comment ###
517 ;;; The real engine parts to do the job
518
519 ;;{{{ tinycomment-set-com
520
521 ;;; ----------------------------------------------------------------------
522 ;;; See simple.el (funcall comment-indent-function)
523 ;;; - Funny thing is that you just can't set comment-column to NBR
524 ;;;   and expect it to be comment place, because the indent-for-comment
525 ;;;   might decide to move the position to another place!
526 ;;; - This function instead, will always put comment there where
527 ;;;   user want's it.
528 ;;;
529 (defun tinycomment-set-com (&optional new)
530   "Lighter version of function `indent-for-comment'.
531 Moves current comment tocomment-position. Doesn't signal any errors.
532
533 Features:
534
535 -  if there is multiple comments on the line, like in shell or
536    perl code '#', the last one is considered as comment, *unless*
537    optional artgument NEW is given. In that case, nothing is considered
538    as old comments.
539 -  If line is too long for comment column it inserts additional SPC or TAB
540    between the code and comment. See variable `tinycomment-:comment-extra'
541
542 Return:
543
544   t             position changed OR new comment added
545   nil           position not allowed"
546   (let* (
547          (xtra     tinycomment-:comment-extra)
548          (x-spc    (make-string tinycomment-:comment-extra-arg ?\ ))
549          (x-spc    (if (eq 'tab xtra) "\t" x-spc)) ; what's the insert type ?
550          (stop-col tinycomment-:comment-extra-stop)
551          (ep       (save-excursion (end-of-line) (point)))
552          (skip     (or comment-start-skip  comment-start))
553
554          found
555          bp                             ;BEG of line point
556          com-c code-c com-p
557          ret)
558     (beginning-of-line)
559     (setq bp (point))
560
561     (if (null new)                      ;did user say new vomment ?
562         (while (re-search-forward skip ep t) ;last comment
563           (setq found t)))
564
565 ;;;    (d! skip new found (match-beginning 0))
566     (if (null found)
567         (progn
568           (end-of-line)
569           (indent-to comment-column)
570           (insert comment-start)
571           (setq ret t))
572
573       ;;  first set comment position
574       (goto-char (match-beginning 0))
575       (setq com-p (point))
576       (setq com-c (current-column))     ;comment column
577
578       ;; Now where is the code position
579       ;; Give argument "nil" (no limit) for skip syntax function is line
580       ;; is first line in buffer.
581       ;;
582       (backward-char 1)
583       (skip-syntax-backward " " (if (eq 1 bp)
584                                     nil
585                                   (1- bp)))
586       (setq code-c (current-column))
587
588       (goto-char com-p)
589 ;;;      (d! "#set" (current-column) comment-column com-c)
590
591       (if (= comment-column com-c)
592           nil                           ;nothing to do
593         (setq ret t)
594         (if (< code-c comment-column)
595             (progn                      ;we can indent ok
596               (delete-horizontal-space)
597 ;;;           (d! "deleted")
598               (indent-to comment-column))
599           ;;  line is too long to get position to comment-col
600 ;;;       (d! "Too long line..." (point)  com-c stop-col)
601           (if (> com-c stop-col) nil    ;do not touch this
602             (delete-horizontal-space)
603 ;;;         (d! "del ok" )
604             (insert x-spc)))))
605 ;;;    (d! "#set end" ret (current-column))
606     ret))
607
608 ;;}}}
609 ;;{{{ tinycomment-adj-com
610
611 ;;; ----------------------------------------------------------------------
612 ;;; Original idea in asm-mode.el by :
613 ;;;   Martin Neitzel,  Techn. Univ. Braunschweig, W.Germany
614 ;;;   BITNET/EARN:   neitzel@dbsinf6.bitnet    (mail via bitnet preferred)
615 ;;
616 ;;; - Thank you Martin! I'm Afraid the code isn't like yours any more,
617 ;;;   but the same principle 'converting to bigger class'
618 ;;;   is preserved.
619 ;;; - This is self standing function.
620 ;;;
621 ;;; - I really should write this again some day, divide into more smaller
622 ;;;   blocks of funcs...
623 ;;;
624 (defun tinycomment-adjust-comment ()
625   "Introduce a comment or convert an already existing comment to next class.
626 These are the known comment classes:
627
628         1-- Left margin             ;; omitted if there is CODE on the line
629         2-- indented like code
630         3-- on comment column
631
632 Suggested usage: while writing your code, trigger this command repeatedly
633 until you are satisfied with the comment.
634
635 Comment on it's own line note:
636
637 - Following lines has two comment chars '#', I call it double commented line.
638               # comment text # more text
639               # set myVariable = 100;      # temporarily commented
640   Because It's hard to know if the line is 'full comment' as in case 1, or
641   has 'code temporarily commented out' as line 2, we always consider
642   line as 'full comment' if line starts with `comment-start'.
643 - In this case whole line moves when converting to classes.
644
645 Code note:
646
647 -  `tinycomment-set-com' is used instead of standard `indent-for-comment'.
648 -  Considered adding 4th choice: indent like previous comment,
649    but I decided 4th choice or 4 taps was too much...3 seemed ideal,
650    so I left it out from 'full comment line'."
651   (let* (
652          (def-place tinycomment-:def-com-pos)
653          (tab-alist tinycomment-:tab-call-no-alist)
654          (ci        (current-indentation))
655          (cc        (current-column))
656          (com       comment-start)
657          (col       comment-column)
658          (clen      (length comment-start))
659
660          ;;    handle ONLY lines that have only comment, no code.
661          (re-com    (concat "^[ \t]*\\(" (regexp-quote com) "+\\)"))
662          (re-com2   (concat ".*" (regexp-quote com)))
663
664          cur-code-c
665          prev-cc cur-cc                 ;various com-col points
666          code-col
667          class
668          prev-code-ind
669          cont
670          tmp)
671
672     (catch 'done
673       (if (or (not (integerp col)) (not (stringp com)))
674           (error "comment-[column/start] not set"))
675
676       (when (string-match "^[ \t]*$" com) ;empty comment?
677         (if (tinycomment-check-line 'emptyEol)
678             (indent-to col)
679           (message "tinycomment-adj: no comment-start defined.")
680           (throw 'done t)))
681
682       (setq cur-code-c (tinycomment-check-line 'code-last-col))
683       (setq prev-cc (tinycomment-find-prev-com-col com col cur-code-c)) ;previous c col
684       (setq cur-cc (tinycomment-find-com-col)) ;current comment column
685
686       ;;  - If we do NOT already have a comment, indent for a new one.
687       (beginning-of-line)
688
689       (unless (looking-at re-com)       ;comment on it's own line ?
690 ;;;     (d! (looking-at re-com2) re-com2)
691         ;; .............................................................
692         (cond
693          ;;  no comment at all or not suitable comment ?
694          ((or (null (setq tmp (looking-at re-com2)))
695               (and tmp
696                    (null (tinycomment-find-com-col)))) ;it isn't suitable
697           (if (not (looking-at "[ \t]*$"))             ; CODE + no COM
698               (progn
699 ;;;             (d! "new")
700                 (tinycomment-set-com 'new) ;Normal column, but it'll be changed
701                 (setq cur-cc (tinycomment-find-com-col))
702                 (setq class 3))         ;indent like prev line by DEF
703             ;;  empty line
704             (insert com)                ;see cont, it passes thru
705 ;;;         (d! "Insert 1")
706
707             ;;  User propably want CODE level indent on empty line by DEF
708             (if (eq def-place 'code )
709                 (setq cont t))))
710
711          ;;   There is existing comment
712          ((and cur-cc (= cur-cc col))   ;change class if possible
713           (setq class 3))
714
715          ((and cur-cc prev-cc           ;make sure these are set
716                (or (null prev-cc) (= cur-cc prev-cc)))
717           ;;   possibly change class to standard column
718 ;;;       (d! "set com")
719           (tinycomment-set-com)) ; no prev comment or position was same
720
721          (t
722           ;;  add New comment
723 ;;;       (d! "new--")
724           (tinycomment-set-com)))
725
726 ;;;     (d! "CLASS " class cur-cc col)
727         ;;   Determine how CODE + COM line is handled
728         (when (eq class 3)
729
730           (save-excursion
731             (forward-line -1) (end-of-line)
732             (setq prev-code-ind (tinycomment-find-comment-col com)))
733
734 ;;;       (d! "#1 prev" (point) "col" cur-code-c col
735 ;;;           "cc" prev-cc  cur-cc  "ind" prev-code-ind )
736
737           (if (or (null prev-code-ind)  ;No code found
738                   (>= cur-code-c col)   ;cannot put to comment-col
739                   (null prev-cc)   ;cannot convert to class, isn't set
740                   (>= cur-code-c prev-cc) ;cannot use prev com class
741                   (not (= cur-cc col)))   ;convert to com-col CLASS
742               (progn
743 ;;;             (d! "#1.1 com-col" col)
744                 (tinycomment-set-com))
745
746             ;;   Convert to previous comment column class then
747 ;;;         (d! "#2 prev" prev-cc "cur" cur-cc "code" code-c)
748             (setq comment-column prev-cc) ; change temporarily
749             (tinycomment-set-com)
750             ;; restore value
751             (setq comment-column col)))
752
753 ;;;     (d! "cont" cont)
754         (if cont
755             nil                         ;do we continue forward ?
756           (if (not (eolp))
757               (forward-char (length comment-start)))
758
759           (throw 'done t)))
760
761 ;;;      (d! "Comment ok")
762
763       ;; --``-- --``-- --``-- --``-- --``-- --``-- --``-- --``-- --``--
764       ;;  There is a comment, convert it between classes.
765       ;;  Also correct the search position due to S-FWD command
766
767       (beginning-of-line)
768       (if (re-search-forward comment-start (tinycomment-check-line 'eolpos))
769           (goto-char (match-beginning 0)))
770
771       (setq cc (current-column))        ;at front of comment
772       (setq code-col (tinycomment-find-code-col com))
773
774       ;;   First select where to convert?
775       (cond
776        ((= cc 0)                        ;BEG of line ?
777         (setq class 1))
778
779        ((or (eq code-col cc)
780             (eq cc col))                ; in Comment column ?
781         (setq class 0))
782
783        ((and (not (eq ci 0))            ; prallel to code ?
784              (not (eq cc col)))         ; this is rough guess...
785         (setq class 2)))
786
787 ;;;      (d! "cc" cc ci col class)
788
789       ;; --``-- --``-- --``-- --``-- --``-- --``-- --``-- --``-- --``--
790 ;;;   (d! "TIC-ADJ" (point) (bolp) cc col class)
791
792       (cond                             ;Now the converting procedure
793        ((eq class 0)                    ;BEG of line
794         (delete-horizontal-space))
795
796        ((eq class 1)                    ;code level
797         (beginning-of-line) (delete-horizontal-space)
798
799         ;; Are we allowed to indent this by ourself ?
800         (if (null (memq major-mode tab-alist))
801             (indent-according-to-mode)  ;let mode place the statement
802
803           (if (null code-col)           ;no code
804               (indent-to comment-column)
805             (if (and (= cc 0) (= col 0)) ;if suggested POS is same
806                 (indent-relative))
807             (indent-to col))))
808
809        ((eq class 2)                    ;column level
810         (indent-to col)))
811       (forward-char clen))              ;after class change
812
813     ;;  do we need to restore the point ? [experimental]
814     ;;    (if save-excur (goto-char op))
815     nil))                               ;
816
817 ;;}}}
818 ;;{{{ code: main
819
820 ;;; ----------------------------------------------------------------------
821 ;;;
822 (defun tinycomment-status ()
823   "Displays comment info."
824   (interactive)
825   (message
826    (concat
827     "cc=" (prin1-to-string comment-column) " "
828     "cs=" (prin1-to-string comment-start) " "
829     "ce=" (prin1-to-string comment-end) " "
830     "css=" (prin1-to-string comment-start-skip) " ")))
831
832 ;;; ----------------------------------------------------------------------
833 ;;;
834 (defun tinycomment-set-c-vars-maybe (&optional cs ce cc css)
835   "Set comment variables CS CE CC and CSS.
836 The names are `comment-start' `comment-end' etc. If some
837 comment variable is nil, it will be set to some harmless value."
838   (if (null cs)                 (setq comment-start ""))
839   (if (null ce)                 (setq comment-end ""))
840   (if (not (integerp cc))       (setq comment-column 48))
841   (if (null css)                (setq comment-start-skip "")))
842
843 ;;; ----------------------------------------------------------------------
844 ;;;
845 ;;;###autoload
846 (defun tinycomment-indent-for-comment ()
847   "Alternative to standard `indent-for-comment'.
848 Relies on file extension
849 and doesn't need specific mode to be turned on. Temporary buffers
850 that has no file name cannot be identified by this function, so
851 it passes control directly to mode. There is a chance you might not
852 even notice that this function is working on the background.
853
854 Verbose warnings are enabled by `tinycomment-:comment-notify'
855 Special cases are handled by tinycomment-:comment-extra* variables
856 Version info is on \\[tinycomment-version]."
857   (interactive)
858   (let* ((warn          tinycomment-:comment-notify) ;; shorter name
859          (no-list       tinycomment-:adj-no-alist)
860          (com-col       48)         ;default comment column if not set
861          elt
862          (mode-desc     (or (ti::id-info nil 'variable-lookup)
863                             (concat
864                              "code-"
865                              (replace-regexp-in-string
866                               "-mode" "" (symbol-name major-mode))))))
867
868     (if mode-desc
869         (setq elt (ti::id-cnv-txt2comment mode-desc)))
870
871     (if warn
872         (setq warn warn))               ;XE 19.14 ByteComp silencer
873
874     (tinycomment-set-c-vars-maybe
875      comment-start comment-end comment-column comment-start-skip)
876
877     (cond
878      ;; ........................................ mode's own commenting ...
879      ((or (memq major-mode no-list)
880           (null mode-desc))
881       ;;   let mode handle comment classes, only IF NOT SET
882       ;;   but let's correct some user mistakes first...
883       (indent-for-comment))             ;mode call...)
884
885      (t
886       ;; ............................................... real engine ...
887
888       (if (ti::nil-p comment-start)     ;they are not defined.
889           (if elt                       ;we have comment info?
890               (setq comment-start (car elt) comment-end (or (cdr elt) ""))))
891
892       (tinycomment-set-c-vars-maybe
893        comment-start comment-end comment-column comment-start-skip)
894
895       ;;   if the position is NOT set use default comment position
896       ;;
897       (if (not (integerp comment-column))
898           (setq comment-column com-col))
899
900       ;;  - The indent-for-comment WON'T work if this is nill
901       ;;    See simple.el for function def.
902       ;;  - We don't set _right_ value, just sufficent replacement.
903       ;;
904       (setq comment-start-skip (concat comment-start "+"))
905       (tinycomment-adjust-comment)
906
907       (if (and warn (ti::nil-p comment-start))
908           (message
909            "TIC: unknown file, no comment syntax available")) ))))
910
911 ;;}}}
912
913 ;;{{{ example setup
914
915 ;;; ......................................................... &example ...
916 ;;; - Copy this, and use M-% to remove comment prefixes ';;* '
917 ;;; - Code can also be extracted with function tinylib.el/ti::package-rip-magic
918
919 ;;* (autoload 'turn-on-tinytab-mode "tinytab" "" t)
920 ;;_
921 ;;* (defun my-fundamental-mode ()
922 ;;*   "my fundamental-mode"
923 ;;*   (interactive)
924 ;;*   (fundamental-mode)
925 ;;*   (turn-on-tinytab-mode)
926 ;;*   (setq tinytab-tt-mode nil)
927 ;;*   (if (fboundp 'folding-mode)
928 ;;*       (ti::funcall 'folding-mode))
929 ;;*   (recenter)                                ;Show visible notification
930 ;;*   ;; delete possible comment settings
931 ;;*   (setq comment-start nil
932 ;;*        comment-end    nil
933 ;;*        comment-column nil
934 ;;*     ;;   very important to restore this !! See simple.el
935 ;;*         comment-indent-hook '(lambda () comment-column)))
936 ;;* _
937 ;;* (add-hook 'c++-mode-hook  'my-c++-mode-hook)
938 ;;* _
939 ;;* (defun my-c++-mode-hook ()
940 ;;*   (setq comment-column nil   ;; When set to nil, tinycomment.el takes over.
941 ;;*     comment-start nil
942 ;;*     comment-end nil))
943
944 ;;}}}
945
946 (provide 'tinycomment)
947 (run-hooks       'tinycomment-:load-hook)
948
949 ;;; tinycomment.el ends here