|
|
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) ===
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.