diff options
| author | Michal Nazarewicz | 2018-03-31 14:16:54 +0100 |
|---|---|---|
| committer | Michal Nazarewicz | 2018-04-07 11:16:12 +0100 |
| commit | 8d3bb7beb4bfab60ba31505728f8f945116d7a40 (patch) | |
| tree | c8bea63e9079c07dd69193ac3cf6ddaf6af1d7d3 | |
| parent | 358da4565b589570759ddc9c2d1043405fdbb26e (diff) | |
| download | emacs-8d3bb7beb4bfab60ba31505728f8f945116d7a40.tar.gz emacs-8d3bb7beb4bfab60ba31505728f8f945116d7a40.zip | |
Handle quotation marks and apostrophes in ‘sgml-quote’
To be able to use text in an HTML argument, quotation marks need
to be replaced with an appropriate character reference. Make
‘sgml-quote’ do that.
While at it, fix entiteis not being unquoted if they lack closing
semicolon (e.g. ‘&’) occuring at the very end of a region.
Even though unlikely, make ‘sgml-quote’ handle this scenario.
* lisp/textmodes/sgml-mode.el (sgml-quote): Handle quotation marks and
apostrophes. Match entities lacking semicolon at the end of regions.
* test/lisp/textmodes/sgml-mode-tests.el (sgml-quote-works): New test
case for ‘sgml-quote’ function.
| -rw-r--r-- | etc/NEWS | 7 | ||||
| -rw-r--r-- | lisp/textmodes/sgml-mode.el | 26 | ||||
| -rw-r--r-- | test/lisp/textmodes/sgml-mode-tests.el | 30 |
3 files changed, 56 insertions, 7 deletions
| @@ -208,6 +208,13 @@ Can be controlled via the new variable 'footnote-align-to-fn-text'. | |||
| 208 | formats (e.g. "black" => "#000000" => "rgb(0, 0, 0)") has been added, | 208 | formats (e.g. "black" => "#000000" => "rgb(0, 0, 0)") has been added, |
| 209 | bound to 'C-c C-f'. | 209 | bound to 'C-c C-f'. |
| 210 | 210 | ||
| 211 | ** SGML mode | ||
| 212 | |||
| 213 | --- | ||
| 214 | *** 'sgml-quote' now handles double quotes and apostrophes | ||
| 215 | when escaping text and in addition all numeric entities when | ||
| 216 | unescaping text. | ||
| 217 | |||
| 211 | ** Dired | 218 | ** Dired |
| 212 | 219 | ||
| 213 | +++ | 220 | +++ |
diff --git a/lisp/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el index f6bdfc63844..52d14bd800c 100644 --- a/lisp/textmodes/sgml-mode.el +++ b/lisp/textmodes/sgml-mode.el | |||
| @@ -1241,8 +1241,11 @@ See `sgml-tag-alist' for info about attribute rules." | |||
| 1241 | 1241 | ||
| 1242 | (defun sgml-quote (start end &optional unquotep) | 1242 | (defun sgml-quote (start end &optional unquotep) |
| 1243 | "Quote SGML text in region START ... END. | 1243 | "Quote SGML text in region START ... END. |
| 1244 | Only &, < and > are quoted, the rest is left untouched. | 1244 | Only &, <, >, ' and \" characters are quoted, the rest is left |
| 1245 | With prefix argument UNQUOTEP, unquote the region." | 1245 | untouched. This is sufficient to use quoted text as SGML argument. |
| 1246 | |||
| 1247 | With prefix argument UNQUOTEP, unquote the region. All numeric entities, | ||
| 1248 | \"amp\", \"lt\", \"gt\" and \"quot\" named entities are unquoted." | ||
| 1246 | (interactive "r\nP") | 1249 | (interactive "r\nP") |
| 1247 | (save-restriction | 1250 | (save-restriction |
| 1248 | (narrow-to-region start end) | 1251 | (narrow-to-region start end) |
| @@ -1250,14 +1253,23 @@ With prefix argument UNQUOTEP, unquote the region." | |||
| 1250 | (if unquotep | 1253 | (if unquotep |
| 1251 | ;; FIXME: We should unquote other named character references as well. | 1254 | ;; FIXME: We should unquote other named character references as well. |
| 1252 | (while (re-search-forward | 1255 | (while (re-search-forward |
| 1253 | "\\(&\\(amp\\|\\(l\\|\\(g\\)\\)t\\)\\)[][<>&;\n\t \"%!'(),/=?]" | 1256 | "\\(&\\(amp\\|quot\\|lt\\|gt\\|#\\([0-9]+\\|[xX][0-9a-fA-F]+\\)\\)\\)\\([][<>&;\n\t \"%!'(),/=?]\\|$\\)" |
| 1254 | nil t) | 1257 | nil t) |
| 1255 | (replace-match (if (match-end 4) ">" (if (match-end 3) "<" "&")) t t | 1258 | (replace-match |
| 1256 | nil (if (eq (char-before (match-end 0)) ?\;) 0 1))) | 1259 | (string |
| 1257 | (while (re-search-forward "[&<>]" nil t) | 1260 | (or (cdr (assq (char-after (match-beginning 2)) |
| 1261 | '((?a . ?&) (?q . ?\") (?l . ?<) (?g . ?>)))) | ||
| 1262 | (let ((num (match-string 3))) | ||
| 1263 | (if (or (eq ?x (aref num 0)) (eq ?X (aref num 0))) | ||
| 1264 | (string-to-number (substring num 1) 16) | ||
| 1265 | (string-to-number num 10))))) | ||
| 1266 | t t nil (if (eq (char-before (match-end 0)) ?\;) 0 1))) | ||
| 1267 | (while (re-search-forward "[&<>\"']" nil t) | ||
| 1258 | (replace-match (cdr (assq (char-before) '((?& . "&") | 1268 | (replace-match (cdr (assq (char-before) '((?& . "&") |
| 1259 | (?< . "<") | 1269 | (?< . "<") |
| 1260 | (?> . ">")))) | 1270 | (?> . ">") |
| 1271 | (?\" . """) | ||
| 1272 | (?' . "'")))) | ||
| 1261 | t t))))) | 1273 | t t))))) |
| 1262 | 1274 | ||
| 1263 | (defun sgml-pretty-print (beg end) | 1275 | (defun sgml-pretty-print (beg end) |
diff --git a/test/lisp/textmodes/sgml-mode-tests.el b/test/lisp/textmodes/sgml-mode-tests.el index 7ca6e676c64..6c0070ccb1e 100644 --- a/test/lisp/textmodes/sgml-mode-tests.el +++ b/test/lisp/textmodes/sgml-mode-tests.el | |||
| @@ -131,5 +131,35 @@ The point is set to the beginning of the buffer." | |||
| 131 | (sgml-delete-tag 1) | 131 | (sgml-delete-tag 1) |
| 132 | (should (string= "Winter is comin'" (buffer-string))))) | 132 | (should (string= "Winter is comin'" (buffer-string))))) |
| 133 | 133 | ||
| 134 | (ert-deftest sgml-quote-works () | ||
| 135 | (let ((text "Foo<Bar> \"Baz\" 'Qux'\n")) | ||
| 136 | (with-temp-buffer | ||
| 137 | ;; Back and forth transformation. | ||
| 138 | (insert text) | ||
| 139 | (sgml-quote (point-min) (point-max)) | ||
| 140 | (should (string= "Foo<Bar> "Baz" 'Qux'\n" | ||
| 141 | (buffer-string))) | ||
| 142 | (sgml-quote (point-min) (point-max) t) | ||
| 143 | (should (string= text (buffer-string))) | ||
| 144 | |||
| 145 | ;; The same text escaped differently. | ||
| 146 | (erase-buffer) | ||
| 147 | (insert "Foo<Bar> "Baz" 'Qux'\n") | ||
| 148 | (sgml-quote (point-min) (point-max) t) | ||
| 149 | (should (string= text (buffer-string))) | ||
| 150 | |||
| 151 | ;; Lack of semicolon. | ||
| 152 | (erase-buffer) | ||
| 153 | (insert "&&") | ||
| 154 | (sgml-quote (point-min) (point-max) t) | ||
| 155 | (should (string= "&&" (buffer-string))) | ||
| 156 | |||
| 157 | ;; Double quoting | ||
| 158 | (sgml-quote (point-min) (point-max)) | ||
| 159 | (sgml-quote (point-min) (point-max)) | ||
| 160 | (sgml-quote (point-min) (point-max) t) | ||
| 161 | (sgml-quote (point-min) (point-max) t) | ||
| 162 | (should (string= "&&" (buffer-string)))))) | ||
| 163 | |||
| 134 | (provide 'sgml-mode-tests) | 164 | (provide 'sgml-mode-tests) |
| 135 | ;;; sgml-mode-tests.el ends here | 165 | ;;; sgml-mode-tests.el ends here |