diff options
| author | Stefan Monnier | 2013-08-29 17:00:18 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2013-08-29 17:00:18 -0400 |
| commit | 112798c18dbbb095a34ace257767ae6f57643468 (patch) | |
| tree | 99d4759444b3609f43954776f38da1cec29b357f | |
| parent | 40f7e0e853bf21003fdffeac35e47616f393055d (diff) | |
| download | emacs-112798c18dbbb095a34ace257767ae6f57643468.tar.gz emacs-112798c18dbbb095a34ace257767ae6f57643468.zip | |
* lisp/textmodes/css-mode.el: Use SMIE.
(css-smie-grammar): New var.
(css-smie--forward-token, css-smie--backward-token)
(css-smie-rules): New functions.
(css-mode): Use them.
(css-navigation-syntax-table): Remove var.
(css-backward-sexp, css-forward-sexp, css-indent-calculate-virtual)
(css-indent-calculate, css-indent-line): Remove functions.
| -rw-r--r-- | lisp/ChangeLog | 27 | ||||
| -rw-r--r-- | lisp/textmodes/css-mode.el | 172 |
2 files changed, 72 insertions, 127 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 4d0859097d2..a2028d5623b 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,5 +1,32 @@ | |||
| 1 | 2013-08-29 Stefan Monnier <monnier@iro.umontreal.ca> | 1 | 2013-08-29 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 2 | ||
| 3 | * textmodes/css-mode.el: Use SMIE. | ||
| 4 | (css-smie-grammar): New var. | ||
| 5 | (css-smie--forward-token, css-smie--backward-token) | ||
| 6 | (css-smie-rules): New functions. | ||
| 7 | (css-mode): Use them. | ||
| 8 | (css-navigation-syntax-table): Remove var. | ||
| 9 | (css-backward-sexp, css-forward-sexp, css-indent-calculate-virtual) | ||
| 10 | (css-indent-calculate, css-indent-line): Remove functions. | ||
| 11 | |||
| 12 | Misc changes to reduce use of `(lambda...); and other cleanups. | ||
| 13 | * cus-edit.el: Use lexical-binding. | ||
| 14 | (customize-push-and-save, customize-apropos) | ||
| 15 | (custom-buffer-create-internal): Use closures. | ||
| 16 | * progmodes/bat-mode.el (bat-mode-syntax-table): "..." are strings. | ||
| 17 | * progmodes/ada-xref.el: Use setq. | ||
| 18 | * net/tramp.el (with-tramp-progress-reporter): Avoid setq. | ||
| 19 | * dframe.el: Use lexical-binding. | ||
| 20 | (dframe-frame-mode): Fix calling convention for hooks. Use a closure. | ||
| 21 | * speedbar.el (speedbar-frame-mode): Adjust call accordingly. | ||
| 22 | * descr-text.el: Use lexical-binding. | ||
| 23 | (describe-text-widget, describe-text-sexp, describe-property-list): | ||
| 24 | Use closures. | ||
| 25 | * comint.el (comint-history-isearch-push-state): Use a closure. | ||
| 26 | * calculator.el: Use lexical-binding. | ||
| 27 | (calculator-number-to-string): Make it work with lexical-binding. | ||
| 28 | (calculator-funcall): Same and use cl-letf. | ||
| 29 | |||
| 3 | * emacs-lisp/lisp.el (lisp--company-doc-buffer) | 30 | * emacs-lisp/lisp.el (lisp--company-doc-buffer) |
| 4 | (lisp--company-doc-string, lisp--company-location): New functions. | 31 | (lisp--company-doc-string, lisp--company-location): New functions. |
| 5 | (lisp-completion-at-point): Use them to improve Company support. | 32 | (lisp-completion-at-point): Use them to improve Company support. |
diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el index cb19c018839..9c32604b4f4 100644 --- a/lisp/textmodes/css-mode.el +++ b/lisp/textmodes/css-mode.el | |||
| @@ -263,6 +263,48 @@ | |||
| 263 | (defvar css-font-lock-defaults | 263 | (defvar css-font-lock-defaults |
| 264 | '(css-font-lock-keywords nil t)) | 264 | '(css-font-lock-keywords nil t)) |
| 265 | 265 | ||
| 266 | (defcustom css-indent-offset 4 | ||
| 267 | "Basic size of one indentation step." | ||
| 268 | :version "22.2" | ||
| 269 | :type 'integer) | ||
| 270 | |||
| 271 | (require 'smie) | ||
| 272 | |||
| 273 | (defconst css-smie-grammar | ||
| 274 | (smie-prec2->grammar | ||
| 275 | (smie-precs->prec2 '((assoc ";") (assoc ",") (left ":"))))) | ||
| 276 | |||
| 277 | (defun css-smie--forward-token () | ||
| 278 | (cond | ||
| 279 | ((and (eq (char-before) ?\}) | ||
| 280 | ;; FIXME: If the next char is not whitespace, what should we do? | ||
| 281 | (or (memq (char-after) '(?\s ?\t ?\n)) | ||
| 282 | (looking-at comment-start-skip))) | ||
| 283 | (if (memq (char-after) '(?\s ?\t ?\n)) | ||
| 284 | (forward-char 1) (forward-comment 1)) | ||
| 285 | ";") | ||
| 286 | ((progn (forward-comment (point-max)) | ||
| 287 | (looking-at "[;,:]")) | ||
| 288 | (forward-char 1) (match-string 0)) | ||
| 289 | (t (smie-default-forward-token)))) | ||
| 290 | |||
| 291 | (defun css-smie--backward-token () | ||
| 292 | (let ((pos (point))) | ||
| 293 | (forward-comment (- (point))) | ||
| 294 | (cond | ||
| 295 | ;; FIXME: If the next char is not whitespace, what should we do? | ||
| 296 | ((and (eq (char-before) ?\}) (> pos (point))) ";") | ||
| 297 | ((memq (char-before) '(?\; ?\, ?\:)) | ||
| 298 | (forward-char -1) (string (char-after))) | ||
| 299 | (t (smie-default-backward-token))))) | ||
| 300 | |||
| 301 | (defun css-smie-rules (kind token) | ||
| 302 | (pcase (cons kind token) | ||
| 303 | (`(:elem . basic) css-indent-offset) | ||
| 304 | (`(:elem . arg) 0) | ||
| 305 | (`(:before . "{") (if (smie-rule-hanging-p) | ||
| 306 | (smie-rule-parent 0))))) | ||
| 307 | |||
| 266 | ;;;###autoload | 308 | ;;;###autoload |
| 267 | (define-derived-mode css-mode fundamental-mode "CSS" | 309 | (define-derived-mode css-mode fundamental-mode "CSS" |
| 268 | "Major mode to edit Cascading Style Sheets." | 310 | "Major mode to edit Cascading Style Sheets." |
| @@ -271,11 +313,13 @@ | |||
| 271 | (setq-local comment-start-skip "/\\*+[ \t]*") | 313 | (setq-local comment-start-skip "/\\*+[ \t]*") |
| 272 | (setq-local comment-end "*/") | 314 | (setq-local comment-end "*/") |
| 273 | (setq-local comment-end-skip "[ \t]*\\*+/") | 315 | (setq-local comment-end-skip "[ \t]*\\*+/") |
| 274 | (setq-local forward-sexp-function 'css-forward-sexp) | ||
| 275 | (setq-local parse-sexp-ignore-comments t) | 316 | (setq-local parse-sexp-ignore-comments t) |
| 276 | (setq-local indent-line-function 'css-indent-line) | 317 | (setq-local indent-line-function 'css-indent-line) |
| 277 | (setq-local fill-paragraph-function 'css-fill-paragraph) | 318 | (setq-local fill-paragraph-function 'css-fill-paragraph) |
| 278 | (setq-local add-log-current-defun-function #'css-current-defun-name) | 319 | (setq-local add-log-current-defun-function #'css-current-defun-name) |
| 320 | (smie-setup css-smie-grammar #'css-smie-rules | ||
| 321 | :forward-token #'css-smie--forward-token | ||
| 322 | :backward-token #'css-smie--backward-token) | ||
| 279 | (when css-electric-keys | 323 | (when css-electric-keys |
| 280 | (let ((fc (make-char-table 'auto-fill-chars))) | 324 | (let ((fc (make-char-table 'auto-fill-chars))) |
| 281 | (set-char-table-parent fc auto-fill-chars) | 325 | (set-char-table-parent fc auto-fill-chars) |
| @@ -355,132 +399,6 @@ | |||
| 355 | ;; Don't use the default filling code. | 399 | ;; Don't use the default filling code. |
| 356 | t))))))) | 400 | t))))))) |
| 357 | 401 | ||
| 358 | ;;; Navigation and indentation. | ||
| 359 | |||
| 360 | (defconst css-navigation-syntax-table | ||
| 361 | (let ((st (make-syntax-table css-mode-syntax-table))) | ||
| 362 | (map-char-table (lambda (c v) | ||
| 363 | ;; Turn punctuation (code = 1) into symbol (code = 1). | ||
| 364 | (if (eq (car-safe v) 1) | ||
| 365 | (set-char-table-range st c (cons 3 (cdr v))))) | ||
| 366 | st) | ||
| 367 | st)) | ||
| 368 | |||
| 369 | (defun css-backward-sexp (n) | ||
| 370 | (let ((forward-sexp-function nil)) | ||
| 371 | (if (< n 0) (css-forward-sexp (- n)) | ||
| 372 | (while (> n 0) | ||
| 373 | (setq n (1- n)) | ||
| 374 | (forward-comment (- (point-max))) | ||
| 375 | (if (not (eq (char-before) ?\;)) | ||
| 376 | (backward-sexp 1) | ||
| 377 | (while (progn (backward-sexp 1) | ||
| 378 | (save-excursion | ||
| 379 | (forward-comment (- (point-max))) | ||
| 380 | ;; FIXME: We should also skip punctuation. | ||
| 381 | (not (or (bobp) (memq (char-before) '(?\; ?\{)))))))))))) | ||
| 382 | |||
| 383 | (defun css-forward-sexp (n) | ||
| 384 | (let ((forward-sexp-function nil)) | ||
| 385 | (if (< n 0) (css-backward-sexp (- n)) | ||
| 386 | (while (> n 0) | ||
| 387 | (setq n (1- n)) | ||
| 388 | (forward-comment (point-max)) | ||
| 389 | (if (not (eq (char-after) ?\;)) | ||
| 390 | (forward-sexp 1) | ||
| 391 | (while (progn (forward-sexp 1) | ||
| 392 | (save-excursion | ||
| 393 | (forward-comment (point-max)) | ||
| 394 | ;; FIXME: We should also skip punctuation. | ||
| 395 | (not (memq (char-after) '(?\; ?\}))))))))))) | ||
| 396 | |||
| 397 | (defun css-indent-calculate-virtual () | ||
| 398 | (if (or (save-excursion (skip-chars-backward " \t") (bolp)) | ||
| 399 | (if (looking-at "\\s(") | ||
| 400 | (save-excursion | ||
| 401 | (forward-char 1) (skip-chars-forward " \t") | ||
| 402 | (not (or (eolp) (looking-at comment-start-skip)))))) | ||
| 403 | (current-column) | ||
| 404 | (css-indent-calculate))) | ||
| 405 | |||
| 406 | (defcustom css-indent-offset 4 | ||
| 407 | "Basic size of one indentation step." | ||
| 408 | :version "22.2" | ||
| 409 | :type 'integer | ||
| 410 | :group 'css) | ||
| 411 | |||
| 412 | (defun css-indent-calculate () | ||
| 413 | (let ((ppss (syntax-ppss)) | ||
| 414 | pos) | ||
| 415 | (with-syntax-table css-navigation-syntax-table | ||
| 416 | (save-excursion | ||
| 417 | (cond | ||
| 418 | ;; Inside a string. | ||
| 419 | ((nth 3 ppss) 'noindent) | ||
| 420 | ;; Inside a comment. | ||
| 421 | ((nth 4 ppss) | ||
| 422 | (setq pos (point)) | ||
| 423 | (forward-line -1) | ||
| 424 | (skip-chars-forward " \t") | ||
| 425 | (if (>= (nth 8 ppss) (point)) | ||
| 426 | (progn | ||
| 427 | (goto-char (nth 8 ppss)) | ||
| 428 | (if (eq (char-after pos) ?*) | ||
| 429 | (forward-char 1) | ||
| 430 | (if (not (looking-at comment-start-skip)) | ||
| 431 | (error "Internal css-mode error") | ||
| 432 | (goto-char (match-end 0)))) | ||
| 433 | (current-column)) | ||
| 434 | (if (and (eq (char-after pos) ?*) (eq (char-after) ?*)) | ||
| 435 | (current-column) | ||
| 436 | ;; 'noindent | ||
| 437 | (current-column) | ||
| 438 | ))) | ||
| 439 | ;; In normal code. | ||
| 440 | (t | ||
| 441 | (or | ||
| 442 | (when (looking-at "\\s)") | ||
| 443 | (forward-char 1) | ||
| 444 | (backward-sexp 1) | ||
| 445 | (css-indent-calculate-virtual)) | ||
| 446 | (when (looking-at comment-start-skip) | ||
| 447 | (forward-comment (point-max)) | ||
| 448 | (css-indent-calculate)) | ||
| 449 | (when (save-excursion (forward-comment (- (point-max))) | ||
| 450 | (setq pos (point)) | ||
| 451 | (eq (char-syntax (preceding-char)) ?\()) | ||
| 452 | (goto-char (1- pos)) | ||
| 453 | (if (not (looking-at "\\s([ \t]*")) | ||
| 454 | (error "Internal css-mode error") | ||
| 455 | (if (or (memq (char-after (match-end 0)) '(?\n nil)) | ||
| 456 | (save-excursion (goto-char (match-end 0)) | ||
| 457 | (looking-at comment-start-skip))) | ||
| 458 | (+ (css-indent-calculate-virtual) css-indent-offset) | ||
| 459 | (progn (goto-char (match-end 0)) (current-column))))) | ||
| 460 | (progn | ||
| 461 | (css-backward-sexp 1) | ||
| 462 | (if (looking-at "\\s(") | ||
| 463 | (css-indent-calculate) | ||
| 464 | (css-indent-calculate-virtual)))))))))) | ||
| 465 | |||
| 466 | |||
| 467 | (defun css-indent-line () | ||
| 468 | "Indent current line according to CSS indentation rules." | ||
| 469 | (interactive) | ||
| 470 | (let* ((savep (point)) | ||
| 471 | (forward-sexp-function nil) | ||
| 472 | (indent (condition-case nil | ||
| 473 | (save-excursion | ||
| 474 | (forward-line 0) | ||
| 475 | (skip-chars-forward " \t") | ||
| 476 | (if (>= (point) savep) (setq savep nil)) | ||
| 477 | (css-indent-calculate)) | ||
| 478 | (error nil)))) | ||
| 479 | (if (not (numberp indent)) 'noindent | ||
| 480 | (if savep | ||
| 481 | (save-excursion (indent-line-to indent)) | ||
| 482 | (indent-line-to indent))))) | ||
| 483 | |||
| 484 | (defun css-current-defun-name () | 402 | (defun css-current-defun-name () |
| 485 | "Return the name of the CSS section at point, or nil." | 403 | "Return the name of the CSS section at point, or nil." |
| 486 | (save-excursion | 404 | (save-excursion |