diff options
| -rw-r--r-- | lisp/progmodes/hideif.el | 192 |
1 files changed, 88 insertions, 104 deletions
diff --git a/lisp/progmodes/hideif.el b/lisp/progmodes/hideif.el index 2e21af69340..dbcfd593ff4 100644 --- a/lisp/progmodes/hideif.el +++ b/lisp/progmodes/hideif.el | |||
| @@ -206,6 +206,8 @@ how the hiding is done: | |||
| 206 | (set (make-local-variable 'hide-ifdef-hiding) | 206 | (set (make-local-variable 'hide-ifdef-hiding) |
| 207 | (default-value 'hide-ifdef-hiding)) | 207 | (default-value 'hide-ifdef-hiding)) |
| 208 | (set (make-local-variable 'hif-outside-read-only) buffer-read-only) | 208 | (set (make-local-variable 'hif-outside-read-only) buffer-read-only) |
| 209 | (set (make-local-variable 'line-move-ignore-invisible) t) | ||
| 210 | (add-hook 'change-major-mode-hook (lambda () (hide-ifdef-mode -1))) | ||
| 209 | 211 | ||
| 210 | (add-to-invisibility-spec '(hide-ifdef . t)) | 212 | (add-to-invisibility-spec '(hide-ifdef . t)) |
| 211 | 213 | ||
| @@ -213,6 +215,7 @@ how the hiding is done: | |||
| 213 | (hide-ifdefs) | 215 | (hide-ifdefs) |
| 214 | (show-ifdefs))) | 216 | (show-ifdefs))) |
| 215 | ;; else end hide-ifdef-mode | 217 | ;; else end hide-ifdef-mode |
| 218 | (kill-local-variable 'line-move-ignore-invisible) | ||
| 216 | (if hide-ifdef-hiding | 219 | (if hide-ifdef-hiding |
| 217 | (show-ifdefs)))) | 220 | (show-ifdefs)))) |
| 218 | 221 | ||
| @@ -230,15 +233,23 @@ how the hiding is done: | |||
| 230 | (hide-ifdefs t))) | 233 | (hide-ifdefs t))) |
| 231 | (add-hook 'after-revert-hook 'hif-after-revert-function) | 234 | (add-hook 'after-revert-hook 'hif-after-revert-function) |
| 232 | 235 | ||
| 236 | (defun hif-end-of-line () | ||
| 237 | (end-of-line) | ||
| 238 | (while (= (logand 1 (skip-chars-backward "\\\\")) 1) | ||
| 239 | (end-of-line 2))) | ||
| 240 | |||
| 241 | (defun hide-ifdef-region-internal (start end) | ||
| 242 | (remove-overlays start end 'invisible 'hide-ifdef) | ||
| 243 | (let ((o (make-overlay start end))) | ||
| 244 | (overlay-put o 'invisible 'hide-ifdef))) | ||
| 245 | |||
| 233 | (defun hide-ifdef-region (start end) | 246 | (defun hide-ifdef-region (start end) |
| 234 | "START is the start of a #if or #else form. END is the ending part. | 247 | "START is the start of a #if or #else form. END is the ending part. |
| 235 | Everything including these lines is made invisible." | 248 | Everything including these lines is made invisible." |
| 236 | (save-excursion | 249 | (save-excursion |
| 237 | (goto-char start) (end-of-line) (setq start (point)) | 250 | (goto-char start) (hif-end-of-line) (setq start (point)) |
| 238 | (goto-char end) (end-of-line) (setq end (point)) | 251 | (goto-char end) (hif-end-of-line) (setq end (point)) |
| 239 | (remove-overlays start end 'invisible 'hide-ifdef) | 252 | (hide-ifdef-region-internal start end))) |
| 240 | (let ((o (make-overlay start end))) | ||
| 241 | (overlay-put o 'invisible 'hide-ifdef)))) | ||
| 242 | 253 | ||
| 243 | (defun hif-show-ifdef-region (start end) | 254 | (defun hif-show-ifdef-region (start end) |
| 244 | "Everything between START and END is made visible." | 255 | "Everything between START and END is made visible." |
| @@ -271,13 +282,7 @@ that form should be displayed.") | |||
| 271 | hif-undefined-symbol))) | 282 | hif-undefined-symbol))) |
| 272 | 283 | ||
| 273 | (defun hif-defined (var) | 284 | (defun hif-defined (var) |
| 274 | (hif-lookup var) | 285 | (if (assoc var hide-ifdef-env) 1 0)) |
| 275 | ;; when #if expressions are fully supported, defined result should be 1 | ||
| 276 | ;; (if (assoc var hide-ifdef-env) | ||
| 277 | ;; 1 | ||
| 278 | ;; nil) | ||
| 279 | ) | ||
| 280 | |||
| 281 | 286 | ||
| 282 | ;;===%%SF%% evaluation (End) === | 287 | ;;===%%SF%% evaluation (End) === |
| 283 | 288 | ||
| @@ -299,71 +304,47 @@ that form should be displayed.") | |||
| 299 | (defvar hif-token) | 304 | (defvar hif-token) |
| 300 | (defvar hif-token-list) | 305 | (defvar hif-token-list) |
| 301 | 306 | ||
| 302 | (defun hif-infix-to-prefix (token-list) | ||
| 303 | "Convert list of tokens in infix into prefix list." | ||
| 304 | ;; (message "hif-infix-to-prefix: %s" token-list) | ||
| 305 | (if (= 1 (length token-list)) | ||
| 306 | `(hif-lookup (quote ,(car token-list))) | ||
| 307 | (hif-parse-if-exp token-list))) | ||
| 308 | |||
| 309 | ;; pattern to match initial identifier, !, &&, ||, (, or ). | 307 | ;; pattern to match initial identifier, !, &&, ||, (, or ). |
| 310 | ;; Added ==, + and -: garyo@avs.com 8/9/94 | 308 | ;; Added ==, + and -: garyo@avs.com 8/9/94 |
| 311 | (defconst hif-token-regexp "^\\(&&\\|||\\|[!=]=\\|!\\|[()+-]\\|[<>]=?\\|\\w+\\)") | 309 | (defconst hif-token-regexp |
| 312 | (defconst hif-end-of-comment "\\*/") | 310 | "\\(&&\\|||\\|[!=]=\\|!\\|[()+-]\\|[<>]=?\\|\\w+\\)") |
| 313 | |||
| 314 | 311 | ||
| 315 | (defun hif-tokenize (expr-string) | 312 | (defun hif-tokenize (start end) |
| 316 | "Separate string into a list of tokens." | 313 | "Separate string between START and END into a list of tokens." |
| 317 | (let ((token-list nil) | 314 | (let ((token-list nil)) |
| 318 | (expr-start 0) | ||
| 319 | (expr-length (length expr-string))) | ||
| 320 | (with-syntax-table hide-ifdef-syntax-table | 315 | (with-syntax-table hide-ifdef-syntax-table |
| 321 | (while (< expr-start expr-length) | 316 | (save-excursion |
| 322 | ;; (message "expr-start = %d" expr-start) (sit-for 1) | 317 | (goto-char start) |
| 323 | (cond | 318 | (while (progn (forward-comment (point-max)) (< (point) end)) |
| 324 | ((string-match "^[ \t]+" expr-string expr-start) | 319 | ;; (message "expr-start = %d" expr-start) (sit-for 1) |
| 325 | ;; skip whitespace | 320 | (cond |
| 326 | (setq expr-start (match-end 0)) | 321 | ((looking-at "\\\\\n") |
| 327 | ;; stick newline in string so ^ matches on the next string-match | 322 | (forward-char 2)) |
| 328 | (aset expr-string (1- expr-start) ?\n)) | 323 | |
| 329 | 324 | ((looking-at hif-token-regexp) | |
| 330 | ((string-match "^/\\*" expr-string expr-start) | 325 | (let ((token (buffer-substring (point) (match-end 0)))) |
| 331 | (setq expr-start (match-end 0)) | 326 | (goto-char (match-end 0)) |
| 332 | (aset expr-string (1- expr-start) ?\n) | 327 | ;; (message "token: %s" token) (sit-for 1) |
| 333 | (or | 328 | (push (cond |
| 334 | (string-match hif-end-of-comment | 329 | ((string-equal token "||") 'or) |
| 335 | expr-string expr-start) ; eat comment | 330 | ((string-equal token "&&") 'and) |
| 336 | (string-match "$" expr-string expr-start)) ; multi-line comment | 331 | ((string-equal token "==") 'equal) |
| 337 | (setq expr-start (match-end 0)) | 332 | ((string-equal token "!=") 'hif-notequal) |
| 338 | (aset expr-string (1- expr-start) ?\n)) | 333 | ((string-equal token "!") 'not) |
| 339 | 334 | ((string-equal token "defined") 'hif-defined) | |
| 340 | ((string-match "^//" expr-string expr-start) | 335 | ((string-equal token "(") 'lparen) |
| 341 | (string-match "$" expr-string expr-start) | 336 | ((string-equal token ")") 'rparen) |
| 342 | (setq expr-start (match-end 0))) | 337 | ((string-equal token ">") 'hif-greater) |
| 343 | 338 | ((string-equal token "<") 'hif-less) | |
| 344 | ((string-match hif-token-regexp expr-string expr-start) | 339 | ((string-equal token ">=") 'hif-greater-equal) |
| 345 | (let ((token (substring expr-string expr-start (match-end 0)))) | 340 | ((string-equal token "<=") 'hif-less-equal) |
| 346 | (setq expr-start (match-end 0)) | 341 | ((string-equal token "+") 'hif-plus) |
| 347 | (aset expr-string (1- expr-start) ?\n) | 342 | ((string-equal token "-") 'hif-minus) |
| 348 | ;; (message "token: %s" token) (sit-for 1) | 343 | ((string-match "\\`[0-9]*\\'" token) |
| 349 | (push (cond | 344 | (string-to-number token)) |
| 350 | ((string-equal token "||") 'or) | 345 | (t (intern token))) |
| 351 | ((string-equal token "&&") 'and) | 346 | token-list))) |
| 352 | ((string-equal token "==") 'equal) | 347 | (t (error "Bad #if expression: %s" (buffer-string))))))) |
| 353 | ((string-equal token "!=") 'hif-notequal) | ||
| 354 | ((string-equal token "!") 'not) | ||
| 355 | ((string-equal token "defined") 'hif-defined) | ||
| 356 | ((string-equal token "(") 'lparen) | ||
| 357 | ((string-equal token ")") 'rparen) | ||
| 358 | ((string-equal token ">") 'hif-greater) | ||
| 359 | ((string-equal token "<") 'hif-less) | ||
| 360 | ((string-equal token ">=") 'hif-greater-equal) | ||
| 361 | ((string-equal token "<=") 'hif-less-equal) | ||
| 362 | ((string-equal token "+") 'hif-plus) | ||
| 363 | ((string-equal token "-") 'hif-minus) | ||
| 364 | (t (intern token))) | ||
| 365 | token-list))) | ||
| 366 | (t (error "Bad #if expression: %s" expr-string))))) | ||
| 367 | (nreverse token-list))) | 348 | (nreverse token-list))) |
| 368 | 349 | ||
| 369 | ;;;----------------------------------------------------------------- | 350 | ;;;----------------------------------------------------------------- |
| @@ -379,11 +360,9 @@ that form should be displayed.") | |||
| 379 | (if hif-token ; is there still a token? | 360 | (if hif-token ; is there still a token? |
| 380 | (error "Error: unexpected token: %s" hif-token)))) | 361 | (error "Error: unexpected token: %s" hif-token)))) |
| 381 | 362 | ||
| 382 | (defun hif-nexttoken () | 363 | (defsubst hif-nexttoken () |
| 383 | "Pop the next token from token-list into the let variable \"hif-token\"." | 364 | "Pop the next token from token-list into the let variable \"hif-token\"." |
| 384 | (setq hif-token (car hif-token-list)) | 365 | (setq hif-token (pop hif-token-list))) |
| 385 | (setq hif-token-list (cdr hif-token-list)) | ||
| 386 | hif-token) | ||
| 387 | 366 | ||
| 388 | (defun hif-expr () | 367 | (defun hif-expr () |
| 389 | "Parse an expression as found in #if. | 368 | "Parse an expression as found in #if. |
| @@ -391,7 +370,7 @@ that form should be displayed.") | |||
| 391 | (let ((result (hif-term))) | 370 | (let ((result (hif-term))) |
| 392 | (while (eq hif-token 'or) | 371 | (while (eq hif-token 'or) |
| 393 | (hif-nexttoken) | 372 | (hif-nexttoken) |
| 394 | (setq result (list 'or result (hif-term)))) | 373 | (setq result (list 'hif-or result (hif-term)))) |
| 395 | result)) | 374 | result)) |
| 396 | 375 | ||
| 397 | (defun hif-term () | 376 | (defun hif-term () |
| @@ -399,7 +378,7 @@ that form should be displayed.") | |||
| 399 | (let ((result (hif-eq-expr))) | 378 | (let ((result (hif-eq-expr))) |
| 400 | (while (eq hif-token 'and) | 379 | (while (eq hif-token 'and) |
| 401 | (hif-nexttoken) | 380 | (hif-nexttoken) |
| 402 | (setq result (list 'and result (hif-eq-expr)))) | 381 | (setq result (list 'hif-and result (hif-eq-expr)))) |
| 403 | result)) | 382 | result)) |
| 404 | 383 | ||
| 405 | (defun hif-eq-expr () | 384 | (defun hif-eq-expr () |
| @@ -418,7 +397,7 @@ that form should be displayed.") | |||
| 418 | math : factor | math '+|-' factor." | 397 | math : factor | math '+|-' factor." |
| 419 | (let ((result (hif-factor)) | 398 | (let ((result (hif-factor)) |
| 420 | (math-op nil)) | 399 | (math-op nil)) |
| 421 | (while (or (eq hif-token 'hif-plus) (eq hif-token 'hif-minus)) | 400 | (while (memq hif-token '(hif-plus hif-minus)) |
| 422 | (setq math-op hif-token) | 401 | (setq math-op hif-token) |
| 423 | (hif-nexttoken) | 402 | (hif-nexttoken) |
| 424 | (setq result (list math-op result (hif-factor)))) | 403 | (setq result (list math-op result (hif-factor)))) |
| @@ -429,7 +408,7 @@ that form should be displayed.") | |||
| 429 | (cond | 408 | (cond |
| 430 | ((eq hif-token 'not) | 409 | ((eq hif-token 'not) |
| 431 | (hif-nexttoken) | 410 | (hif-nexttoken) |
| 432 | (list 'not (hif-factor))) | 411 | (list 'hif-not (hif-factor))) |
| 433 | 412 | ||
| 434 | ((eq hif-token 'lparen) | 413 | ((eq hif-token 'lparen) |
| 435 | (hif-nexttoken) | 414 | (hif-nexttoken) |
| @@ -441,18 +420,20 @@ that form should be displayed.") | |||
| 441 | 420 | ||
| 442 | ((eq hif-token 'hif-defined) | 421 | ((eq hif-token 'hif-defined) |
| 443 | (hif-nexttoken) | 422 | (hif-nexttoken) |
| 444 | (if (not (eq hif-token 'lparen)) | 423 | (let ((paren (when (eq hif-token 'lparen) (hif-nexttoken) t)) |
| 445 | (error "Error: expected \"(\" after \"defined\"")) | 424 | (ident hif-token)) |
| 446 | (hif-nexttoken) | ||
| 447 | (let ((ident hif-token)) | ||
| 448 | (if (memq hif-token '(or and not hif-defined lparen rparen)) | 425 | (if (memq hif-token '(or and not hif-defined lparen rparen)) |
| 449 | (error "Error: unexpected token: %s" hif-token)) | 426 | (error "Error: unexpected token: %s" hif-token)) |
| 450 | (hif-nexttoken) | 427 | (when paren |
| 451 | (unless (eq hif-token 'rparen) | 428 | (hif-nexttoken) |
| 452 | (error "Error: expected \")\" after identifier")) | 429 | (unless (eq hif-token 'rparen) |
| 430 | (error "Error: expected \")\" after identifier"))) | ||
| 453 | (hif-nexttoken) | 431 | (hif-nexttoken) |
| 454 | `(hif-defined (quote ,ident)))) | 432 | `(hif-defined (quote ,ident)))) |
| 455 | 433 | ||
| 434 | ((numberp hif-token) | ||
| 435 | (prog1 hif-token (hif-nexttoken))) | ||
| 436 | |||
| 456 | (t ; identifier | 437 | (t ; identifier |
| 457 | (let ((ident hif-token)) | 438 | (let ((ident hif-token)) |
| 458 | (if (memq ident '(or and)) | 439 | (if (memq ident '(or and)) |
| @@ -466,6 +447,12 @@ that form should be displayed.") | |||
| 466 | ((null val) 0) | 447 | ((null val) 0) |
| 467 | (t val))) | 448 | (t val))) |
| 468 | 449 | ||
| 450 | (defun hif-and (a b) | ||
| 451 | (and (not (zerop (hif-mathify a))) (not (zerop (hif-mathify b))))) | ||
| 452 | (defun hif-or (a b) | ||
| 453 | (or (not (zerop (hif-mathify a))) (not (zerop (hif-mathify b))))) | ||
| 454 | (defun hif-not (a) | ||
| 455 | (zerop (hif-mathify a))) | ||
| 469 | (defun hif-plus (a b) | 456 | (defun hif-plus (a b) |
| 470 | "Like ordinary plus but treat t and nil as 1 and 0." | 457 | "Like ordinary plus but treat t and nil as 1 and 0." |
| 471 | (+ (hif-mathify a) (hif-mathify b))) | 458 | (+ (hif-mathify a) (hif-mathify b))) |
| @@ -495,13 +482,12 @@ that form should be displayed.") | |||
| 495 | (save-excursion | 482 | (save-excursion |
| 496 | (let ((negate (looking-at hif-ifndef-regexp))) | 483 | (let ((negate (looking-at hif-ifndef-regexp))) |
| 497 | (re-search-forward hif-ifx-regexp) | 484 | (re-search-forward hif-ifx-regexp) |
| 498 | (let* ((expr-string | 485 | (let* ((tokens (hif-tokenize (point) |
| 499 | (buffer-substring (point) | 486 | (progn (hif-end-of-line) (point)))) |
| 500 | (progn (skip-chars-forward "^\n\r") (point)))) | 487 | (expr (hif-parse-if-exp tokens))) |
| 501 | (expr (hif-infix-to-prefix (hif-tokenize expr-string)))) | ||
| 502 | ;; (message "hif-canonicalized: %s" expr) | 488 | ;; (message "hif-canonicalized: %s" expr) |
| 503 | (if negate | 489 | (if negate |
| 504 | (list 'not expr) | 490 | (list 'hif-not expr) |
| 505 | expr))))) | 491 | expr))))) |
| 506 | 492 | ||
| 507 | 493 | ||
| @@ -669,12 +655,12 @@ With argument, do this that many times." | |||
| 669 | ;;; Only valid if ELSE-P is true. | 655 | ;;; Only valid if ELSE-P is true. |
| 670 | ;;; END The end of the range. (beginning of line) | 656 | ;;; END The end of the range. (beginning of line) |
| 671 | 657 | ||
| 672 | (defun hif-make-range (start end &optional else) | 658 | (defsubst hif-make-range (start end &optional else) |
| 673 | (list start else end)) | 659 | (list start else end)) |
| 674 | 660 | ||
| 675 | (defun hif-range-start (range) (elt range 0)) | 661 | (defsubst hif-range-start (range) (elt range 0)) |
| 676 | (defun hif-range-else (range) (elt range 1)) | 662 | (defsubst hif-range-else (range) (elt range 1)) |
| 677 | (defun hif-range-end (range) (elt range 2)) | 663 | (defsubst hif-range-end (range) (elt range 2)) |
| 678 | 664 | ||
| 679 | 665 | ||
| 680 | 666 | ||
| @@ -716,16 +702,14 @@ Point is left unchanged." | |||
| 716 | 702 | ||
| 717 | 703 | ||
| 718 | ;;; A bit slimy. | 704 | ;;; A bit slimy. |
| 719 | ;;; NOTE: If there's an #ifdef at the beginning of the file, we can't | ||
| 720 | ;;; hide it. There's no previous newline to replace. If we added | ||
| 721 | ;;; one, we'd throw off all the counts. Feh. | ||
| 722 | 705 | ||
| 723 | (defun hif-hide-line (point) | 706 | (defun hif-hide-line (point) |
| 724 | "Hide the line containing point. Does nothing if `hide-ifdef-lines' is nil." | 707 | "Hide the line containing point. Does nothing if `hide-ifdef-lines' is nil." |
| 725 | (if hide-ifdef-lines | 708 | (if hide-ifdef-lines |
| 726 | (save-excursion | 709 | (save-excursion |
| 727 | (goto-char point) | 710 | (goto-char point) |
| 728 | (hide-ifdef-region (line-end-position 0) (line-end-position))))) | 711 | (hide-ifdef-region-internal (line-beginning-position) |
| 712 | (progn (hif-end-of-line) (point)))))) | ||
| 729 | 713 | ||
| 730 | 714 | ||
| 731 | ;;; Hif-Possibly-Hide | 715 | ;;; Hif-Possibly-Hide |
| @@ -769,10 +753,10 @@ It uses the judgement of `hide-ifdef-evaluator'." | |||
| 769 | ;; (message "test = %s" test) (sit-for 1) | 753 | ;; (message "test = %s" test) (sit-for 1) |
| 770 | 754 | ||
| 771 | (hif-hide-line (hif-range-end range)) | 755 | (hif-hide-line (hif-range-end range)) |
| 772 | (if (funcall hide-ifdef-evaluator test) | 756 | (if (not (hif-not (funcall hide-ifdef-evaluator test))) |
| 773 | (cond ((hif-range-else range) ; case 1 | 757 | (cond ((hif-range-else range) ; case 1 |
| 774 | (hif-hide-line (hif-range-else range)) | 758 | (hif-hide-line (hif-range-else range)) |
| 775 | (hide-ifdef-region (hif-range-else range) | 759 | (hide-ifdef-region (hif-range-else range) |
| 776 | (1- (hif-range-end range))) | 760 | (1- (hif-range-end range))) |
| 777 | (hif-recurse-on (hif-range-start range) | 761 | (hif-recurse-on (hif-range-start range) |
| 778 | (hif-range-else range))) | 762 | (hif-range-else range))) |