Annotation of 43BSDReno/contrib/emacs-18.55/lisp/hideif.el, revision 1.1.1.1

1.1       root        1: ;;; hide-ifdef-mode.el   Hides selected code within ifdef.
                      2: ;;;
                      3: ;;; Copyright (C) 1988 Brian Marick and Daniel LaLiberte
                      4: ;;; Written by Brian Marick, at Gould, Computer Systems Division, Urbana IL.
                      5: ;;; Extensively modified by Daniel LaLiberte (while at Gould).
                      6: ;;;
                      7: ;;; You may freely modify and distribute this, but keep a record
                      8: ;;; of modifications and send comments to:
                      9: ;;;     [email protected]  or  ihnp4!uiucdcs!liberte
                     10: ;;; I will continue to upgrade hide-ifdef-mode
                     11: ;;; with your contributions and will eventually offer it to FSF.
                     12: ;;;
                     13: ;;; $Header: hide-ifdef-mode.el,v 1.7 88/02/16 03:12:58 liberte Exp $
                     14: ;;;
                     15: ;;; $Log:      hide-ifdef-mode.el,v $
                     16: ;;; Revision 1.7  88/02/16  03:12:58  liberte
                     17: ;;; Fixed comments and doc strings.
                     18: ;;; Added optional prefix arg for ifdef motion commands.
                     19: ;;; 
                     20: ;;; Revision 1.6  88/02/05  00:36:18  liberte
                     21: ;;; Bug fixes.
                     22: ;;; 1. A multi-line comment that starts on an #ifdef line
                     23: ;;;    now ends on that line.
                     24: ;;; 2. Fix bad function name: hide-hif-ifdef-toggle-read-only
                     25: ;;; 3. Make ifdef-block hiding work outside of ifdefs.
                     26: ;;; 
                     27: ;;; Revision 1.5  88/01/31  23:19:31  liberte
                     28: ;;; Major clean up.
                     29: ;;;   Prefix internal names with "hif-".
                     30: ;;; 
                     31: ;;; Revision 1.4  88/01/30  14:09:38  liberte
                     32: ;;; Add hide-ifdef-hiding and hide-ifdef-mode to minor-mode-alist.
                     33: ;;; 
                     34: ;;; Revision 1.3  88/01/29  00:38:19  liberte
                     35: ;;; Fix three bugs.
                     36: ;;; 1. Function "defined" is just like lookup.
                     37: ;;; 2. Skip to newline or cr in case text is hidden.
                     38: ;;; 3. Use car of token list if just one symbol.
                     39: ;;;
                     40: ;;; Revision 1.2  88/01/28  23:32:46  liberte
                     41: ;;; Use hide-ifdef-mode-prefix-key.
                     42: ;;; Copy current-local-map so other buffers do not get
                     43: ;;; hide-ifdef-mode bindings.
                     44: ;;;
                     45: ;;;--------------------------------------------------------------
                     46: ;;; To initialize, toggle the hide-ifdef minor mode with
                     47: ;;;
                     48: ;;; M-x hide-ifdef-mode
                     49: ;;;
                     50: ;;; This will set up key bindings and call hide-ifdef-mode-hook if it
                     51: ;;; has a value.  To explicitly hide ifdefs using a buffer-local
                     52: ;;; define list (default empty), type
                     53: ;;;
                     54: ;;; M-x hide-ifdefs  or C-c h
                     55: ;;;
                     56: ;;; Hide-ifdef suppresses the display of code that the preprocessor wouldn't
                     57: ;;; pass through.  The support of constant expressions in #if lines is 
                     58: ;;; limited to identifiers, parens, and the operators: &&, ||, !, and
                     59: ;;; "defined".  Please extend this.
                     60: ;;;
                     61: ;;; The hidden code is marked by ellipses (...).  Be
                     62: ;;; cautious when editing near ellipses, since the hidden text is
                     63: ;;; still in the buffer, and you can move the point into it and modify
                     64: ;;; text unawares.  If you don't want to see the ellipses, set 
                     65: ;;; selective-display-ellipses to nil.  But this can be dangerous.
                     66: ;;; You can make your buffer read-only while hide-ifdef-hiding by setting
                     67: ;;; hide-ifdef-read-only to a non-nil value.  You can toggle this 
                     68: ;;; variable with hide-ifdef-toggle-read-only (C-c C-q).
                     69: ;;;
                     70: ;;; You can undo the effect of hide-ifdefs by typing
                     71: ;;;
                     72: ;;; M-x show-ifdefs  or C-c s
                     73: ;;;
                     74: ;;; Use M-x hide-ifdef-define (C-c d) to define a symbol.
                     75: ;;; Use M-x hide-ifdef-undef (C-c u) to undefine a symbol.
                     76: ;;;
                     77: ;;; If you define or undefine a symbol while hide-ifdef-mode is in effect,
                     78: ;;; the display will be updated.  Only the define list for the current
                     79: ;;; buffer will be affected.  You can save changes to the local define
                     80: ;;; list with hide-ifdef-set-define-alist.  This adds entries 
                     81: ;;; to hide-ifdef-define-alist.
                     82: ;;;
                     83: ;;; If you have defined a hide-ifdef-mode-hook, you can set
                     84: ;;; up a list of symbols that may be used by hide-ifdefs as in the
                     85: ;;; following example:
                     86: ;;;
                     87: ;;; (setq hide-ifdef-mode-hook
                     88: ;;;      '(lambda ()
                     89: ;;;     (if (not hide-ifdef-define-alist)
                     90: ;;;         (setq hide-ifdef-define-alist
                     91: ;;;              '((list1 ONE TWO)
                     92: ;;;                (list2 TWO THREE)
                     93: ;;;                )))
                     94: ;;;     (hide-ifdef-use-define-alist 'list2) ; use list2 by default
                     95: ;;;     ))
                     96: ;;;
                     97: ;;; You can call hide-ifdef-use-define-alist (C-c u) at any time to specify
                     98: ;;; another list to use.
                     99: ;;;
                    100: ;;; To cause ifdefs to be hidden as soon as hide-ifdef-mode is called,
                    101: ;;; set hide-ifdef-initially to non-nil.
                    102: ;;;
                    103: ;;; If you set hide-ifdef-lines to t, hide-ifdefs hides all the #ifdef lines.
                    104: ;;; In the absence of highlighting, that might be a bad idea.  If you set
                    105: ;;; hide-ifdef-lines to nil (the default), the surrounding preprocessor
                    106: ;;; lines will be displayed.  That can be confusing in its own
                    107: ;;; right.  Other variations on display are possible, but not much
                    108: ;;; better.
                    109: ;;;
                    110: ;;; You can explicitly hide or show individual ifdef blocks irrespective
                    111: ;;; of the define list by using hide-ifdef-block and show-ifdef-block.
                    112: ;;;
                    113: ;;; You can move the point between ifdefs with forward-ifdef, backward-ifdef,
                    114: ;;; up-ifdef, down-ifdef, next-ifdef, and previous-ifdef.
                    115: ;;;
                    116: ;;; If you have minor-mode-alist in your mode line (the default) two labels
                    117: ;;; may appear.  "Ifdef" will appear when hide-ifdef-mode is active.  "Hiding"
                    118: ;;; will appear when text may be hidden ("hide-ifdef-hiding" is non-nil).
                    119: 
                    120: 
                    121: 
                    122: (defvar hide-ifdef-mode-map nil
                    123:   "Keymap used with hide-ifdef mode")
                    124: 
                    125: (defconst hide-ifdef-mode-prefix-key "\C-c"
                    126:   "Prefix key for all hide-ifdef-mode commands.")
                    127: 
                    128: (defvar hide-ifdef-mode-map-before nil
                    129:   "Buffer-local variable to store a copy of the local keymap
                    130:        before hide-ifdef-mode modifies it.")
                    131: 
                    132: (defun define-hide-ifdef-mode-map ()
                    133:   (if hide-ifdef-mode-map
                    134:       ()                               ; dont redefine it.
                    135:     (setq hide-ifdef-mode-map (make-sparse-keymap))
                    136:     (define-key hide-ifdef-mode-map "d" 'hide-ifdef-define)
                    137:     (define-key hide-ifdef-mode-map "u" 'hide-ifdef-undef)
                    138:     (define-key hide-ifdef-mode-map "D" 'hide-ifdef-set-define-alist)
                    139:     (define-key hide-ifdef-mode-map "U" 'hide-ifdef-use-define-alist)
                    140:   
                    141:     (define-key hide-ifdef-mode-map "h" 'hide-ifdefs)
                    142:     (define-key hide-ifdef-mode-map "s" 'show-ifdefs)
                    143:     (define-key hide-ifdef-mode-map "\C-h" 'hide-ifdef-block)
                    144:     (define-key hide-ifdef-mode-map "\C-s" 'show-ifdef-block)
                    145:   
                    146:     (define-key hide-ifdef-mode-map "\C-f" 'forward-ifdef)
                    147:     (define-key hide-ifdef-mode-map "\C-b" 'backward-ifdef)
                    148:     (define-key hide-ifdef-mode-map "\C-d" 'down-ifdef)
                    149:     (define-key hide-ifdef-mode-map "\C-u" 'up-ifdef)
                    150:     (define-key hide-ifdef-mode-map "\C-n" 'next-ifdef)
                    151:     (define-key hide-ifdef-mode-map "\C-p" 'previous-ifdef)
                    152:     (define-key hide-ifdef-mode-map "\C-q" 'hide-ifdef-toggle-read-only)
                    153:     (define-key hide-ifdef-mode-map
                    154:       (where-is-internal 'toggle-read-only nil t)
                    155:       'hide-ifdef-toggle-outside-read-only)
                    156:     )
                    157:   (fset 'hide-ifdef-mode-map hide-ifdef-mode-map)  ; the function is the map
                    158:   )
                    159: 
                    160: (defun hif-update-mode-line ()
                    161:   "Update mode-line by setting buffer-modified to itself."
                    162:   (set-buffer-modified-p (buffer-modified-p)))
                    163: 
                    164: 
                    165: (defvar hide-ifdef-mode nil
                    166:   "non-nil when hide-ifdef-mode is activated.")
                    167: 
                    168: (defvar hide-ifdef-hiding nil
                    169:   "non-nil when text may be hidden.")
                    170: 
                    171: (or (assq 'hide-ifdef-hiding minor-mode-alist)
                    172:     (setq minor-mode-alist
                    173:           (cons '(hide-ifdef-hiding " Hiding")
                    174:                 minor-mode-alist)))
                    175: 
                    176: (or (assq 'hide-ifdef-mode minor-mode-alist)
                    177:     (setq minor-mode-alist
                    178:           (cons '(hide-ifdef-mode " Ifdef")
                    179:                 minor-mode-alist)))
                    180: 
                    181: 
                    182: (defun hide-ifdef-mode (arg)
                    183:   "Toggle hide-ifdef-mode.  Thus this is a minor mode, albeit a large one.
                    184: With arg, turn hide-ifdef-mode on iff arg is positive.
                    185: In hide-ifdef-mode, code within #ifdef constructs that the C preprocessor
                    186: would eliminate may be hidden from view.  Several variables affect
                    187: how the hiding is done:
                    188: 
                    189: hide-ifdef-env
                    190:        An association list of defined and undefined symbols for the
                    191:        current buffer.  Initially, the global value of hide-ifdef-env is used.
                    192: 
                    193: hide-ifdef-define-alist
                    194:        An association list of defined symbol lists.  
                    195:         Use hide-ifdef-set-define-alist to save the current hide-ifdef-env
                    196:         and hide-ifdef-use-define-alist to set the current hide-ifdef-env
                    197:         from one of the lists in hide-ifdef-define-alist.
                    198: 
                    199: hide-ifdef-lines
                    200:        Set to non-nil to not show #if, #ifdef, #ifndef, #else, and
                    201:        #endif lines when hiding.
                    202: 
                    203: hide-ifdef-initially
                    204:        Indicates whether hide-ifdefs should be called when hide-ifdef-mode
                    205:        is activated.
                    206: 
                    207: hide-ifdef-read-only
                    208:        Set to non-nil if you want to make buffers read only while hiding.
                    209:        After show-ifdefs, read-only status is restored to previous value.
                    210: 
                    211: \\{hide-ifdef-mode-map}"
                    212: 
                    213:   (interactive "P")
                    214:   (make-local-variable 'hide-ifdef-mode)
                    215:   (setq hide-ifdef-mode
                    216:        (if (null arg)
                    217:            (not hide-ifdef-mode)
                    218:          (> (prefix-numeric-value arg) 0)))
                    219:   
                    220:   (hif-update-mode-line)
                    221: 
                    222:   (if hide-ifdef-mode
                    223:       (progn
                    224:        ; fix c-mode syntax table so we can recognize whole symbols.
                    225:        (modify-syntax-entry ?_ "w")
                    226:        (modify-syntax-entry ?& ".")
                    227:        (modify-syntax-entry ?\| ".")
                    228: 
                    229:        ; inherit global values
                    230:        (make-local-variable 'hide-ifdef-env)
                    231:        (setq hide-ifdef-env (default-value 'hide-ifdef-env))
                    232: 
                    233:        (make-local-variable 'hide-ifdef-hiding)
                    234:        (setq hide-ifdef-hiding (default-value 'hide-ifdef-hiding))
                    235: 
                    236:        (make-local-variable 'hif-outside-read-only)
                    237:        (setq hif-outside-read-only buffer-read-only)
                    238: 
                    239:        (make-local-variable 'ide-ifdef-mode-map-before)
                    240:        (setq hide-ifdef-mode-map-before (current-local-map))
                    241:        (use-local-map (copy-keymap (current-local-map)))
                    242:        (local-unset-key hide-ifdef-mode-prefix-key)
                    243:        (local-set-key hide-ifdef-mode-prefix-key 'hide-ifdef-mode-map)
                    244:        (define-hide-ifdef-mode-map)
                    245: 
                    246:        (run-hooks 'hide-ifdef-mode-hook)
                    247: 
                    248:        (if hide-ifdef-initially
                    249:            (hide-ifdefs)
                    250:          (show-ifdefs))
                    251:        (message "Enter hide-ifdef-mode.")
                    252:        )
                    253:      ; else end hide-ifdef-mode
                    254:     (if hide-ifdef-hiding
                    255:        (show-ifdefs))
                    256:     (use-local-map hide-ifdef-mode-map-before)
                    257:     (message "Exit hide-ifdef-mode.")
                    258:     ))
                    259:   
                    260: 
                    261: ;; from outline.el with docstring fixed.
                    262: (defun hif-outline-flag-region (from to flag)
                    263:   "Hides or shows lines from FROM to TO, according to FLAG.  If FLAG
                    264: is \\n (newline character) then text is shown, while if FLAG is \\^M
                    265: \(control-M) the text is hidden."
                    266:   (let ((modp (buffer-modified-p)))
                    267:     (unwind-protect (progn
                    268:                      (subst-char-in-region from to
                    269:                              (if (= flag ?\n) ?\^M ?\n)
                    270:                              flag t) )
                    271:       (set-buffer-modified-p modp))
                    272:     ))
                    273: 
                    274: (defun hif-show-all ()
                    275:   "Show all of the text in the current buffer."
                    276:   (interactive)
                    277:   (hif-outline-flag-region (point-min) (point-max) ?\n))
                    278: 
                    279: (defun hide-ifdef-region (start end)
                    280:   "START is the start of a #if or #else form.  END is the ending part.
                    281: Everything including these lines is made invisible."
                    282:   (hif-outline-flag-region start end ?\^M)
                    283:   )
                    284: 
                    285: (defun hif-show-ifdef-region (start end)
                    286:   "Everything between START and END is made visible."
                    287:   (hif-outline-flag-region start end ?\n)
                    288:   )
                    289: 
                    290: 
                    291: 
                    292: ;===%%SF%% evaluation (Start)  ===
                    293: 
                    294: (defvar hide-ifdef-evaluator 'eval
                    295:   "The evaluator is given a canonical form and returns T if text under
                    296: that form should be displayed.")
                    297: 
                    298: (defvar hif-undefined-symbol nil
                    299:   "...is by default considered to be false.")
                    300: 
                    301: (defvar hide-ifdef-env nil
                    302:   "An alist of defined symbols and their values.")
                    303: 
                    304: 
                    305: (defun hif-set-var (var value)
                    306:   "Prepend (var value) pair to hide-ifdef-env."
                    307:   (setq hide-ifdef-env (cons (cons var value) hide-ifdef-env)))
                    308: 
                    309: 
                    310: (defun hif-lookup (var)
                    311: ;  (message "hif-lookup %s" var)
                    312:   (let ((val (assoc var hide-ifdef-env)))
                    313:     (if val
                    314:        (cdr val)
                    315:       hif-undefined-symbol)))
                    316: 
                    317: (defun hif-defined (var)
                    318:   (hif-lookup var)
                    319:   ; when #if expressions are fully supported, defined result should be 1
                    320:   ;  (if (assoc var  hide-ifdef-env)
                    321:   ;      1
                    322:   ;    nil)
                    323: )
                    324: 
                    325: 
                    326: ;===%%SF%% evaluation (End)  ===
                    327: 
                    328: 
                    329: 
                    330: ;===%%SF%% parsing (Start)  ===
                    331: ;;;  The code that understands what ifs and ifdef in files look like.
                    332: 
                    333: (defconst hif-cpp-prefix "\\(^\\|\r\\)[ \t]*#[ \t]*")
                    334: (defconst hif-ifndef-regexp (concat hif-cpp-prefix "ifndef"))
                    335: (defconst hif-ifx-regexp (concat hif-cpp-prefix "if\\(n?def\\)?[ \t]+"))
                    336: (defconst hif-else-regexp (concat hif-cpp-prefix "else"))
                    337: (defconst hif-endif-regexp (concat hif-cpp-prefix "endif"))
                    338: (defconst hif-ifx-else-endif-regexp
                    339:   (concat hif-ifx-regexp "\\|" hif-else-regexp "\\|" hif-endif-regexp))
                    340: 
                    341: 
                    342: (defun hif-infix-to-prefix (token-list)
                    343:   "Convert list of tokens in infix into prefix list"
                    344: ;  (message "hif-infix-to-prefix: %s" token-list)
                    345:   (if (= 1 (length token-list))
                    346:       (` (hif-lookup (quote (, (car token-list)))))
                    347:     (hif-parse-if-exp token-list))
                    348:   )
                    349: 
                    350: ; pattern to match initial identifier, !, &&, ||, (, or ).
                    351: (defconst hif-token-regexp "^\\(!\\|&&\\|||\\|[()]\\|\\w+\\)")
                    352: (defconst hif-end-of-comment "\\*/")
                    353: 
                    354: 
                    355: (defun hif-tokenize (expr-string)
                    356:   "Separate string into a list of tokens"
                    357:   (let ((token-list nil)
                    358:        (expr-start 0)
                    359:        (expr-length (length expr-string)))
                    360: 
                    361:     (while (< expr-start expr-length) 
                    362: ;      (message "expr-start = %d" expr-start) (sit-for 1)
                    363:       (cond
                    364:        ((string-match "^[ \t]+" expr-string expr-start)
                    365:           ; skip whitespace
                    366:         (setq expr-start (match-end 0))
                    367:         ; stick newline in string so ^ matches on the next string-match
                    368:         (aset expr-string (1- expr-start) ?\n)
                    369:         )
                    370: 
                    371:        ((string-match "^/\\*" expr-string expr-start)
                    372:         (setq expr-start (match-end 0))
                    373:         (aset expr-string (1- expr-start) ?\n)
                    374:         (or
                    375:           (string-match hif-end-of-comment
                    376:                         expr-string expr-start) ; eat comment
                    377:           (string-match "$" expr-string expr-start)) ; multi-line comment
                    378:         (setq expr-start (match-end 0))
                    379:         (aset expr-string (1- expr-start) ?\n)
                    380:         )
                    381: 
                    382:        ((string-match hif-token-regexp expr-string expr-start)
                    383:          (let ((token (substring expr-string expr-start (match-end 0))))
                    384:            (setq expr-start (match-end 0))
                    385:            (aset expr-string (1- expr-start) ?\n)
                    386: ;          (message "token: %s" token) (sit-for 1)
                    387:            (setq token-list
                    388:                  (cons
                    389:                    (cond
                    390:                      ((string-equal token "||") 'or)
                    391:                      ((string-equal token "&&") 'and)
                    392:                      ((string-equal token "!")  'not)
                    393:                      ((string-equal token "defined") 'hif-defined)
                    394:                      ((string-equal token "(") 'lparen)
                    395:                      ((string-equal token ")") 'rparen)
                    396:                      (t (intern token)))
                    397:                    token-list))
                    398:            ))
                    399:          (t (error "Bad #if expression: %s" expr-string))
                    400:          ))
                    401:     (nreverse token-list)
                    402:     ))
                    403: 
                    404: ;;;-----------------------------------------------------------------
                    405: ;;; Translate C preprocessor #if expressions using recursive descent.
                    406: ;;; This parser is limited to the operators &&, ||, !, and "defined".
                    407: 
                    408: (defun hif-parse-if-exp (token-list)
                    409:   "Parse the TOKEN-LIST.  Return translated list in prefix form."
                    410:   (hif-nexttoken)
                    411:   (prog1
                    412:       (hif-expr)
                    413:     (if token ; is there still a token?
                    414:        (error "Error: unexpected token: %s" token)))
                    415:   )
                    416: 
                    417: (defun hif-nexttoken ()
                    418:   "Pop the next token from token-list into the let variable \"token\"."
                    419:   (setq token (car token-list))
                    420:   (setq token-list (cdr token-list))
                    421:   token
                    422:   )
                    423: 
                    424: (defun hif-expr ()
                    425:   "Parse and expression of the form
                    426:        expr : term | expr '||' term."
                    427:   (let ((result (hif-term)))
                    428:     (while (eq  token 'or)
                    429:       (hif-nexttoken)
                    430:       (setq result (list 'or result (hif-term))))
                    431:   result
                    432:   ))
                    433: 
                    434: (defun hif-term ()
                    435:   "Parse a term of the form
                    436:        term : factor | term '&&' factor."
                    437:   (let ((result (hif-factor)))
                    438:     (while (eq token 'and)
                    439:       (hif-nexttoken)
                    440:       (setq result (list 'and result (hif-factor))))
                    441:     result
                    442:     ))
                    443: 
                    444: (defun hif-factor ()
                    445:   "Parse a factor of the form
                    446:        factor : '!' factor | '(' expr ')' | 'defined(' id ')' | id."
                    447:   (cond
                    448:     ((eq token 'not)
                    449:      (hif-nexttoken)
                    450:      (list 'not (hif-factor)))
                    451: 
                    452:     ((eq token 'lparen)
                    453:      (hif-nexttoken)
                    454:      (let ((result (hif-expr)))
                    455:        (if (not (eq token 'rparen))
                    456:           (error "Bad token in parenthesized expression: %s" token)
                    457:         (hif-nexttoken)
                    458:         result)))
                    459: 
                    460:     ((eq token 'hif-defined)
                    461:      (hif-nexttoken)
                    462:      (if (not (eq token 'lparen))
                    463:         (error "Error: expected \"(\" after \"define\""))
                    464:      (hif-nexttoken)
                    465:      (let ((ident token))
                    466:        (if (memq token '(or and not hif-defined lparen rparen))
                    467:           (error "Error: unexpected token: %s" token))
                    468:        (hif-nexttoken)
                    469:        (if (not (eq token 'rparen))
                    470:           (error "Error: expected \")\" after identifier"))
                    471:        (hif-nexttoken)
                    472:        (` (hif-defined (quote (, ident))))
                    473:        ))
                    474: 
                    475:     (t ; identifier
                    476:       (let ((ident token))
                    477:        (if (memq ident '(or and))
                    478:            (error "Error: missing identifier"))
                    479:        (hif-nexttoken)
                    480:        (` (hif-lookup (quote (, ident))))
                    481:        ))
                    482: 
                    483:     ))
                    484: 
                    485: ;;;----------- end of parser -----------------------
                    486: 
                    487: 
                    488: (defun hif-canonicalize ()
                    489:   "When at beginning of #ifX, returns a canonical (evaluatable)
                    490:        form for the expression."
                    491:   (save-excursion
                    492:     (let ((negate (looking-at hif-ifndef-regexp)))
                    493:       (re-search-forward hif-ifx-regexp)
                    494:       (let* ((expr-string
                    495:              (buffer-substring (point)
                    496:                                (progn (skip-chars-forward "^\n\r") (point))))
                    497:             (expr (hif-infix-to-prefix (hif-tokenize expr-string))))
                    498: ;      (message "hif-canonicalized: %s" expr)
                    499:        (if negate
                    500:            (list 'not expr)
                    501:          expr)))))
                    502: 
                    503: 
                    504: (defun hif-find-any-ifX ()
                    505:   "Position at beginning of next #if, #ifdef, or #ifndef, including one on
                    506: this line."
                    507: ;  (message "find ifX at %d" (point))
                    508:   (prog1
                    509:       (re-search-forward hif-ifx-regexp (point-max) t)
                    510:     (beginning-of-line)))
                    511: 
                    512: 
                    513: (defun hif-find-next-relevant ()
                    514:   "Position at beginning of next #ifdef, #ifndef, #else, #endif,
                    515: NOT including one on this line."
                    516: ;  (message "hif-find-next-relevant at %d" (point))
                    517:   (end-of-line)
                    518:   ; avoid infinite recursion by only going to beginning of line if match found
                    519:   (if (re-search-forward hif-ifx-else-endif-regexp (point-max) t)
                    520:       (beginning-of-line))
                    521:   )
                    522: 
                    523: (defun hif-find-previous-relevant ()
                    524:   "Position at beginning of previous #ifdef, #ifndef, #else, #endif,
                    525: NOT including one on this line."
                    526: ;  (message "hif-find-previous-relevant at %d" (point))
                    527:   (beginning-of-line)
                    528:   ; avoid infinite recursion by only going to beginning of line if match found
                    529:   (if (re-search-backward hif-ifx-else-endif-regexp (point-min) t)
                    530:      (beginning-of-line)
                    531:     )
                    532:   )
                    533: 
                    534: 
                    535: (defun hif-looking-at-ifX ()           ;; Should eventually see #if
                    536:   (looking-at hif-ifx-regexp))
                    537: (defun hif-looking-at-endif ()
                    538:   (looking-at hif-endif-regexp))
                    539: (defun hif-looking-at-else ()
                    540:   (looking-at hif-else-regexp))
                    541: 
                    542: 
                    543: 
                    544: (defun hif-ifdef-to-endif ()
                    545:   "If positioned at #ifX or #else form, skip to corresponding #endif."
                    546: ;  (message "hif-ifdef-to-endif at %d" (point)) (sit-for 1)
                    547:   (hif-find-next-relevant)
                    548:   (cond ((hif-looking-at-ifX)
                    549:         (hif-ifdef-to-endif) ; find endif of nested if
                    550:         (hif-ifdef-to-endif)) ; find outer endif or else
                    551:        ((hif-looking-at-else)
                    552:         (hif-ifdef-to-endif)) ; find endif following else
                    553:        ((hif-looking-at-endif)
                    554:         'done)
                    555:        (t
                    556:         (error "Missmatched #ifdef #endif pair"))
                    557:        ))
                    558: 
                    559: 
                    560: (defun hif-endif-to-ifdef ()
                    561:   "If positioned at #endif form, skip backward to corresponding #ifX."
                    562: ;  (message "hif-endif-to-ifdef at %d" (point))
                    563:   (let ((start (point)))
                    564:     (hif-find-previous-relevant)
                    565:     (if (= start (point))
                    566:        (error "Missmatched #ifdef #endif pair")))
                    567:   (cond ((hif-looking-at-endif)
                    568:         (hif-endif-to-ifdef) ; find beginning of nested if
                    569:         (hif-endif-to-ifdef)) ; find beginning of outer if or else
                    570:        ((hif-looking-at-else)
                    571:         (hif-endif-to-ifdef))
                    572:        ((hif-looking-at-ifX)
                    573:         'done)
                    574:        (t ; never gets here
                    575:         )))
                    576: 
                    577: 
                    578: (defun forward-ifdef (&optional arg)
                    579:   "Move point to beginning of line of the next ifdef-endif.
                    580:        With argument, do this that many times."
                    581:   (interactive "p")
                    582:   (or arg (setq arg 1))
                    583:   (if (< arg 0)
                    584:       (backward-ifdef (- arg)))
                    585:   (while (< 0 arg)
                    586:     (setq arg (- arg))
                    587:     (let ((start (point)))
                    588:       (if (not (hif-looking-at-ifX))
                    589:          (hif-find-next-relevant))
                    590:       (if (hif-looking-at-ifX)
                    591:          (hif-ifdef-to-endif)
                    592:        (goto-char start)
                    593:        (error "No following #ifdef")
                    594:        ))))
                    595: 
                    596: 
                    597: (defun backward-ifdef (&optional arg)
                    598:   "Move point to beginning of the previous ifdef-endif.
                    599:        With argument, do this that many times."
                    600:   (interactive "p")
                    601:   (or arg (setq arg 1))
                    602:   (if (< arg 0)
                    603:       (forward-ifdef (- arg)))
                    604:   (while (< 0 arg)
                    605:     (setq arg (1- arg))
                    606:     (beginning-of-line)
                    607:     (let ((start (point)))
                    608:       (if (not (hif-looking-at-endif))
                    609:          (hif-find-previous-relevant))
                    610:       (if (hif-looking-at-endif)
                    611:          (hif-endif-to-ifdef)
                    612:        (goto-char start)
                    613:        (error "No previous #ifdef")
                    614:        ))))
                    615: 
                    616: 
                    617: 
                    618: (defun down-ifdef ()
                    619:   "Move point to beginning of nested ifdef or else-part."
                    620:     (interactive)
                    621:     (let ((start (point)))
                    622:       (hif-find-next-relevant)
                    623:       (if (or (hif-looking-at-ifX) (hif-looking-at-else))
                    624:          ()
                    625:        (goto-char start)
                    626:        (error "No following #ifdef")
                    627:        )))
                    628: 
                    629: 
                    630: (defun up-ifdef ()
                    631:   "Move point to beginning of enclosing ifdef or else-part."
                    632:   (interactive)
                    633:   (beginning-of-line)
                    634:   (let ((start (point)))
                    635:     (if (not (hif-looking-at-endif))
                    636:        (hif-find-previous-relevant))
                    637:     (if (hif-looking-at-endif)
                    638:        (hif-endif-to-ifdef))
                    639:       (if (= start (point))
                    640:          (error "No previous #ifdef")
                    641:        )))
                    642: 
                    643: (defun next-ifdef (&optional arg)
                    644:   "Move to the beginning of the next #ifX, #else, or #endif.
                    645:        With argument, do this that many times."
                    646:   (interactive "p")
                    647:   (or arg (setq arg 1))
                    648:   (if (< arg 0)
                    649:       (previous-ifdef (- arg)))
                    650:   (while (< 0 arg)
                    651:     (setq arg (1- arg))
                    652:     (hif-find-next-relevant)
                    653:     (if (eolp)
                    654:        (progn
                    655:          (beginning-of-line)
                    656:          (error "No following #ifdefs, #elses, or #endifs")
                    657:          ))))
                    658: 
                    659: (defun previous-ifdef (&optional arg)
                    660:   "Move to the beginning of the previous #ifX, #else, or #endif.
                    661:        With argument, do this that many times."
                    662:   (interactive "p")
                    663:   (or arg (setq arg 1))
                    664:   (if (< arg 0)
                    665:       (next-ifdef (- arg)))
                    666:   (while (< 0 arg)
                    667:     (setq arg (1- arg))
                    668:     (let ((start (point)))
                    669:       (hif-find-previous-relevant)
                    670:       (if (= start (point))
                    671:          (error "No previous #ifdefs, #elses, or #endifs")
                    672:        ))))
                    673: 
                    674: 
                    675: ;===%%SF%% parsing (End)  ===
                    676: 
                    677: 
                    678: ;===%%SF%% hide-ifdef-hiding (Start)  ===
                    679: 
                    680: 
                    681: ;;; A range is a structure with four components:
                    682: ;;; ELSE-P     True if there was an else clause for the ifdef.
                    683: ;;; START      The start of the range. (beginning of line)
                    684: ;;; ELSE       The else marker (beginning of line)
                    685: ;;;                    Only valid if ELSE-P is true.
                    686: ;;; END                The end of the range.  (beginning of line)
                    687: 
                    688: (defun hif-make-range (else-p start end &optional else)
                    689:   (list else-p start else end))
                    690: 
                    691: (defun hif-range-else-p (range)  (elt range 0))
                    692: (defun hif-range-start (range) (elt range 1))
                    693: (defun hif-range-else (range) (elt range 2))
                    694: (defun hif-range-end (range) (elt range 3))
                    695: 
                    696: 
                    697: 
                    698: ;;; Find-Range
                    699: ;;; The workhorse, it delimits the #if region.  Reasonably simple:
                    700: ;;; Skip until an #else or #endif is found, remembering positions.  If
                    701: ;;; an #else was found, skip some more, looking for the true #endif.
                    702: 
                    703: (defun hif-find-range ()
                    704:   "Returns a Range structure describing the current #if region.
                    705: Point is left unchanged."
                    706: ;  (message "hif-find-range at %d" (point))
                    707:   (save-excursion
                    708:     (beginning-of-line)
                    709:     (let ((start (point))
                    710:          (else-p nil)
                    711:          (else nil)
                    712:          (end nil))
                    713:       ;; Part one.  Look for either #endif or #else.
                    714:       ;; This loop-and-a-half dedicated to E. Dijkstra.
                    715:       (hif-find-next-relevant)
                    716:       (while (hif-looking-at-ifX)              ; Skip nested ifdef
                    717:        (hif-ifdef-to-endif)
                    718:        (hif-find-next-relevant))
                    719:       ;; Found either a #else or an #endif.
                    720:       (cond ((hif-looking-at-else)
                    721:             (setq else-p t)
                    722:             (setq else (point)))
                    723:            (t
                    724:             (setq end (point)) ; (save-excursion (end-of-line) (point))
                    725:             ))
                    726:       ;; If found #else, look for #endif.
                    727:       (if else-p
                    728:          (progn
                    729:            (hif-find-next-relevant)
                    730:            (while (hif-looking-at-ifX) ; Skip nested ifdef
                    731:              (hif-ifdef-to-endif)
                    732:              (hif-find-next-relevant))
                    733:            (if (hif-looking-at-else)
                    734:                (error "Found two elses in a row?  Broken!"))
                    735:            (setq end (point))  ; (save-excursion (end-of-line) (point))
                    736:            ))
                    737:       (hif-make-range else-p start end else))))
                    738: 
                    739:          
                    740: ;;; A bit slimy.
                    741: ;;; NOTE:  If there's an #ifdef at the beginning of the file, we can't
                    742: ;;; hide it.  There's no previous newline to replace.  If we added
                    743: ;;; one, we'd throw off all the counts.  Feh.
                    744: 
                    745: (defun hif-hide-line (point)
                    746:   "Hide the line containing point.  Does nothing if
                    747: hide-ifdef-lines is nil."
                    748:   (if hide-ifdef-lines
                    749:       (save-excursion
                    750:        (goto-char point)
                    751:        (let ((modp (buffer-modified-p)))
                    752:          (unwind-protect
                    753:              (progn
                    754:                (beginning-of-line)
                    755:                (if (not (= (point) 1))
                    756:                    (hide-ifdef-region (1- (point)) (point))))
                    757:            (set-buffer-modified-p modp))
                    758:          ))
                    759:     ))
                    760:                  
                    761: 
                    762: ;;;  Hif-Possibly-Hide
                    763: ;;;  There are four cases.  The #ifX expression is "taken" if it
                    764: ;;;  the hide-ifdef-evaluator returns T.  Presumably, this means the code
                    765: ;;;  inside the #ifdef would be included when the program was
                    766: ;;;  compiled.  
                    767: ;;;
                    768: ;;;  Case 1:  #ifX taken, and there's an #else.
                    769: ;;;    The #else part must be hidden.  The #if (then) part must be
                    770: ;;;    processed for nested #ifX's.
                    771: ;;;  Case 2:  #ifX taken, and there's no #else.
                    772: ;;;    The #if part must be processed for nested #ifX's.
                    773: ;;;  Case 3:  #ifX not taken, and there's an #else.
                    774: ;;;    The #if part must be hidden.  The #else part must be processed
                    775: ;;;    for nested #ifs.
                    776: ;;;  Case 4:  #ifX not taken, and there's no #else.
                    777: ;;;    The #ifX part must be hidden.
                    778: ;;;
                    779: ;;;  Further processing is done by narrowing to the relevant region
                    780: ;;;  and just recursively calling hide-ifdef-guts.
                    781: ;;;
                    782: ;;;  When hif-possibly-hide returns, point is at the end of the
                    783: ;;;  possibly-hidden range.
                    784: 
                    785: (defun hif-recurse-on (start end)
                    786:   "Call hide-ifdef-guts after narrowing to end of START line and END
                    787: line."
                    788:   (save-excursion
                    789:     (save-restriction
                    790:       (goto-char start)
                    791:       (end-of-line)
                    792:       (narrow-to-region (point) end)
                    793:       (hide-ifdef-guts))))
                    794: 
                    795: (defun hif-possibly-hide ()
                    796:   "Called at #ifX expression, this hides those parts that should be
                    797: hidden, according to judgement of hide-ifdef-evaluator."
                    798: ;  (message "hif-possibly-hide") (sit-for 1)
                    799:     (let ((test (hif-canonicalize))
                    800:          (range (hif-find-range)))
                    801: ;      (message "test = %s" test) (sit-for 1)
                    802:       
                    803:       (hif-hide-line (hif-range-end range))
                    804:       (if (funcall hide-ifdef-evaluator test)
                    805:          (cond ((hif-range-else-p range) ; case 1
                    806:                 (hif-hide-line (hif-range-else range))
                    807:                 (hide-ifdef-region (hif-range-else range) 
                    808:                                    (1- (hif-range-end range)))
                    809:                 (hif-recurse-on (hif-range-start range)
                    810:                                 (hif-range-else range)))
                    811:                (t ; case 2
                    812:                 (hif-recurse-on (hif-range-start range)
                    813:                                 (hif-range-end range))))
                    814:        (cond ((hif-range-else-p range) ; case 3
                    815:               (hif-hide-line (hif-range-else range))
                    816:               (hide-ifdef-region (hif-range-start range)
                    817:                                  (1- (hif-range-else range)))
                    818:               (hif-recurse-on (hif-range-else range)
                    819:                               (hif-range-end range)))
                    820:              (t ; case 4
                    821:               (hide-ifdef-region (point)
                    822:                                  (1- (hif-range-end range))))
                    823:              ))
                    824:       (hif-hide-line (hif-range-start range))  ; Always hide start.
                    825:       (goto-char (hif-range-end range))
                    826:       (end-of-line)
                    827:       ))
                    828: 
                    829: 
                    830: 
                    831: (defun hide-ifdef-guts ()
                    832:   "Does the work of hide-ifdefs, except for the work that's pointless
                    833: to redo on a recursive entry."
                    834: ;  (message "hide-ifdef-guts")
                    835:   (save-excursion
                    836:     (goto-char (point-min))
                    837:     (while (hif-find-any-ifX)
                    838:       (hif-possibly-hide))))
                    839: 
                    840: ;===%%SF%% hide-ifdef-hiding (End)  ===
                    841: 
                    842: 
                    843: ;===%%SF%% exports (Start)  ===
                    844: 
                    845: (defvar hide-ifdef-initially nil
                    846:   "*Non-nil if hide-ifdefs should be called when hide-ifdef-mode
                    847:        is first activated.")
                    848: 
                    849: (defvar hide-ifdef-hiding nil
                    850:   "Non-nil if text might be hidden.")
                    851: 
                    852: (defvar hide-ifdef-read-only nil
                    853:   "*Set to non-nil if you want buffer to be read-only while hiding text.")
                    854: 
                    855: (defvar hif-outside-read-only nil
                    856:   "Internal variable.  Saves the value of buffer-read-only while hiding.")
                    857: 
                    858: (defvar hide-ifdef-lines nil
                    859:   "*Set to t if you don't want to see the #ifX, #else, and #endif lines.")
                    860: 
                    861: (defun hide-ifdef-toggle-read-only ()
                    862:   "Toggle hide-ifdef-read-only."
                    863:   (interactive)
                    864:   (setq hide-ifdef-read-only (not hide-ifdef-read-only))
                    865:   (message "Hide-Read-Only %s"
                    866:           (if hide-ifdef-read-only "ON" "OFF"))
                    867:   (if hide-ifdef-hiding
                    868:       (setq buffer-read-only (or hide-ifdef-read-only hif-outside-read-only)))
                    869:   (hif-update-mode-line)
                    870:   )
                    871: 
                    872: (defun hide-ifdef-toggle-outside-read-only ()
                    873:   "Replacement for toggle-read-only within hide-ifdef-mode."
                    874:   (interactive)
                    875:   (setq hif-outside-read-only (not hif-outside-read-only))
                    876:   (message "Read only %s"
                    877:           (if hif-outside-read-only "ON" "OFF"))
                    878:   (setq buffer-read-only
                    879:        (or (and hide-ifdef-hiding hide-ifdef-read-only)
                    880:            hif-outside-read-only)
                    881:        )
                    882:   (hif-update-mode-line)
                    883:   )
                    884: 
                    885:       
                    886: (defun hide-ifdef-define (var)
                    887:   "Define a VAR so that #ifdef VAR would be included."
                    888:   (interactive "SDefine what? ")
                    889:   (hif-set-var var t)
                    890:   (if hide-ifdef-hiding (hide-ifdefs)))
                    891: 
                    892: (defun hide-ifdef-undef (var)
                    893:   "Undefine a VAR so that #ifdef VAR would not be included."
                    894:   (interactive "SUndefine what? ")
                    895:   (hif-set-var var nil)
                    896:   (if hide-ifdef-hiding (hide-ifdefs)))
                    897: 
                    898: 
                    899: (defun hide-ifdefs ()
                    900:   "Hide the contents of some #ifdefs.  Assume that defined symbols have
                    901: been added to hide-ifdef-env.  The text hidden is the text that would not
                    902: be included by the C preprocessor if it were given the file with those
                    903: symbols defined.
                    904: 
                    905: Turn off hiding by calling show-ifdef."
                    906: 
                    907:   (interactive)
                    908:   (message "Hiding...")
                    909:   (if (not hide-ifdef-mode)
                    910:       (hide-ifdef-mode 1)) ; turn on hide-ifdef-mode
                    911:   (if hide-ifdef-hiding
                    912:       (show-ifdefs))                   ; Otherwise, deep confusion.
                    913:   (if buffer-read-only (toggle-read-only)) ; make it writable temporarily
                    914:   (setq selective-display t)
                    915:   (setq hide-ifdef-hiding t)
                    916:   (hide-ifdef-guts)
                    917:   (if (or hide-ifdef-read-only hif-outside-read-only)
                    918:       (toggle-read-only) ; make it read only
                    919:     )
                    920:   (message "Hiding done")
                    921:   )
                    922: 
                    923: 
                    924: (defun show-ifdefs ()
                    925:   "Cancel the effects of hide-ifdef.  The contents of all #ifdefs is shown."
                    926:   (interactive)
                    927:   (if buffer-read-only (toggle-read-only)) ; make it writable temporarily
                    928:   (setq selective-display nil) ; defaults
                    929:   (hif-show-all)
                    930:   (if hif-outside-read-only
                    931:       (toggle-read-only)) ; make it read only
                    932:   (setq hide-ifdef-hiding nil)
                    933:   )
                    934: 
                    935: 
                    936: (defun hif-find-ifdef-block ()
                    937:   "Utilitiy for hide and show ifdef-block.  Set top and bottom of ifdef block."
                    938:   (let (max-bottom)
                    939:   (save-excursion
                    940:     (beginning-of-line)
                    941:     (if (not (or (hif-looking-at-else) (hif-looking-at-ifX)))
                    942:        (up-ifdef))
                    943:     (setq top (point))
                    944:     (hif-ifdef-to-endif)
                    945:     (setq max-bottom (1- (point)))
                    946:     )
                    947:   (save-excursion
                    948:     (beginning-of-line)
                    949:     (if (not (hif-looking-at-endif))
                    950:        (hif-find-next-relevant))
                    951:     (while (hif-looking-at-ifX)
                    952:       (hif-ifdef-to-endif)
                    953:       (hif-find-next-relevant)
                    954:       )
                    955:     (setq bottom (min max-bottom (1- (point))))
                    956:     ))
                    957:   )
                    958: 
                    959: 
                    960: (defun hide-ifdef-block ()
                    961:   "Hide the ifdef block (true or false part) enclosing or before the cursor."
                    962:   (interactive)
                    963:   (if (not hide-ifdef-mode)
                    964:       (hide-ifdef-mode 1))
                    965:   (if buffer-read-only (toggle-read-only))
                    966:   (setq selective-display t)
                    967:   (let (top bottom)
                    968:     (hif-find-ifdef-block) ; set top and bottom - dynamic scoping
                    969:     (hide-ifdef-region top bottom)
                    970:     (if hide-ifdef-lines
                    971:        (progn
                    972:          (hif-hide-line top)
                    973:          (hif-hide-line (1+ bottom))))
                    974:     (setq hide-ifdef-hiding t)
                    975:     )
                    976:   (if (or hide-ifdef-read-only hif-outside-read-only)
                    977:       (toggle-read-only))
                    978:   )
                    979: 
                    980: 
                    981: (defun show-ifdef-block ()
                    982:   "Show the ifdef block (true or false part) enclosing or before the cursor."
                    983:   (interactive)
                    984:   (let ((old-read-only buffer-read-only))
                    985:     (if old-read-only (toggle-read-only))
                    986:     (if hide-ifdef-lines
                    987:        (save-excursion
                    988:          (beginning-of-line)
                    989:          (hif-show-ifdef-region (1- (point)) (progn (end-of-line) (point))))
                    990: 
                    991:       (let (top bottom)
                    992:        (hif-find-ifdef-block)
                    993:        (hif-show-ifdef-region (1- top) bottom))
                    994:       )
                    995: 
                    996:     ; restore read only status since we dont know if all is shown.
                    997:     (if old-read-only (toggle-read-only))
                    998:     ))
                    999: 
                   1000: 
                   1001: 
                   1002: ;;;  defininition alist support
                   1003: 
                   1004: (defvar hide-ifdef-define-alist nil
                   1005:   "A global assoc list of pre-defined symbol lists")
                   1006: 
                   1007: (defun hif-compress-define-list (env)
                   1008:   "Compress the define list ENV into a list of defined symbols only."
                   1009:   (let ((defs (mapcar '(lambda (arg)
                   1010:                         (if (hif-lookup (car arg)) (car arg)))
                   1011:                      env))
                   1012:        (new-defs nil))
                   1013:     (while defs
                   1014:       (if (car defs)
                   1015:          (setq new-defs (cons (car defs) new-defs)))
                   1016:       (setq defs (cdr defs)))
                   1017:     new-defs
                   1018:     ))
                   1019: 
                   1020: (defun hide-ifdef-set-define-alist (name)
                   1021:   "Set the association for NAME to hide-ifdef-env."
                   1022:   (interactive "SSet define list: ")
                   1023:   (setq hide-ifdef-define-alist
                   1024:        (cons (cons name (hif-compress-define-list hide-ifdef-env))
                   1025:              hide-ifdef-define-alist))
                   1026:   )
                   1027: 
                   1028: (defun hide-ifdef-use-define-alist (name)
                   1029:   "Set hide-ifdef-env to the define list specified by NAME."
                   1030:   (interactive "SUse define list: ")
                   1031:   (let ((define-list (assoc name hide-ifdef-define-alist)))
                   1032:     (if define-list
                   1033:        (setq hide-ifdef-env
                   1034:              (mapcar '(lambda (arg) (cons arg t))
                   1035:                      (cdr define-list)))
                   1036:       (error "No define list for %s" name))
                   1037:     (if hide-ifdef-hiding (hide-ifdefs))
                   1038:     )
                   1039:   )
                   1040: 
                   1041: ;===%%SF%% exports (End)  ===

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.