emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Shankar Rao <shankar.rao@gmail.com>
To: emacs-orgmode@gnu.org
Subject: Re: [PATCH] Add mode for automatically unhiding emphasis markers in the current region
Date: Mon, 1 Jun 2020 17:33:06 +0200	[thread overview]
Message-ID: <CAGEgU=iR6cdZ7xen=cvU-WD9GNOxh8NwuazQWa7GM8Sc3WNx2w@mail.gmail.com> (raw)
In-Reply-To: <CAGEgU=j+UJoWwoRKChkVxN5dmwbD4YaNTWdLS6Qgj57osZLRJA@mail.gmail.com>


[-- Attachment #1.1: Type: text/plain, Size: 8252 bytes --]

Sorry, I've never submitted a patch before. Looking through this mailing
list, I see that you're supposed to attach the .patch file to the e-mail,
so here it is.

This patch adds a minor mode that makes emphasis markers be automatically
unhidden when the point is inside the region of emphasis and then the
markers are rehidden when the point is moved elsewhere. I posted this on
/r/orgmode on reddit (
https://www.reddit.com/r/orgmode/comments/gss1g4/update_i_made_my_own_sbrorgemphasizemode_that/),
and people there suggested that I submit this here as a patch.

Shankar

On Mon, Jun 1, 2020 at 4:14 PM Shankar Rao <shankar.rao@gmail.com> wrote:

> * lisp/org.el:
> (org-auto-emphasis-unhide-at-point): Parameter that controls the
> behavior of Org Auto Emphasis mode.  It can be one of the values nil, t,
> and
> 'right-edge, and works similarly to the parameter
> `prettify-symbols-unprettify-at-point' for `prettify-symbols-mode'.
> (org-do-emphasis-faces): When hiding emphasis markers, add additional
> text properties 'org-emph-start and org-emph-end to the emphasized
> region.
> (org-auto-emphasis--current-region-bounds): Local variable containing
> the bounds of the region whose emphasis markers are currently
> unhidden.
> (org-auto-emphasis--get-prop-as-list): Helper function that returns
> Org Auto Emphasis properties as a list.
> (org-auto-emphasis--post-command-hook): Function added to
> `post-command-hook' that rehides emphasis markers for the previous
> region and unhides emphasis marks for the current region.
> (org-auto-emphasis-mode): Toggles Org Auto Emphasis mode.  Can be
> added to `org-mode-hook' to be enabled for all org-mode files.
>
> This code was adapted from prettify-symbols-mode in prog-mode.el
>
> I have not yet signed the papers assigning copyright to the FSF.  I sent a
> request for the papers to assign@gnu.org, but have not yet received a
> response.
>
> Shankar Rao
>
> ---
>  lisp/org.el | 98 +++++++++++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 87 insertions(+), 11 deletions(-)
>
> diff --git a/lisp/org.el b/lisp/org.el
> index 7ff7ec685..870c5c958 100644
> --- a/lisp/org.el
> +++ b/lisp/org.el
> @@ -3644,6 +3644,19 @@ following symbols:
>    :type 'boolean
>    :safe #'booleanp)
>
> +(defcustom org-auto-emphasis-unhide-at-point nil
> +  "If non-nil, unhide the emphasis markers for the region when point is
> on it.
> +If set to the symbol `right-edge', also unhide the emphasis
> +markers if point is immediately after the emphasized region.  The
> +emphasis markers will be rehidden as soon as point moves away
> +from the region.  If set to nil, the emphasis markers remain
> +hidden even when point is in the region."
> +  :version "25.1"
> +  :type '(choice (const :tag "Never unhide emphasis markers" nil)
> +                 (const :tag "Unhide emphasis markers when point is
> inside" t)
> +                 (const :tag "Unhide emphasis markers when point is
> inside or at right edge" right-edge))
> +  :group 'org-appearance)
> +
>  (defcustom org-hide-macro-markers nil
>    "Non-nil mean font-lock should hide the brackets marking macro calls."
>    :group 'org-appearance
> @@ -5056,12 +5069,77 @@ stacked delimiters is N.  Escaping delimiters is
> not possible."
>     '(font-lock-multiline t org-emphasis t))
>        (when (and org-hide-emphasis-markers
>   (not (org-at-comment-p)))
> - (add-text-properties (match-end 4) (match-beginning 5)
> -     '(invisible org-link))
> - (add-text-properties (match-beginning 3) (match-end 3)
> -     '(invisible org-link)))
> + (let ((s1 (match-beginning 3))
> +      (e1 (match-end 3))
> +      (s2 (match-end 4))
> +      (e2 (match-beginning 5)))
> +  (add-text-properties s2 e2 '(invisible org-link))
> +  (add-text-properties s1 e1 '(invisible org-link))
> +  (add-text-properties s1 e2
> +       `(org-emph-start ,s1 org-emph-end ,e2))))
>        (throw :exit t))))))))
>
> +(defvar-local org-auto-emphasis--current-region-bounds nil)
> +
> +(defun org-auto-emphasis--get-prop-as-list (prop)
> +  "Helper function to get org-auto-emphasis properties as a list.
> +If `org-auto-emphasis-unhide-at-point' is set to `t' then return
> +the text property PROP at point in a list. If
> +`org-auto-emphasis-unhide-at-point' is set to `right-edge', the
> +also include the text property PROP at point-1 unless we are at
> +the beginning of the buffer."
> +  (remove nil
> +  (list (get-text-property (point) prop)
> + (when (and (eq org-auto-emphasis-unhide-at-point 'right-edge)
> +   (not (bobp)))
> +  (get-text-property (1- (point)) prop)))))
> +
> +(defun org-auto-emphasis--post-command-hook ()
> +  ;; Rehide emphasis markers for the previous region.
> +  (when (and org-auto-emphasis--current-region-bounds
> +     (or (< (point) (car org-auto-emphasis--current-region-bounds))
> + (> (point) (cadr org-auto-emphasis--current-region-bounds))
> + (and (not (eq org-auto-emphasis-unhide-at-point 'right-edge))
> +      (= (point) (cadr org-auto-emphasis--current-region-bounds)))))
> + (apply #'font-lock-flush org-auto-emphasis--current-region-bounds)
> + (setq org-auto-emphasis--current-region-bounds nil))
> +  ;; Unhide emphasis markers for the current region.
> +  (when-let* ((s (org-auto-emphasis--get-prop-as-list 'org-emph-start))
> +      (e (org-auto-emphasis--get-prop-as-list 'org-emph-end))
> +      (s (apply #'min s))
> +      (e (apply #'max e)))
> +    (with-silent-modifications
> +      (setq org-auto-emphasis--current-region-bounds (list s e))
> +      (remove-text-properties s (1+ s) '(invisible org-link))
> +      (remove-text-properties (1- e) e '(invisible org-link)))))
> +
> +(define-minor-mode org-auto-emphasis-mode
> +  "Toggle Org Auto Emphasis mode.
> +This mode, when enabled, unhides emphasis markers for the region
> +at point, depending on the value of
> +`org-auto-emphasis-unhide-at-point'. With a prefix argument ARG,
> +enable Org Auto Emphasis mode if ARG is positive, and disable it
> +otherwise.  If called from Lisp, enable the mode if ARG is
> +omitted or nil.
> +
> +To enable this in all org-mode files, add the following line to init.el:
> +
> +  (add-hook 'org-mode #'org-auto-emphasis-mode)
> +"
> +  :init-value nil
> +  (if org-auto-emphasis-mode
> +      ;; Turn on
> +      (progn
> +        (setq-local font-lock-extra-managed-props
> +                    (append font-lock-extra-managed-props
> +                            '(org-emph-start org-emph-end)))
> +        (when org-auto-emphasis-unhide-at-point
> +          (add-hook 'post-command-hook
> +                    #'org-auto-emphasis--post-command-hook nil t))
> +        (font-lock-flush))
> +    ;; Turn off
> +    (remove-hook 'post-command-hook
> #'org-auto-emphasis--post-command-hook t)))
> +
>  (defun org-emphasize (&optional char)
>    "Insert or change an emphasis, i.e. a font like bold or italic.
>  If there is an active region, change that region to a new emphasis.
> @@ -20482,16 +20560,15 @@ With ARG, repeats or can move backward if
> negative."
>     (beginning-of-line))
>    (_ nil)))
>        (cl-incf arg))
> -    (while (and (> arg 0) (re-search-forward regexp nil t))
> +    (while (and (> arg 0) (re-search-forward regexp nil :move))
>        (pcase (get-char-property-and-overlay (point) 'invisible)
>   (`(outline . ,o)
>   (goto-char (overlay-end o))
> - (skip-chars-forward " \t\n")
> - (end-of-line))
> + (end-of-line 2))
>   (_
>   (end-of-line)))
>        (cl-decf arg))
> -    (if (> arg 0) (goto-char (point-max)) (beginning-of-line))))
> +    (when (/= arg initial-arg) (beginning-of-line))))
>
>  (defun org-previous-visible-heading (arg)
>    "Move to the previous visible heading.
> @@ -20830,11 +20907,10 @@ ones already marked."
>   (set-mark
>   (save-excursion
>     (goto-char (mark))
> -   (goto-char (org-element-property :end (org-element-at-point)))
> -   (point)))
> +   (goto-char (org-element-property :end (org-element-at-point)))))
>        (let ((element (org-element-at-point)))
>   (end-of-line)
> - (push-mark (min (point-max) (org-element-property :end element)) t t)
> + (push-mark (org-element-property :end element) t t)
>   (goto-char (org-element-property :begin element))))))
>
>  (defun org-narrow-to-element ()
> --
> 2.17.1
>

[-- Attachment #1.2: Type: text/html, Size: 9508 bytes --]

[-- Attachment #2: 0001-Add-mode-for-automatically-unhiding-emphasis-markers.patch --]
[-- Type: application/octet-stream, Size: 7404 bytes --]

From c1af9efbad7993deb5c483979b7624edf8b26e8d Mon Sep 17 00:00:00 2001
From: Shankar Rao <shankar.rao@gmail.com>
Date: Mon, 1 Jun 2020 14:42:51 +0200
Subject: [PATCH] Add mode for automatically unhiding emphasis markers in the
 current region

* lisp/org.el:
(org-auto-emphasis-unhide-at-point): Parameter that controls the
behavior of Org Auto Emphasis mode.  It can be one of the values nil, t, and
'right-edge, and works similarly to the parameter
`prettify-symbols-unprettify-at-point' for `prettify-symbols-mode'.
(org-do-emphasis-faces): When hiding emphasis markers, add additional
text properties 'org-emph-start and org-emph-end to the emphasized
region.
(org-auto-emphasis--current-region-bounds): Local variable containing
the bounds of the region whose emphasis markers are currently
unhidden.
(org-auto-emphasis--get-prop-as-list): Helper function that returns
Org Auto Emphasis properties as a list.
(org-auto-emphasis--post-command-hook): Function added to
`post-command-hook' that rehides emphasis markers for the previous
region and unhides emphasis marks for the current region.
(org-auto-emphasis-mode): Toggles Org Auto Emphasis mode.  Can be
added to `org-mode-hook' to be enabled for all org-mode files.

This code was adapted from prettify-symbols-mode in prog-mode.el
---
 lisp/org.el | 98 +++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 87 insertions(+), 11 deletions(-)

diff --git a/lisp/org.el b/lisp/org.el
index 7ff7ec685..870c5c958 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -3644,6 +3644,19 @@ following symbols:
   :type 'boolean
   :safe #'booleanp)
 
+(defcustom org-auto-emphasis-unhide-at-point nil
+  "If non-nil, show the unhide the emphasis markers for the region when point is on it.
+If set to the symbol `right-edge', also unhide the emphasis
+markers if point is immediately after the emphasized region.  The
+emphasis markers will be rehidden as soon as point moves away
+from the region.  If set to nil, the emphasis markers remain
+hidden even when point is in the region."
+  :version "25.1"
+  :type '(choice (const :tag "Never unhide emphasis markers" nil)
+                 (const :tag "Unhide emphasis markers when point is inside" t)
+                 (const :tag "Unhide emphasis markers when point is inside or at right edge" right-edge))
+  :group 'org-appearance)
+
 (defcustom org-hide-macro-markers nil
   "Non-nil mean font-lock should hide the brackets marking macro calls."
   :group 'org-appearance
@@ -5056,12 +5069,77 @@ stacked delimiters is N.  Escaping delimiters is not possible."
 				   '(font-lock-multiline t org-emphasis t))
 	      (when (and org-hide-emphasis-markers
 			 (not (org-at-comment-p)))
-		(add-text-properties (match-end 4) (match-beginning 5)
-				     '(invisible org-link))
-		(add-text-properties (match-beginning 3) (match-end 3)
-				     '(invisible org-link)))
+		(let ((s1 (match-beginning 3))
+		      (e1 (match-end 3))
+		      (s2 (match-end 4))
+		      (e2 (match-beginning 5)))
+		  (add-text-properties s2 e2 '(invisible org-link))
+		  (add-text-properties s1 e1 '(invisible org-link))
+		  (add-text-properties s1 e2
+				       `(org-emph-start ,s1 org-emph-end ,e2))))
 	      (throw :exit t))))))))
 
+(defvar-local org-auto-emphasis--current-region-bounds nil)
+
+(defun org-auto-emphasis--get-prop-as-list (prop)
+  "Helper function to get org-auto-emphasis properties as a list.
+If `org-auto-emphasis-unhide-at-point' is set to `t' then return
+the text property PROP at point in a list. If
+`org-auto-emphasis-unhide-at-point' is set to `right-edge', the
+also include the text property PROP at point-1 unless we are at
+the beginning of the buffer."
+  (remove nil
+	  (list (get-text-property (point) prop)
+		(when (and (eq org-auto-emphasis-unhide-at-point 'right-edge)
+			   (not (bobp)))
+		  (get-text-property (1- (point)) prop)))))
+
+(defun org-auto-emphasis--post-command-hook ()
+  ;; Rehide emphasis markers for the previous region.
+  (when (and org-auto-emphasis--current-region-bounds
+	     (or (< (point) (car org-auto-emphasis--current-region-bounds))
+		 (> (point) (cadr org-auto-emphasis--current-region-bounds))
+		 (and (not (eq org-auto-emphasis-unhide-at-point 'right-edge))
+		      (= (point) (cadr org-auto-emphasis--current-region-bounds)))))
+	(apply #'font-lock-flush org-auto-emphasis--current-region-bounds)
+	(setq org-auto-emphasis--current-region-bounds nil))
+  ;; Unhide emphasis markers for the current region.
+  (when-let* ((s (org-auto-emphasis--get-prop-as-list 'org-emph-start))
+	      (e (org-auto-emphasis--get-prop-as-list 'org-emph-end))
+	      (s (apply #'min s))
+	      (e (apply #'max e)))
+    (with-silent-modifications
+      (setq org-auto-emphasis--current-region-bounds (list s e))
+      (remove-text-properties s (1+ s) '(invisible org-link))
+      (remove-text-properties (1- e) e '(invisible org-link)))))
+
+(define-minor-mode org-auto-emphasis-mode
+  "Toggle Org Auto Emphasis mode.
+This mode, when enabled, unhides emphasis markers for the region
+at point, depending on the value of
+`org-auto-emphasis-unhide-at-point'. With a prefix argument ARG,
+enable Org Auto Emphasis mode if ARG is positive, and disable it
+otherwise.  If called from Lisp, enable the mode if ARG is
+omitted or nil.
+
+To enable this in all org-mode files, add the following line to init.el:
+
+  (add-hook 'org-mode #'org-auto-emphasis-mode)
+"
+  :init-value nil
+  (if org-auto-emphasis-mode
+      ;; Turn on
+      (progn
+        (setq-local font-lock-extra-managed-props
+                    (append font-lock-extra-managed-props
+                            '(org-emph-start org-emph-end)))
+        (when org-auto-emphasis-unhide-at-point
+          (add-hook 'post-command-hook
+                    #'org-auto-emphasis--post-command-hook nil t))
+        (font-lock-flush))
+    ;; Turn off
+    (remove-hook 'post-command-hook #'org-auto-emphasis--post-command-hook t)))
+
 (defun org-emphasize (&optional char)
   "Insert or change an emphasis, i.e. a font like bold or italic.
 If there is an active region, change that region to a new emphasis.
@@ -20482,16 +20560,15 @@ With ARG, repeats or can move backward if negative."
 	   (beginning-of-line))
 	  (_ nil)))
       (cl-incf arg))
-    (while (and (> arg 0) (re-search-forward regexp nil t))
+    (while (and (> arg 0) (re-search-forward regexp nil :move))
       (pcase (get-char-property-and-overlay (point) 'invisible)
 	(`(outline . ,o)
 	 (goto-char (overlay-end o))
-	 (skip-chars-forward " \t\n")
-	 (end-of-line))
+	 (end-of-line 2))
 	(_
 	 (end-of-line)))
       (cl-decf arg))
-    (if (> arg 0) (goto-char (point-max)) (beginning-of-line))))
+    (when (/= arg initial-arg) (beginning-of-line))))
 
 (defun org-previous-visible-heading (arg)
   "Move to the previous visible heading.
@@ -20830,11 +20907,10 @@ ones already marked."
 	(set-mark
 	 (save-excursion
 	   (goto-char (mark))
-	   (goto-char (org-element-property :end (org-element-at-point)))
-	   (point)))
+	   (goto-char (org-element-property :end (org-element-at-point)))))
       (let ((element (org-element-at-point)))
 	(end-of-line)
-	(push-mark (min (point-max) (org-element-property :end element)) t t)
+	(push-mark (org-element-property :end element) t t)
 	(goto-char (org-element-property :begin element))))))
 
 (defun org-narrow-to-element ()
-- 
2.17.1


  reply	other threads:[~2020-06-01 15:33 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-01 14:14 [PATCH] Add mode for automatically unhiding emphasis markers in the current region Shankar Rao
2020-06-01 15:33 ` Shankar Rao [this message]
2020-06-22  5:40   ` Kyle Meyer
2020-06-22 11:25     ` Gustavo Barros
2020-06-23  0:07       ` Kyle Meyer
2020-06-24 12:53         ` Shankar Rao
2020-06-24 13:49           ` Gustavo Barros
2020-06-24 15:46             ` Nicolas Goaziou
2020-06-24 16:34               ` Shankar Rao
2020-06-26  7:32                 ` Nicolas Goaziou
2020-07-03 15:19                   ` Shankar Rao
2020-07-05 10:50                     ` Nicolas Goaziou
2020-07-05 20:49                       ` Gustavo Barros
2020-07-06 14:01                         ` Gustavo Barros
2020-07-07 15:57                       ` Shankar Rao
2020-06-24 17:27               ` Gustavo Barros

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAGEgU=iR6cdZ7xen=cvU-WD9GNOxh8NwuazQWa7GM8Sc3WNx2w@mail.gmail.com' \
    --to=shankar.rao@gmail.com \
    --cc=emacs-orgmode@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).