aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/textmodes
diff options
context:
space:
mode:
authorAlan Mackenzie2017-02-12 10:59:03 +0000
committerAlan Mackenzie2017-02-12 10:59:03 +0000
commitf4d5b687150810129b7a1d5b006e31ccf82b691b (patch)
tree4229b13800349032697daae3904dc3773e6b7a80 /lisp/textmodes
parentd5514332d4a6092673ce1f78fadcae0c57f7be64 (diff)
parent148100d98319499f0ac6f57b8be08cbd14884a5c (diff)
downloademacs-comment-cache.tar.gz
emacs-comment-cache.zip
Merge branch 'master' into comment-cachecomment-cache
Diffstat (limited to 'lisp/textmodes')
-rw-r--r--lisp/textmodes/css-mode.el156
-rw-r--r--lisp/textmodes/reftex-vars.el2
2 files changed, 155 insertions, 3 deletions
diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el
index c81c3f62e16..0c7d76f7924 100644
--- a/lisp/textmodes/css-mode.el
+++ b/lisp/textmodes/css-mode.el
@@ -32,9 +32,11 @@
32 32
33;;; Code: 33;;; Code:
34 34
35(require 'eww)
35(require 'seq) 36(require 'seq)
36(require 'sgml-mode) 37(require 'sgml-mode)
37(require 'smie) 38(require 'smie)
39(require 'subr-x)
38 40
39(defgroup css nil 41(defgroup css nil
40 "Cascading Style Sheets (CSS) editing mode." 42 "Cascading Style Sheets (CSS) editing mode."
@@ -621,6 +623,12 @@ cannot be completed sensibly: `custom-ident',
621 (modify-syntax-entry ?- "_" st) 623 (modify-syntax-entry ?- "_" st)
622 st)) 624 st))
623 625
626(defvar css-mode-map
627 (let ((map (make-sparse-keymap)))
628 (define-key map [remap info-lookup-symbol] 'css-lookup-symbol)
629 map)
630 "Keymap used in `css-mode'.")
631
624(eval-and-compile 632(eval-and-compile
625 (defconst css--uri-re 633 (defconst css--uri-re
626 (concat 634 (concat
@@ -734,7 +742,30 @@ cannot be completed sensibly: `custom-ident',
734 742
735(defconst css-smie-grammar 743(defconst css-smie-grammar
736 (smie-prec2->grammar 744 (smie-prec2->grammar
737 (smie-precs->prec2 '((assoc ";") (assoc ",") (left ":"))))) 745 (smie-precs->prec2
746 '((assoc ";")
747 ;; Colons that belong to a CSS property. These get a higher
748 ;; precedence than other colons, such as colons in selectors,
749 ;; which are represented by a plain ":" token.
750 (left ":-property")
751 (assoc ",")
752 (assoc ":")))))
753
754(defun css--colon-inside-selector-p ()
755 "Return t if point looks to be inside a CSS selector.
756This function is intended to be good enough to help SMIE during
757tokenization, but should not be regarded as a reliable function
758for determining whether point is within a selector."
759 (save-excursion
760 (re-search-forward "[{};)]" nil t)
761 (eq (char-before) ?\{)))
762
763(defun css--colon-inside-funcall ()
764 "Return t if point is inside a function call."
765 (when-let (opening-paren-pos (nth 1 (syntax-ppss)))
766 (save-excursion
767 (goto-char opening-paren-pos)
768 (eq (char-after) ?\())))
738 769
739(defun css-smie--forward-token () 770(defun css-smie--forward-token ()
740 (cond 771 (cond
@@ -748,7 +779,13 @@ cannot be completed sensibly: `custom-ident',
748 ";") 779 ";")
749 ((progn (forward-comment (point-max)) 780 ((progn (forward-comment (point-max))
750 (looking-at "[;,:]")) 781 (looking-at "[;,:]"))
751 (forward-char 1) (match-string 0)) 782 (forward-char 1)
783 (if (equal (match-string 0) ":")
784 (if (or (css--colon-inside-selector-p)
785 (css--colon-inside-funcall))
786 ":"
787 ":-property")
788 (match-string 0)))
752 (t (smie-default-forward-token)))) 789 (t (smie-default-forward-token))))
753 790
754(defun css-smie--backward-token () 791(defun css-smie--backward-token ()
@@ -759,7 +796,13 @@ cannot be completed sensibly: `custom-ident',
759 ((and (eq (char-before) ?\}) (scss-smie--not-interpolation-p) 796 ((and (eq (char-before) ?\}) (scss-smie--not-interpolation-p)
760 (> pos (point))) ";") 797 (> pos (point))) ";")
761 ((memq (char-before) '(?\; ?\, ?\:)) 798 ((memq (char-before) '(?\; ?\, ?\:))
762 (forward-char -1) (string (char-after))) 799 (forward-char -1)
800 (if (eq (char-after) ?\:)
801 (if (or (css--colon-inside-selector-p)
802 (css--colon-inside-funcall))
803 ":"
804 ":-property")
805 (string (char-after))))
763 (t (smie-default-backward-token))))) 806 (t (smie-default-backward-token)))))
764 807
765(defun css-smie-rules (kind token) 808(defun css-smie-rules (kind token)
@@ -1087,5 +1130,112 @@ pseudo-elements, pseudo-classes, at-rules, and bang-rules."
1087 (setq-local font-lock-defaults 1130 (setq-local font-lock-defaults
1088 (list (scss-font-lock-keywords) nil t))) 1131 (list (scss-font-lock-keywords) nil t)))
1089 1132
1133
1134
1135(defvar css--mdn-lookup-history nil)
1136
1137(defcustom css-lookup-url-format
1138 "https://developer.mozilla.org/en-US/docs/Web/CSS/%s?raw&macros"
1139 "Format for a URL where CSS documentation can be found.
1140The format should include a single \"%s\" substitution.
1141The name of the CSS property, @-id, pseudo-class, or pseudo-element
1142to look up will be substituted there."
1143 :version "26.1"
1144 :type 'string
1145 :group 'css)
1146
1147(defun css--mdn-after-render ()
1148 (setf header-line-format nil)
1149 (goto-char (point-min))
1150 (let ((window (get-buffer-window (current-buffer) 'visible)))
1151 (when window
1152 (when (re-search-forward "^Summary" nil 'move)
1153 (beginning-of-line)
1154 (set-window-start window (point))))))
1155
1156(defconst css--mdn-symbol-regexp
1157 (concat "\\("
1158 ;; @-ids.
1159 "\\(@" (regexp-opt css-at-ids) "\\)"
1160 "\\|"
1161 ;; ;; Known properties.
1162 (regexp-opt css-property-ids t)
1163 "\\|"
1164 ;; Pseudo-classes.
1165 "\\(:" (regexp-opt css-pseudo-class-ids) "\\)"
1166 "\\|"
1167 ;; Pseudo-elements with either one or two ":"s.
1168 "\\(::?" (regexp-opt css-pseudo-element-ids) "\\)"
1169 "\\)")
1170 "Regular expression to match the CSS symbol at point.")
1171
1172(defconst css--mdn-property-regexp
1173 (concat "\\_<" (regexp-opt css-property-ids t) "\\s-*\\(?:\\=\\|:\\)")
1174 "Regular expression to match a CSS property.")
1175
1176(defconst css--mdn-completion-list
1177 (nconc
1178 ;; @-ids.
1179 (mapcar (lambda (atrule) (concat "@" atrule)) css-at-ids)
1180 ;; Pseudo-classes.
1181 (mapcar (lambda (class) (concat ":" class)) css-pseudo-class-ids)
1182 ;; Pseudo-elements with either one or two ":"s.
1183 (mapcar (lambda (elt) (concat ":" elt)) css-pseudo-element-ids)
1184 (mapcar (lambda (elt) (concat "::" elt)) css-pseudo-element-ids)
1185 ;; Properties.
1186 css-property-ids)
1187 "List of all symbols available for lookup via MDN.")
1188
1189(defun css--mdn-find-symbol ()
1190 "A helper for `css-lookup-symbol' that finds the symbol at point.
1191Returns the symbol, a string, or nil if none found."
1192 (save-excursion
1193 ;; Skip backward over a word first.
1194 (skip-chars-backward "-[:alnum:] \t")
1195 ;; Now skip ":" or "@" to see if it's a pseudo-element or at-id.
1196 (skip-chars-backward "@:")
1197 (if (looking-at css--mdn-symbol-regexp)
1198 (match-string-no-properties 0)
1199 (let ((bound (save-excursion
1200 (beginning-of-line)
1201 (point))))
1202 (when (re-search-backward css--mdn-property-regexp bound t)
1203 (match-string-no-properties 1))))))
1204
1205;;;###autoload
1206(defun css-lookup-symbol (symbol)
1207 "Display the CSS documentation for SYMBOL, as found on MDN.
1208When this command is used interactively, it picks a default
1209symbol based on the CSS text before point -- either an @-keyword,
1210a property name, a pseudo-class, or a pseudo-element, depending
1211on what is seen near point."
1212 (interactive
1213 (list
1214 (let* ((sym (css--mdn-find-symbol))
1215 (enable-recursive-minibuffers t)
1216 (value (completing-read
1217 (if sym
1218 (format "Describe CSS symbol (default %s): " sym)
1219 "Describe CSS symbol: ")
1220 css--mdn-completion-list nil nil nil
1221 'css--mdn-lookup-history sym)))
1222 (if (equal value "") sym value))))
1223 (when symbol
1224 ;; If we see a single-colon pseudo-element like ":after", turn it
1225 ;; into "::after".
1226 (when (and (eq (aref symbol 0) ?:)
1227 (member (substring symbol 1) css-pseudo-element-ids))
1228 (setq symbol (concat ":" symbol)))
1229 (let ((url (format css-lookup-url-format symbol))
1230 (buffer (get-buffer-create "*MDN CSS*")))
1231 (save-selected-window
1232 ;; Make sure to display the buffer before calling `eww', as
1233 ;; that calls `pop-to-buffer-same-window'.
1234 (switch-to-buffer-other-window buffer)
1235 (with-current-buffer buffer
1236 (eww-mode)
1237 (add-hook 'eww-after-render-hook #'css--mdn-after-render nil t)
1238 (eww url))))))
1239
1090(provide 'css-mode) 1240(provide 'css-mode)
1091;;; css-mode.el ends here 1241;;; css-mode.el ends here
diff --git a/lisp/textmodes/reftex-vars.el b/lisp/textmodes/reftex-vars.el
index 63abd048e9d..03da584e96f 100644
--- a/lisp/textmodes/reftex-vars.el
+++ b/lisp/textmodes/reftex-vars.el
@@ -164,6 +164,8 @@ distribution. Mixed-case symbols are convenience aliases.")
164 (?U . "\\autocite*[][]{%l}") 164 (?U . "\\autocite*[][]{%l}")
165 (?a . "\\citeauthor{%l}") 165 (?a . "\\citeauthor{%l}")
166 (?A . "\\citeauthor*{%l}") 166 (?A . "\\citeauthor*{%l}")
167 (?i . "\\citetitle{%l}")
168 (?I . "\\citetitle*{%l}")
167 (?y . "\\citeyear{%l}") 169 (?y . "\\citeyear{%l}")
168 (?Y . "\\citeyear*{%l}") 170 (?Y . "\\citeyear*{%l}")
169 (?n . "\\nocite{%l}"))) 171 (?n . "\\nocite{%l}")))