From b7bbf6f28f70ce31285fec9b09d6f73c9d3a13fb Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 5 Nov 2021 15:40:37 +0200 Subject: [PATCH] Enhance 'highlight-confusing-reorderings' * lisp/international/mule-cmds.el (confusingly-reordered): Make sure the face looks distinct on displays that don't support the "wavy" underline attribute. (highlight-confusing-reorderings): Add a tooltip explaining why the text was highlighted. Allow to remove the highlighting by invoking the command with a prefix argument. --- lisp/international/mule-cmds.el | 108 ++++++++++++++++++++------------ 1 file changed, 68 insertions(+), 40 deletions(-) diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el index c05a99c4d3c..91219ca480c 100644 --- a/lisp/international/mule-cmds.el +++ b/lisp/international/mule-cmds.el @@ -3260,7 +3260,10 @@ as names, not numbers." (define-key ctl-x-map "8\r" 'insert-char) (defface confusingly-reordered - '((t :inherit underline :underline (:style wave :color "Red1"))) + '((((supports :underline (:style wave))) + :underline (:style wave :color "Red1")) + (t + :inherit warning)) "Face for highlighting text that was bidi-reordered in confusing ways." :version "29.1") @@ -3269,7 +3272,11 @@ as names, not numbers." (defvar reorder-enders "[\u202C\u2069]+\\|\n" "Regular expression for characters that end forced-reordered text.") -(defun highlight-confusing-reorderings (beg end) +(autoload 'text-property-search-forward "text-property-search") +(autoload 'prop-match-beginning "text-property-search") +(autoload 'prop-match-end "text-property-search") + +(defun highlight-confusing-reorderings (beg end &optional remove) "Highlight text in region that might be bidi-reordered in suspicious ways. This command find and highlights segments of buffer text that could have been reordered on display by using directional control characters, such @@ -3280,46 +3287,67 @@ highlighted using the `confusingly-reordered' face. If the region is active, check the text inside the region. Otherwise check the entire buffer. When called from Lisp, pass BEG and END to -specify the portion of the buffer to check." +specify the portion of the buffer to check. + +Optional argument REMOVE, if non-nil (interactively, prefix argument), +means remove the highlighting from the region between BEG and END, +or the active region if that is set." (interactive (if (use-region-p) - (list (region-beginning) (region-end)) - (list (point-min) (point-max)))) + (list (region-beginning) (region-end) current-prefix-arg) + (list (point-min) (point-max) current-prefix-arg))) (save-excursion - (let (next) - (goto-char beg) - (while (setq next - (bidi-find-overridden-directionality - (point) end nil - (current-bidi-paragraph-direction))) - (goto-char next) - ;; We detect the problematic parts by watching directional - ;; properties of strong L2R and R2L characters. But malicious - ;; reordering in source buffers can, and usuually does, - ;; include syntactically-important punctuation characters. - ;; Those have "weak" directionality, so we cannot easily - ;; detect when they are affected in malicious ways. - ;; Therefore, once we find a strong directional character - ;; whose directionality was tweaked, we highlight the text - ;; around it, between the first bidi control character we find - ;; before it that starts an override/embedding/isolate, and - ;; the first control after it that ends these. This could - ;; sometimes highlight only part of the affected text. An - ;; alternative would be to find the first "starter" following - ;; BOL and the last "ender" before EOL, and highlight - ;; everything in between them -- this could sometimes - ;; highlight too much. - (let ((start - (save-excursion - (re-search-backward reorder-starters nil t))) - (finish - (save-excursion - (re-search-forward reorder-enders nil t)))) - (with-silent-modifications - (add-text-properties start (1- finish) - '(font-lock-face - 'confusingly-reordered - face 'confusingly-reordered))) - (goto-char finish)))))) + (if remove + (let (prop-match) + (goto-char beg) + (while (and + (setq prop-match + (text-property-search-forward 'font-lock-face + 'confusingly-reordered t)) + (< (prop-match-beginning prop-match) end)) + (with-silent-modifications + (remove-list-of-text-properties (prop-match-beginning prop-match) + (prop-match-end prop-match) + '(font-lock-face face mouse-face + help-echo))))) + (let (next) + (goto-char beg) + (while (setq next + (bidi-find-overridden-directionality + (point) end nil + (current-bidi-paragraph-direction))) + (goto-char next) + ;; We detect the problematic parts by watching directional + ;; properties of strong L2R and R2L characters. But + ;; malicious reordering in source buffers can, and usuually + ;; does, include syntactically-important punctuation + ;; characters. Those have "weak" directionality, so we + ;; cannot easily detect when they are affected in malicious + ;; ways. Therefore, once we find a strong directional + ;; character whose directionality was tweaked, we highlight + ;; the text around it, between the first bidi control + ;; character we find before it that starts an + ;; override/embedding/isolate, and the first control after + ;; it that ends these. This could sometimes highlight only + ;; part of the affected text. An alternative would be to + ;; find the first "starter" following BOL and the last + ;; "ender" before EOL, and highlight everything in between + ;; them -- this could sometimes highlight too much. + (let ((start + (save-excursion + (re-search-backward reorder-starters nil t))) + (finish + (save-excursion + (re-search-forward reorder-enders nil t)))) + (with-silent-modifications + (add-text-properties start (1- finish) + '(font-lock-face + confusingly-reordered + face confusingly-reordered + mouse-face highlight + help-echo "\ +This text is reordered on display in a way that could change its semantics; +use \\[forward-char] and \\[backward-char] to see the actual order of characters."))) + (goto-char finish))))))) ;;; mule-cmds.el ends here -- 2.39.2