emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* [PATCH] Add mode for automatically unhiding emphasis markers in the current region
@ 2020-06-01 14:14 Shankar Rao
  2020-06-01 15:33 ` Shankar Rao
  0 siblings, 1 reply; 16+ messages in thread
From: Shankar Rao @ 2020-06-01 14:14 UTC (permalink / raw)
  To: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 7251 bytes --]

* 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 #2: Type: text/html, Size: 8382 bytes --]

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add mode for automatically unhiding emphasis markers in the current region
  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
  2020-06-22  5:40   ` Kyle Meyer
  0 siblings, 1 reply; 16+ messages in thread
From: Shankar Rao @ 2020-06-01 15:33 UTC (permalink / raw)
  To: emacs-orgmode


[-- 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


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add mode for automatically unhiding emphasis markers in the current region
  2020-06-01 15:33 ` Shankar Rao
@ 2020-06-22  5:40   ` Kyle Meyer
  2020-06-22 11:25     ` Gustavo Barros
  0 siblings, 1 reply; 16+ messages in thread
From: Kyle Meyer @ 2020-06-22  5:40 UTC (permalink / raw)
  To: Shankar Rao; +Cc: emacs-orgmode

Thanks for the patch, and sorry for the slow reply.

Shankar Rao writes:

> 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.

Inline is fine as well, though it can take a little more work on the
sender's end to make sure that the patch doesn't get mangled by their
mail client and that the commit message is formatted correctly.

> 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.

I don't prefer my emphasis markers hidden (i.e. I leave
org-hide-emphasis-markers at nil), so perhaps I'm not the best to judge,
but that does sound like a nice feature.

I'm hoping others will try this out and give their thoughts.

> On Mon, Jun 1, 2020 at 4:14 PM Shankar Rao <shankar.rao@gmail.com> wrote:
[...]
>>
>> 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.

Are you still waiting for a response?

> Subject: [PATCH] Add mode for automatically unhiding emphasis markers in the
>  current region
[...]
>  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

Note that this no longer applies to the current master due to a conflict
with b68090e0b (2020-06-04).  I applied this to b68090e0b^ to try this
out, and it seems to work as advertised.

Here are some comments from an initial read-through.

> --- 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.

s/show the// ?

Also, I find using "region" here (and elsewhere) a little confusing.
Perhaps something like "unhide the emphasis markers for the text at
point" instead?

> +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"

This can instead be

    :package-version '(Org . "9.5")

Emacs can then use customize-package-emacs-version-alist to map to the
Emacs version.

(The next release will be v9.4, but we're in a feature freeze at the
moment.)

> +  :type '(choice (const :tag "Never unhide emphasis markers" nil)

Hmm, I don't see the point of having a nil value.  That already seems
covered by toggling org-auto-emphasis-mode on and off.

I also wonder whether we can get away with not having an option here at
all.  Is one of the below values more likely to be the predominant
preference?

> +                 (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))

IMO these descriptions could be more concise but as clear by dropping
"emphasis markers" from the t and right-edge items.

> +(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

convention nit: Drop quotes from t.

> +(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))

Our minimum supported Emacs version is 24.3, so we can't rely on
when-let and friends being available.

> +(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:

nit: s/org-mode/Org/

> +
> +  (add-hook 'org-mode #'org-auto-emphasis-mode)

You should protect the apostrophes as \\=' so that they aren't rendered
according to text-quoting-style.

>  (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))))

Can you explain why this change to org-next-visible-heading and...

>  
>  (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))))))

... this change to org-mark-element are related/needed?


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add mode for automatically unhiding emphasis markers in the current region
  2020-06-22  5:40   ` Kyle Meyer
@ 2020-06-22 11:25     ` Gustavo Barros
  2020-06-23  0:07       ` Kyle Meyer
  0 siblings, 1 reply; 16+ messages in thread
From: Gustavo Barros @ 2020-06-22 11:25 UTC (permalink / raw)
  To: Kyle Meyer; +Cc: emacs-orgmode, Shankar Rao


Hi Kyle, Hi Shankar,

On Mon, 22 Jun 2020 at 05:40, Kyle Meyer <kyle@kyleam.com> wrote:

> Shankar Rao writes:
>
>> 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.
>
> I don't prefer my emphasis markers hidden (i.e. I leave
> org-hide-emphasis-markers at nil), so perhaps I'm not the best to judge,
> but that does sound like a nice feature.
>
> I'm hoping others will try this out and give their thoughts.

Just an user here, but I'd like to leave my +1 to this proposed feature.
I did use org-hide-emphasis-markers in the past and I liked it, but
eventually dropped it because of the inconveniences of editing at the
border of an emphasized region.  This proposed feature eliminates the
"which side of the invisible character are we?" ambiguity, so I repute
it very nice indeed.  I would certainly appreciate the inclusion of such
a feature and, since I've been around, I've seen folks demanding
something of the sort (memory here, no hard data).  Indeed, I was one of
the people at Reddit who suggested Shankar submitted this to the list.

I did (lightly) test the code as posted on Reddit, and liked what I
saw.  I tried a number of cases I could think of: multiple lines, nested
emphasis markers etc.  As far as I tried, it did work as advertised.

I also did report a corner case I found:

> The only edge case I found, which in no way mars the absolute coolness
> of this, is when you are actually inserting the emphasis marker. For
> example, if you type *word*. Right after you type the last "*" the
> emphasis will be hidden, even though the point position would have it to
> be shown. Same thing if you select word and "C-c C-x C-f *". You have to
> actually move point, for the mode to work in this situation.

Shankar replied me this behavior is the same in prettify-symbols-mode,
on which the code is based.  I do not use prettify-symbols-mode myself,
but did play with it a little because of this, and could not infer a
regularity, so I must trust Shankar's point here.  And it is indeed just
a corner situation, which has no further implication I can conceive, and
which does not diminish the usefulness of the feature.

I can add another thought on the matter.  While prettify-symbols is a
mode, org-hide-emphasis-markers is an option/variable.  So I wonder if
the feature would fit better the current state of things in Org as
either another option/defcustom or by simply expanding the range of
possible values for org-hide-emphasis-markers (e.g. t, nil,
not-at-point, not-at-point-right-edge).  But this is just a thought, I'd
be happy to see this feature be included either way.

So, thanks Shankar for proposing the patch, and thanks Kyle for
reviewing it.

HTH.
Best,
Gustavo.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add mode for automatically unhiding emphasis markers in the current region
  2020-06-22 11:25     ` Gustavo Barros
@ 2020-06-23  0:07       ` Kyle Meyer
  2020-06-24 12:53         ` Shankar Rao
  0 siblings, 1 reply; 16+ messages in thread
From: Kyle Meyer @ 2020-06-23  0:07 UTC (permalink / raw)
  To: Gustavo Barros; +Cc: emacs-orgmode, Shankar Rao

Gustavo Barros writes:

> Just an user here, but I'd like to leave my +1 to this proposed feature.
> [...]

Thanks.  That's very useful feedback.

> I can add another thought on the matter.  While prettify-symbols is a
> mode, org-hide-emphasis-markers is an option/variable.  So I wonder if
> the feature would fit better the current state of things in Org as
> either another option/defcustom or by simply expanding the range of
> possible values for org-hide-emphasis-markers (e.g. t, nil,
> not-at-point, not-at-point-right-edge).  But this is just a thought, I'd
> be happy to see this feature be included either way.

Hmm, yeah, that's worth thinking about.  I mentioned eliminating the
org-auto-emphasis-unhide-at-point option, but I didn't consider doing it
by absorbing the values into org-hide-emphasis-markers and dropping the
mode.  Given what org-auto-emphasis-mode does underneath, though, it
does fit quite neatly into a minor mode toggle.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add mode for automatically unhiding emphasis markers in the current region
  2020-06-23  0:07       ` Kyle Meyer
@ 2020-06-24 12:53         ` Shankar Rao
  2020-06-24 13:49           ` Gustavo Barros
  0 siblings, 1 reply; 16+ messages in thread
From: Shankar Rao @ 2020-06-24 12:53 UTC (permalink / raw)
  To: Kyle Meyer; +Cc: emacs-orgmode, Gustavo Barros


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

Kyle, Gustavo,

Thank you both for your detailed feedback. Attached is a new version of the
patch that incorporates most of your suggestions.

>> 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.
>
> Are you still waiting for a response?
>
I received an assignment form from the FSF and I just now signed it and
sent it back to them.

> +  :type '(choice (const :tag "Never unhide emphasis markers" nil)
>
> Hmm, I don't see the point of having a nil value.  That already seems
> covered by toggling org-auto-emphasis-mode on and off.
>
> I also wonder whether we can get away with not having an option here at
> all.  Is one of the below values more likely to be the predominant
> preference?
>
This mimics the behavior of prettify-symbols-mode.
org-auto-emphasis-unhide-at-point and org-auto-emphasis-mode correspond to
prettify-symbols-unprettify-at-point and global-prettify-symbols-mode,
respectively. So in the same way, one could enable prettify-symbols-mode
globally with (global-prettify-symbols-mode +1) and also have (setq
prettify-symbols-unprettify-at-point nil), which would effectively still
keep it disabled.

I'm amenable to simplifying or eliminating the option entirely. In my use I
find the 'right-edge setting to be more useful that the t setting, but the
behavior for t might be more intuitive to users. If I had to pick one
option, I would choose 'right-edge.

> I can add another thought on the matter.  While prettify-symbols is a
> > mode, org-hide-emphasis-markers is an option/variable.  So I wonder if
> > the feature would fit better the current state of things in Org as
> > either another option/defcustom or by simply expanding the range of
> > possible values for org-hide-emphasis-markers (e.g. t, nil,
> > not-at-point, not-at-point-right-edge).  But this is just a thought, I'd
> > be happy to see this feature be included either way.
>
> Hmm, yeah, that's worth thinking about.  I mentioned eliminating the
> org-auto-emphasis-unhide-at-point option, but I didn't consider doing it
> by absorbing the values into org-hide-emphasis-markers and dropping the
> mode.  Given what org-auto-emphasis-mode does underneath, though, it
> does fit quite neatly into a minor mode toggle.
>
I agree that adding this functionality as additional options to
org-hide-emphasis-markers would be more intuitive and elegant for users, as
they wouldn't have to perform  (add-hook 'org-mode
#'org-auto-emphasis-mode) in order to enable this mode. I didn't implement
it this way first because I wanted to make the simplest, least disruptive
way possible, and secondly because I didn't quite know how to implement it
:-). As you can see in the patch, besides the additional functions and
variables, my code only modifies one preexisting org function, replacing
four lines with my new eight lines.

To implement this functionality in the way Gustavo suggests, we would have
to for all users add org-auto-emphasis--post-command-hook to
post-command-hook, and modify it so that it only operates when
org-hide-emphasis-markers is 'not-at-point or 'not-at-point-right-edge. I
can try to implement this if you think it would be a good idea, but I have
one concern. Even if a user is not interested in org-auto-emphasis-mode,
this implementation would add a small amount of code to post-command-hook,
so would have the effect of slightly slowing down their system.

Shankar

On Tue, Jun 23, 2020 at 2:07 AM Kyle Meyer <kyle@kyleam.com> wrote:

> Gustavo Barros writes:
>
> > Just an user here, but I'd like to leave my +1 to this proposed feature.
> > [...]
>
> Thanks.  That's very useful feedback.
>
> > I can add another thought on the matter.  While prettify-symbols is a
> > mode, org-hide-emphasis-markers is an option/variable.  So I wonder if
> > the feature would fit better the current state of things in Org as
> > either another option/defcustom or by simply expanding the range of
> > possible values for org-hide-emphasis-markers (e.g. t, nil,
> > not-at-point, not-at-point-right-edge).  But this is just a thought, I'd
> > be happy to see this feature be included either way.
>
> Hmm, yeah, that's worth thinking about.  I mentioned eliminating the
> org-auto-emphasis-unhide-at-point option, but I didn't consider doing it
> by absorbing the values into org-hide-emphasis-markers and dropping the
> mode.  Given what org-auto-emphasis-mode does underneath, though, it
> does fit quite neatly into a minor mode toggle.
>

---
 lisp/org.el | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 83 insertions(+), 4 deletions(-)

diff --git a/lisp/org.el b/lisp/org.el
index 4d46b4173..8bab33ec0 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 text at point.
+If set to the symbol `right-edge', also unhide the emphasis
+markers if point is immediately after the emphasized text.  The
+emphasis markers will be rehidden as soon as point moves away
+from the emphasized text.  If set to nil, the emphasis markers
+always remain hidden."
+  :package-version '(Org . "9.5")
+  :type '(choice (const :tag "Never unhide emphasis markers" nil)
+                 (const :tag "Unhide when point is inside" t)
+                 (const :tag "Unhide 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
@@ -5055,12 +5068,78 @@ 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.
+  (let* ((s (org-auto-emphasis--get-prop-as-list 'org-emph-start))
+ (e (and s (org-auto-emphasis--get-prop-as-list 'org-emph-end)))
+ (s (and e (apply #'min s)))
+ (e (and s (apply #'max e))))
+    (when 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 text
+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 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.
-- 
2.17.1

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

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

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add mode for automatically unhiding emphasis markers in the current region
  2020-06-24 12:53         ` Shankar Rao
@ 2020-06-24 13:49           ` Gustavo Barros
  2020-06-24 15:46             ` Nicolas Goaziou
  0 siblings, 1 reply; 16+ messages in thread
From: Gustavo Barros @ 2020-06-24 13:49 UTC (permalink / raw)
  To: Shankar Rao; +Cc: emacs-orgmode

Hi Shankar,

Detailed comments are up for Kyle, or someone more qualified than 
myself, but I leave one further comment regarding the suggestion I had 
made.

On Wed, 24 Jun 2020 at 09:53, Shankar Rao <shankar.rao@gmail.com> wrote:

> I agree that adding this functionality as additional options to
> org-hide-emphasis-markers would be more intuitive and elegant for 
> users, as
> they wouldn't have to perform  (add-hook 'org-mode
> #'org-auto-emphasis-mode) in order to enable this mode. I didn't 
> implement
> it this way first because I wanted to make the simplest, least 
> disruptive
> way possible, and secondly because I didn't quite know how to 
> implement it
> :-). As you can see in the patch, besides the additional functions and
> variables, my code only modifies one preexisting org function, 
> replacing
> four lines with my new eight lines.
>
> To implement this functionality in the way Gustavo suggests, we would 
> have
> to for all users add org-auto-emphasis--post-command-hook to
> post-command-hook, and modify it so that it only operates when
> org-hide-emphasis-markers is 'not-at-point or 
> 'not-at-point-right-edge. I
> can try to implement this if you think it would be a good idea, but I 
> have
> one concern. Even if a user is not interested in 
> org-auto-emphasis-mode,
> this implementation would add a small amount of code to 
> post-command-hook,
> so would have the effect of slightly slowing down their system.

You have a good point here.  When I made the suggestion I was naively 
thinking the featured could be plugged/hooked somewhere in Org, when 
fontification is done.  But that's not really true, as the feature 
requires being run every time the point moves too.  So, as far as I can 
tell, it seems using post-command-hook is unavoidable, and if so, you 
are right in not wanting to add some load to it for everyone, regardless 
of whether they want this feature or not.  You and Kyle have me 
convinced here.

And thanks again!

Best,
Gustavo.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add mode for automatically unhiding emphasis markers in the current region
  2020-06-24 13:49           ` Gustavo Barros
@ 2020-06-24 15:46             ` Nicolas Goaziou
  2020-06-24 16:34               ` Shankar Rao
  2020-06-24 17:27               ` Gustavo Barros
  0 siblings, 2 replies; 16+ messages in thread
From: Nicolas Goaziou @ 2020-06-24 15:46 UTC (permalink / raw)
  To: Gustavo Barros; +Cc: emacs-orgmode, Shankar Rao

Hello,

Gustavo Barros <gusbrs.2016@gmail.com> writes:

> You have a good point here.  When I made the suggestion I was naively
> thinking the featured could be plugged/hooked somewhere in Org, when
> fontification is done.  But that's not really true, as the feature
> requires being run every time the point moves too.  So, as far as
> I can tell, it seems using post-command-hook is unavoidable, and if
> so, you are right in not wanting to add some load to it for everyone,
> regardless of whether they want this feature or not.  You and Kyle
> have me convinced here.

Sorry for being late to the party, but, IMO, this doesn't sound like
a right approach to the problem of invisible emphasis markers. A user
choosing to hide emphasis markers should not need to—or even be given
the opportunity to—display them in order to edit them efficiently.

I think we should upgrade `org-emphasize' command instead, so it handles
both marker visibility states in a DWIM, or in a word processor,
fashion. Indeed, since emphasis markers of a given type cannot be nested
in Org, the WIM part is usually easy to guess, according to the context,
i.e., the syntax at point, and the region. I have some draft lying
somewhere in that direction.

WDYT?

Regards,
-- 
Nicolas Goaziou


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add mode for automatically unhiding emphasis markers in the current region
  2020-06-24 15:46             ` Nicolas Goaziou
@ 2020-06-24 16:34               ` Shankar Rao
  2020-06-26  7:32                 ` Nicolas Goaziou
  2020-06-24 17:27               ` Gustavo Barros
  1 sibling, 1 reply; 16+ messages in thread
From: Shankar Rao @ 2020-06-24 16:34 UTC (permalink / raw)
  To: Gustavo Barros, Shankar Rao, emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 735 bytes --]

> Sorry for being late to the party, but, IMO, this doesn't sound like
> a right approach to the problem of invisible emphasis markers. A user
> choosing to hide emphasis markers should not need to—or even be given
> the opportunity to—display them in order to edit them efficiently.
>

I agree that if org-emphasize handled marker visibility states in a DWIM
fashion, then a user should not need to display them, but why do you
believe they shouldn't have the opportunity, especially given that this is
the exact behavior of prettify-symbols-mode?

Could you walk me through, in your proposed DWIM system, how a user should
be able to remove or change emphasis markers after they are rendered and
hidden?

Shankar

[-- Attachment #2: Type: text/html, Size: 1005 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add mode for automatically unhiding emphasis markers in the current region
  2020-06-24 15:46             ` Nicolas Goaziou
  2020-06-24 16:34               ` Shankar Rao
@ 2020-06-24 17:27               ` Gustavo Barros
  1 sibling, 0 replies; 16+ messages in thread
From: Gustavo Barros @ 2020-06-24 17:27 UTC (permalink / raw)
  To: Nicolas Goaziou; +Cc: emacs-orgmode, Shankar Rao

Hi Nicolas,

On Wed, 24 Jun 2020 at 12:46, Nicolas Goaziou <mail@nicolasgoaziou.fr> 
wrote:

> Hello,
>
> Gustavo Barros <gusbrs.2016@gmail.com> writes:
>
>> You have a good point here.  When I made the suggestion I was naively
>> thinking the featured could be plugged/hooked somewhere in Org, when
>> fontification is done.  But that's not really true, as the feature
>> requires being run every time the point moves too.  So, as far as
>> I can tell, it seems using post-command-hook is unavoidable, and if
>> so, you are right in not wanting to add some load to it for everyone,
>> regardless of whether they want this feature or not.  You and Kyle
>> have me convinced here.
>
> Sorry for being late to the party, but, IMO, this doesn't sound like
> a right approach to the problem of invisible emphasis markers. A user
> choosing to hide emphasis markers should not need to—or even be given
> the opportunity to—display them in order to edit them efficiently.
>

I do agree with what you said, as you have stated it: It'd be good if 
the user of `org-hide-emphasis-markers' didn't need to display the 
invisible character to edit them efficiently.  And it is true that I 
argued in favor of this proposed patch giving the related editing 
inconveniences as a main point.  But the feature is the equivalent of 
`prettify-symbols-unprettify-at-point' for `org-hide-emphasis-markers' 
and it does have an appeal in itself, for the visual cue it offers, 
besides the editing improvement, which is a byproduct.  I like 
`org-hide-emphasis-markers', but if I was not "given the opportunity to 
display them" or if I could not edit them directly even if invisible, as 
a word processor does, I would probably not consider ever hiding them in 
the first place.

> I think we should upgrade `org-emphasize' command instead, so it 
> handles
> both marker visibility states in a DWIM, or in a word processor,
> fashion. Indeed, since emphasis markers of a given type cannot be 
> nested
> in Org, the WIM part is usually easy to guess, according to the 
> context,
> i.e., the syntax at point, and the region. I have some draft lying
> somewhere in that direction.
>
> WDYT?

I think that it would be great independently of the proposed patch. 
Indeed, that would be very useful including for users which set 
`org-hide-emphasis-markers' to nil.  On the other hand, even with a more 
capable dwim `org-empasize', I'm pretty sure many users will still add 
emphasis markers by directly typing them, even if occasionally, or they 
will delete them inadvertently if invisible, in which case, the proposed 
patch remains very useful for this reason too.

If I may, `TeX-font' in AUCTeX would be my dream `org-emphasize'.  Two 
things it does that `org-emphasize' doesn't (as far as I know of): i) 
when there is no region selected, and point is within a font macro, it 
operates on the imediate enclosing font macro, not requiring region 
selection, so that we can change the font macro by calling `TeX-font' 
with a prefix, or remove the font macro with "C-c C-f C-d"; ii) 
`LaTeX-font-list' is customizable, allowing for better key bindings; 
it's easier to type "b" than "*", "s" than "+" etc., anyway, it gives 
choice.

Again, just an user here, just offering a data point.  (And I was quoted 
;-).

Best,
Gustavo.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add mode for automatically unhiding emphasis markers in the current region
  2020-06-24 16:34               ` Shankar Rao
@ 2020-06-26  7:32                 ` Nicolas Goaziou
  2020-07-03 15:19                   ` Shankar Rao
  0 siblings, 1 reply; 16+ messages in thread
From: Nicolas Goaziou @ 2020-06-26  7:32 UTC (permalink / raw)
  To: Shankar Rao; +Cc: emacs-orgmode, Gustavo Barros

Hello,

Shankar Rao <shankar.rao@gmail.com> writes:

> I agree that if org-emphasize handled marker visibility states in a DWIM
> fashion, then a user should not need to display them, but why do you
> believe they shouldn't have the opportunity, especially given that this is
> the exact behavior of prettify-symbols-mode?

I wrote my message in a hurry. Let me clarify it.

I'm only talking about built-in tooling. I don't mind if a user have the
feature you're proposing, of course, as it is not wrong per se.

However, I believe that's not the best solution for the problem we're
trying to solve. I think there's an opportunity to provide something
smarter, and less intrusive, to handle emphasis, which doesn't involve
messing with `post-command-hook'.

> Could you walk me through, in your proposed DWIM system, how a user should
> be able to remove or change emphasis markers after they are rendered and
> hidden?

Like in a word processor, you don't need to see the markers to operate
on them. I don't think the usual "toggle" model is appropriate, however.
I suggest to use two commands: one for deleting the markers around point
or within active region, and one for inserting markers or extending
existing ones.

Allow me to polish up my draft a bit, so we can compare the benefits of
each system.

Regards,
-- 
Nicolas Goaziou


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add mode for automatically unhiding emphasis markers in the current region
  2020-06-26  7:32                 ` Nicolas Goaziou
@ 2020-07-03 15:19                   ` Shankar Rao
  2020-07-05 10:50                     ` Nicolas Goaziou
  0 siblings, 1 reply; 16+ messages in thread
From: Shankar Rao @ 2020-07-03 15:19 UTC (permalink / raw)
  To: Shankar Rao, Gustavo Barros, emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 1990 bytes --]

Hi,

I wrote my message in a hurry. Let me clarify it.
>
> I'm only talking about built-in tooling. I don't mind if a user have the
> feature you're proposing, of course, as it is not wrong per se.
>
> However, I believe that's not the best solution for the problem we're
> trying to solve. I think there's an opportunity to provide something
> smarter, and less intrusive, to handle emphasis, which doesn't involve
> messing with `post-command-hook'.
>

I agree with you that my solution is somewhat intrusive. Ideally, I would
have preferred that my solution could leverage advice functions or some Org
hook, so that I wouldn't have to modify org.el, but it doesn't seem like
there is a straightforward way to do that. The modification of
`post-command-hook', similar to one used for `prettify-symbols-mode', only
occurs if `org-auto-emphasis-mode' is active


> Like in a word processor, you don't need to see the markers to operate
> on them. I don't think the usual "toggle" model is appropriate, however.
> I suggest to use two commands: one for deleting the markers around point
> or within active region, and one for inserting markers or extending
> existing ones.
>
So in your system, in order to interact with emphasis markers, the user
would have to learn two different commands? That doesn't seem to be in line
with the dwim philosophy used in modern emacs packages.

In my opinion, one of the strengths of Org is that the interface is
multimodal. One can (in principle) edit documents in much the same way as
word processors and rich text editors. However since everything underneath
is implemented with just text, one can also directly access and manipulate
this text. The ability to switch between these two modalities is extremely
powerful and is what sets Org apart from other document editing systems.


> Allow me to polish up my draft a bit, so we can compare the benefits of
> each system.
>

I look forward to seeing your proposed system more concretely.

Shankar Rao

[-- Attachment #2: Type: text/html, Size: 2739 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add mode for automatically unhiding emphasis markers in the current region
  2020-07-03 15:19                   ` Shankar Rao
@ 2020-07-05 10:50                     ` Nicolas Goaziou
  2020-07-05 20:49                       ` Gustavo Barros
  2020-07-07 15:57                       ` Shankar Rao
  0 siblings, 2 replies; 16+ messages in thread
From: Nicolas Goaziou @ 2020-07-05 10:50 UTC (permalink / raw)
  To: Shankar Rao; +Cc: emacs-orgmode, Gustavo Barros

Hello,

Shankar Rao <shankar.rao@gmail.com> writes:

> I agree with you that my solution is somewhat intrusive. Ideally, I would
> have preferred that my solution could leverage advice functions or some Org
> hook, so that I wouldn't have to modify org.el, but it doesn't seem like
> there is a straightforward way to do that. The modification of
> `post-command-hook', similar to one used for `prettify-symbols-mode', only
> occurs if `org-auto-emphasis-mode' is active

The problem is not your implementation, really. It's just that I don't
think it should be the _built-in_ way to solve emphasis management. IOW,
we shouldn't need to activate a minor mode to make that management
tolerable in the first place.

However, I agree that it makes senses as an extension, in the same vein
as `org-fragtog` for LaTeX fragments.

> So in your system, in order to interact with emphasis markers, the user
> would have to learn two different commands? That doesn't seem to be in line
> with the dwim philosophy used in modern emacs packages.

Two different commands? Bah! The change I suggest introduces 7 new
commands and 12 new bindings! :)

Yet, I claim it is still (somewhat) intuitive.

> In my opinion, one of the strengths of Org is that the interface is
> multimodal. One can (in principle) edit documents in much the same way as
> word processors and rich text editors. However since everything underneath
> is implemented with just text, one can also directly access and manipulate
> this text. The ability to switch between these two modalities is extremely
> powerful and is what sets Org apart from other document editing
> systems.

You can always toggle `visible-mode' for that.

But, really, I think an option like `org-hide-emphasis-markers' is
a one-off toggle. Having to, in a way, switch regularly between two
values is sub-optimal.

> I look forward to seeing your proposed system more concretely.

Here it is. 

The main command is `org-emphasis'. It emphasizes the minimal possible
area around point, or region. If there's already an emphasis object of
the desired type around point or region, it extends it forward instead.
With a prefix argument, it removes the emphasis.

Interactively, the command asks for the type of emphasis to use, but
I suggest to use dedicated commands instead. Thus, I added a key-binding
for each of the six emphasis types. For example, for bold, use

      `M-o *'    or    `M-o M-*'

There are equivalent commands for underline (`M-o _` or `M-o M-_'), and
so on.

Note there, even though I polished it, there are probably some glitches
left, but it works well enough to give an idea. Tests are missing, too.

Please evaluate the following code to try it.

--8<---------------cut here---------------start------------->8---
(defun org--emphasis-flatten-region (begin end parent)
  "Find minimal region around BEGIN and END with boundaries at the same level.

PARENT is the parent element containing both BEGIN and END.

Return a list

  (B E CONTEXT)

where B and E are, respectively, the start and the end of the smallest region
containing BEGIN and END, but with a guaranteed common parent object or element
CONTEXT."
  (let ((context-beg (org-with-point-at begin (org-element-context parent))))
    ;; Find common container.
    (when (/= begin end)
      (let ((context-end (org-with-point-at end (org-element-context parent))))
        (while (>= end (org-element-property :end context-beg))
          (setq begin (org-element-property :begin context-beg))
          (setq context-beg (org-element-property :parent context-beg)))
        (while (< begin (org-element-property :begin context-end))
          (goto-char (org-element-property :end context-end))
          (skip-chars-backward " \n\t")
          (setq end (point))
          (setq context-end (org-element-property :parent context-end)))))
    ;; Make sure that we do not end up with one boundary inside the
    ;; common context, and the other boundary outside of it. Also move
    ;; out of objects that cannot contain emphasis (e.g., bold).
    (when (or (not (memq 'bold (org-element-restriction context-beg)))
              (< begin (org-element-property :contents-begin context-beg))
              (> end (org-element-property :contents-end context-beg)))
      (setq begin (org-element-property :begin context-beg))
      (goto-char (org-element-property :end context-beg))
      (skip-chars-backward " \n\t")
      (setq end (point)))
    ;; Return value.
    (list begin end context-beg)))

(defun org--emphasis-extend-region (begin end parent type)
  "Return smallest area extending emphasis between BEGIN and END.

PARENT is an element, as returned by `org-element-at-point'. The
function assumes PARENT contents include both BEGIN and END
positions.

TYPE is emphasis type being extended, as a symbol `bold', `code',
`italic', `strike-through', `underline', and `verbatim'.

Return nil if there is no possible location for the emphasis
markup. Otherwise, return (A . B) where A and B are buffer
positions where emphasis markers can be inserted."
  (org-with-wide-buffer
   ;; Skip any white space so that the command marks the following
   ;; word, à la `mark-word'.
   (let ((limit (org-element-property :contents-end parent)))
     (goto-char begin)
     (skip-chars-forward " \t\n" limit)
     (setq begin (and (> limit (point)) (point))))
   ;; At the end of the element, there is nothing to emphasize, so
   ;; bail out.
   (when begin
     (goto-char end)
     (skip-chars-backward " \t\n" begin)
     (setq end (max begin (point)))
     (pcase (org--emphasis-flatten-region begin end parent)
       (`(,new-begin ,new-end ,context)
        ;; Special case: when there's an emphasis object of the
        ;; desired type around the area we're interested in, drop the
        ;; area and extend the object instead.
        (let ((emphasis (org-element-lineage context (list type) t)))
          (when emphasis
            (setq context (org-element-property :parent emphasis))
            (setq new-begin (org-element-property :begin emphasis))
            ;; Force extending after the object only, if possible.
            (setq new-end
                  (and (< (org-element-property :end emphasis)
                          (org-with-point-at
                              (org-element-property :contents-end context)
                            (skip-chars-backward " \t\n")
                            (point)))
                       (1+ (org-element-property :end emphasis))))
            (setq begin 0)
            (setq end new-end)))
        (when (= begin new-begin)
          ;; Find an acceptable BEGIN position for the opening
          ;; emphasis marker. It must be located after an appropriate
          ;; prefix, but not before a white space. We repeatedly try
          ;; to find such a location.
          (let* ((limit (org-element-property :contents-begin context))
                 (prefix-re "-\"'({[:space:]")
                 (non-prefix-re (concat "^" prefix-re)))
            (goto-char new-begin)
            (skip-chars-backward non-prefix-re limit)
            (while (eq ?\s (char-syntax (char-after))) ;invalid border
              (skip-chars-backward prefix-re limit)
              (skip-chars-backward non-prefix-re limit)))
          (setq new-begin (point)))
        (when (and new-end (= end new-end))
          ;; Find an acceptable END position for the closing emphasis
          ;; marker. It must be located between a non-space character
          ;; and an appropriate suffix. We look for the next position
          ;; before the suffix, and check if there is no space behind.
          ;; Rinse and repeat.
          (let* ((limit (org-element-property :contents-end context))
                 (suffix-re "-[:space:]!\"',.:;?)}\\[")
                 (non-suffix-re (concat "^" suffix-re)))
            (goto-char new-end)
            (skip-chars-forward non-suffix-re limit)
            (while (eq ?\s (char-syntax (char-before))) ;invalid border
              (skip-chars-forward suffix-re limit)
              (skip-chars-forward non-suffix-re limit)))
          (setq new-end (point)))
        ;; Return value.
        (and new-begin new-end (cons new-begin new-end)))
       (other
        (error "Invalid return value for `org--emphasis-flatten-region': %S"
        other))))))

(defun org--emphasis-clean-markup (type beg end)
  "Remove all emphasis of type TYPE between BEG and END.

TYPE is a symbol among `bold', `code', `italic', `strike-through',
`underline', and `verbatim'.

The function assumes BEG and END both belong to the same element."
  (save-restriction
    (narrow-to-region beg end)
    (save-excursion
      ;; Remove markup in reverse order so object boundaries are still
      ;; accurate after each buffer modification.
      (dolist (o (reverse (org-element-map (org-element-parse-buffer) type
                            #'identity)))
        (goto-char (org-element-property :end o))
        (skip-chars-backward " \t")
        (delete-char -1)
        (goto-char (org-element-property :begin o))
        (delete-char 1)))))

(defun org--emphasis-container (begin end)
  "Return element around BEGIN and END possibly containing emphasis.
Return nil if there is no such element."
  (org-with-point-at begin
    (let ((element (org-element-at-point)))
      (pcase (org-element-type element)
        ;; XXX: Item's tag and headline title can contain emphasis.
        ;; However, other places in these elements cannot. If BEGIN
        ;; and END are located appropriately, return a fake element
        ;; limiting contents to the tag or the title.
        ((or `headline `inlinetask `item)
         (when (and (or (org-match-line org-complex-heading-regexp)
                        (org-match-line org-list-full-item-re))
                    (org-string-nw-p (match-string 4))
                    (org-pos-in-match-range begin 4)
                    (org-pos-in-match-range end 4))
           (let ((new (org-element-copy element)))
             (org-element-put-property new :contents-begin (match-beginning 4))
             (goto-char (match-end 4))
             (skip-chars-backward " \t")
             (org-element-put-property new :contents-end (point))
             new)))
        (type
         (and (memq type org-element-object-containers)
              (>= begin (org-element-property :contents-begin element))
              (<= end (org-element-property :contents-end element))
              element))))))

(defun org-emphasis (&optional arg type)
  "Apply or remove emphasis at point, or in region.

Emphasize minimal area around region or point.  If the area is already
emphasized, extend it forward.  In that case, point is left within the
emphasis.

When called with an universal prefix argument, remove emphasis
around and within region instead.

When called interactively, ask for the type of emphasis to apply or remove.
When optional argument TYPE is provided, use that emphasis type instead."
  (interactive "P")
  ;; Make sure to consider the next non-white character (or end of
  ;; line, since we don't want to move out of the current element).
  (let* ((region? (org-region-active-p))
         (region-start (and region? (region-beginning)))
         (region-end (and region? (region-end)))
         (begin
          (progn
            (goto-char (or region-start (point)))
            (skip-chars-forward " \t")
            (point)))
         (end (max begin (or region-end (point))))
         (parent (org--emphasis-container begin end)))
    (unless parent (user-error "Cannot emphasize contents here"))
    ;; Now proceed according to ARG.
    (let* ((type
            (pcase (or type (read-char "Choose emphasis [*~/+_=]: "))
              ((or ?* `bold) 'bold)
              ((or ?~ `code) 'code)
              ((or ?/ `italic) 'italic)
              ((or ?+ `strike-through) 'strike-through)
              ((or ?_ `underline) 'underline)
              ((or ?= `verbatim) 'verbatim)
              (answer (user-error "Unknown markup type: %S" answer))))
           (markup
            (pcase type
              (`bold ?*) (`code ?~) (`italic ?/) (`strike-through ?+)
              (`underline ?_) (_ ?=))))
      (pcase arg
        ;; No argument: insert emphasis markers.
        (`nil
         (pcase (org--emphasis-extend-region begin end parent type)
           (`nil
            (user-error
             (if (org-element-lineage (org-element-context parent) (list type) t)
                 "Cannot extend emphasis further"
               "Nothing to emphasize in the region")))
           (`(,begin . ,end)
            (if (and (or (< begin (point-min)) (> end (point-max)))
                     (not (yes-or-no-p "Insert markers outside visible part \
of buffer? ")))
                (message "Emphasis markup insertion aborted")
              ;; First delete all markup, then insert new one. The
              ;; first action modifies buffer, so we store insertion
              ;; location in markers.
              ;;
              ;; Also, pay attention to the final position, which
              ;; should always end within new markers.
              (let ((begin-marker (copy-marker begin))
                    (end-marker (copy-marker end))
                    (origin (point-marker)))
                (org--emphasis-clean-markup type begin end)
                (org-with-point-at origin
                  (goto-char end-marker)
                  (insert markup)
                  (goto-char begin-marker)
                  (insert-before-markers markup))
                (set-marker begin-marker nil)
                (set-marker end-marker nil)
                (set-marker origin nil))))
           (value (error "Invalid return value %S" value))))
        ;; Non-nil argument: remove emphasis markers.
        (_
         (pcase (org--emphasis-flatten-region begin end parent)
           (`(,begin ,end ,context)
            (let ((emphasis (org-element-lineage context (list type) t)))
              (if (not emphasis)
                  (org--emphasis-clean-markup type begin end)
                ;; We're already within emphasis object of the desired
                ;; type: delete it.
                (org-with-point-at (org-element-property :end emphasis)
                  (skip-chars-backward " \t")
                  (delete-char -1))
                (org-with-point-at (org-element-property :begin emphasis)
                  (delete-char 1)))))
           (other
            (error "Unknown return value for `org--emphasis-flatten-region': %S"
                   other))))))))

(defun org-emphasis-bold (&optional arg)
  "Emphasize area around point or region with bold markup.
When optional argument ARG is non-nil, remove such markup
instead."
  (interactive "P")
  (org-emphasis arg 'bold))

(defun org-emphasis-code (&optional arg)
  "Emphasize area around point or region with code markup.
When optional argument ARG is non-nil, remove such markup
instead."
  (interactive "P")
  (org-emphasis arg 'code))

(defun org-emphasis-italic (&optional arg)
  "Emphasize area around point or region with italic markup.
When optional argument ARG is non-nil, remove such markup
instead."
  (interactive "P")
  (org-emphasis arg 'italic))

(defun org-emphasis-strike-through (&optional arg)
  "Emphasize area around point or region with strike-through markup.
When optional argument ARG is non-nil, remove such markup
instead."
  (interactive "P")
  (org-emphasis arg 'strike-through))

(defun org-emphasis-underline (&optional arg)
  "Emphasize area around point or region with underline markup.
When optional argument ARG is non-nil, remove such markup
instead."
  (interactive "P")
  (org-emphasis arg 'underline))

(defun org-emphasis-verbatim (&optional arg)
  "Emphasize area around point or region with verbatim markup.
When optional argument ARG is non-nil, remove such markup
instead."
  (interactive "P")
  (org-emphasis arg 'verbatim))

;;; Suggested bindings
(org-defkey org-mode-map (kbd "M-o *") 'org-emphasis-bold)
(org-defkey org-mode-map (kbd "M-o M-*") 'org-emphasis-bold)
(org-defkey org-mode-map (kbd "M-o ~") 'org-emphasis-code)
(org-defkey org-mode-map (kbd "M-o M-~") 'org-emphasis-code)
(org-defkey org-mode-map (kbd "M-o /") 'org-emphasis-italic)
(org-defkey org-mode-map (kbd "M-o M-/") 'org-emphasis-italic)
(org-defkey org-mode-map (kbd "M-o +") 'org-emphasis-strike-through)
(org-defkey org-mode-map (kbd "M-o M-+") 'org-emphasis-strike-through)
(org-defkey org-mode-map (kbd "M-o _") 'org-emphasis-underline)
(org-defkey org-mode-map (kbd "M-o M-_") 'org-emphasis-underline)
(org-defkey org-mode-map (kbd "M-o =") 'org-emphasis-verbatim)
(org-defkey org-mode-map (kbd "M-o M-=") 'org-emphasis-verbatim)
--8<---------------cut here---------------end--------------->8---

Regards,
-- 
Nicolas Goaziou


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add mode for automatically unhiding emphasis markers in the current region
  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
  1 sibling, 1 reply; 16+ messages in thread
From: Gustavo Barros @ 2020-07-05 20:49 UTC (permalink / raw)
  To: Nicolas Goaziou; +Cc: emacs-orgmode, Shankar Rao

Hi Nicolas,
Hi All,

On Sun, 05 Jul 2020 at 07:50, Nicolas Goaziou <mail@nicolasgoaziou.fr> 
wrote:

> The problem is not your implementation, really. It's just that I don't
> think it should be the _built-in_ way to solve emphasis 
> management. IOW,
> we shouldn't need to activate a minor mode to make that management
> tolerable in the first place.
>
> However, I agree that it makes senses as an extension, in the same 
> vein
> as `org-fragtog` for LaTeX fragments.

[...]

> But, really, I think an option like `org-hide-emphasis-markers' is
> a one-off toggle. Having to, in a way, switch regularly between two
> values is sub-optimal.

I don't think I have anything to add to the previous discussion on this 
matter, and I know you took it into consideration.  Also, I'm well aware 
that sometimes a user interested in a feature lacks a more general 
perspective a maintainer has.  So I take your position here stems from 
one such general design choices, and I understand and respect it.

> Here it is.
>
> The main command is `org-emphasis'. It emphasizes the minimal possible
> area around point, or region. If there's already an emphasis object of
> the desired type around point or region, it extends it forward 
> instead.
> With a prefix argument, it removes the emphasis.
>
> Interactively, the command asks for the type of emphasis to use, but
> I suggest to use dedicated commands instead. Thus, I added a 
> key-binding
> for each of the six emphasis types. For example, for bold, use
>
>       `M-o *'    or    `M-o M-*'
>
> There are equivalent commands for underline (`M-o _` or `M-o M-_'), 
> and
> so on.
>
> Note there, even though I polished it, there are probably some 
> glitches
> left, but it works well enough to give an idea. Tests are missing, 
> too.
>
> Please evaluate the following code to try it.

This is really, really nice.  Certainly a major improvement in the way 
`org-emphasize' works.  I specially like you've chosen to make it act on 
the element around point, that you added the possibility of increasing 
this scope with repetition, and that you made the functions commands we 
can bind.

If I may, I'd like to add comments and report tests, for your 
consideration, in the spirit of trying to help you polish the approach.

One low hanging fruit, which you probably have already considered, is to 
use a transient keymap to ease the repetition of the emphasis commands. 
So that we could type `M-o * * * *' to emphasize four words, instead of 
`M-o * M-o * M-o * M-o *'.  Even better if in this keymap we could call 
a command, bound e.g. to `-', to go back one step in case we have gone 
too far in the repetition.  This is interesting in itself, but specially 
so given a number of the markers are shift-keys, which means the first 
and the second part of the bindings use different modifiers, making the 
repetition quite "athletic" (I suppose we could use "M-O", but still).

A second thing is regarding the removal of the markers.  I think there 
is space to simplify this further and make it even more convenient.  As 
things are, we have six different bindings to remove an emphasis marker 
around point.  Of course, when adding emphasis, we have to specify which 
one we want, but when removing it, the markers are already there and we 
know what is the emphasis around point, and can go with a single 
command, e.g. `org-remove-emphasis', and a single binding, e.g. `M-o 
r/M-r', without the cognitive load of having to identify visually which 
is the marker, to call the correct command to remove it.  The only case 
not covered by this would be if we have nested emphasis of different 
types and want to remove the outer one.  I'd say this is rare enough to 
leave uncovered in exchange for the simplification of 6 to 1 commands 
for emphasis removal.  True, this seventh command could just be added, 
and leave the current six as they are, but I do have a suggestion for 
another use of the prefix, which see.  (Perhaps an argument similar to 
the one being made here for removal could be made for extending 
emphasis, but I'm not sure if with the same relevance).

Still regarding emphasis removal, I see two things one might want when 
"removing" emphasis: one is to remove the whole emphasis around point, 
the other is to remove part of an existing emphasized region, doing the 
analogous of what your six emphasis commands do, but removing emphasis 
one word at a time.  If this distinction is deemed useful and worth 
implementing, how about `org-remove-emphasis' with no prefix doing the 
first, and with prefix doing the second?

A third thing I think is worth considering is the direction of 
extension, given that `org-emphasize' also works by extending an 
existing emphasized region.  Two things here:  should one be able to 
control the direction the expansion occurs?  what should be the 
preferred (or only) expansion direction?  I'd say the first one would be 
really nice, and I'd suggest using the prefix to the six emphasis 
commands to achieve it ("prefix changes the default direction").  As to 
the second, I'd go for preferring a backwards expansion, rather than a 
forwards one.  My reasoning here is that one would be adding emphasis 
either while skimming/navigating through an existing document, in which 
case one has more freedom in point placement, or when one is typing, in 
which case moving point implies that we must get back to where we were 
before continuing typing.  So for this "while typing" situation a 
backward expansion would be much more useful, while for the case of 
"adding emphasis to existing text" the direction would be less 
important.  I take that's the reason `flyspell' has 
`flyspell-auto-correct-previous-word' while it does not have a "next" 
equivalent, and why `flyspell-correct' (the package) defaults to 
correcting the previous misspelling.

A fourth issue is point placement after the emphasis is added. 
`org-emphasis' takes a stance here and places point within the emphasis. 
I do agree with this option, but it is still true that sometimes, one 
might want or need otherwise.  This, of course, gets more interesting 
when `org-hide-emphasis-markers' is t.  And I actually think this issue 
is still more general.  One thing is to "add emphasis markers to 
existing text", another is "adding text around existing emphasis 
markers".  The first one is superbly dealt with by this implementation 
of `org-emphasize', the second one, as far as I can see, not equally so.

Finally, as I took it for a spin, I might as well report some cases 
which called my attention.  I know you said this isn't ready yet, but I 
hope it is still useful.  In the examples, '|' represents point, and '·' 
space.

1) When point is at the right-edge of a word, the emphasis command will 
either emphasize the following word, if there is one before eol, or 
error with "Nothing to emphasize in the region" even though there is no 
active region.  If there is only whitespace between point and eol the 
emphasis command will issue the same error and move point to eol. 
Illustrations:

Starting from:

#+begin_src org
foo|·bar
#+end_src

`M-o *' results in:

#+begin_src org
foo·*|bar*
#+end_src

(note point has moved)

Starting from:

#+begin_src org
foo·bar|
#+end_src

`M-o *' errors with "Nothing to emphasize in the region".

Starting from:

#+begin_src org
foo·bar|···
#+end_src

`M-o *' errors with "Nothing to emphasize in the region" and moves point 
to:

#+begin_src org
foo·bar···|
#+end_src

I suggest it would make sense, when at a word right boundary, to 
emphasize the immediately preceding word rather than the next one. 
Though this is probably somewhat a matter of preference, I'd argue it is 
more intuitive.  On the other hand, the last case, where the command 
issues an error, does not apply emphasis and moves point, is clearly 
unexpected behavior (it should at least not move point).

2) When point is within whitespace, with no "word" at point, it still 
emphasizes the next word, if there is one.  Illustration:

Starting from:

#+begin_src org
foo·|·bar
#+end_src

`M-o *' results in:

#+begin_src org
foo··*|bar*
#+end_src

(note point has moved)

I would expect to get instead:

#+begin_src org
foo·*|*·bar
#+end_src

Starting from an empty line (or a "whitespace only" line):

#+begin_src org
|
#+end_src

We get error "Cannot emphasize contents here". But why not?

#+begin_src org
*|*
#+end_src

And be able to insert some content "to be bold".

Indeed, if the right boundary logic above is used, and this within 
whitespace one is also used, then point never needs to move when 
applying emphasis "around point", which seems sensible to me.  (I 
haven't given proper thought on what to do with point/region when region 
is active though.)  Also, as far as I can tell, it would also never fall 
back to "Nothing to emphasize in the region", which indeed is somewhat 
strange when no region is active.  The general idea is, if no "minimal 
area around region or point" can be identified, place the markers around 
point, instead of returning error.


That said, I reiterate I really consider this revamping of 
`org-emphasize' a major improvement, and a very welcome one.  And I 
thank you very much for that.  My comments here are just offered for 
your consideration and use as you see fit, in the hope they might be 
useful.  And I'm looking forward to see this reach distribution.

Best,
Gustavo.



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add mode for automatically unhiding emphasis markers in the current region
  2020-07-05 20:49                       ` Gustavo Barros
@ 2020-07-06 14:01                         ` Gustavo Barros
  0 siblings, 0 replies; 16+ messages in thread
From: Gustavo Barros @ 2020-07-06 14:01 UTC (permalink / raw)
  To: Nicolas Goaziou; +Cc: emacs-orgmode, Shankar Rao

Hi Nicolas,
Hi All,

On Sun, 05 Jul 2020 at 17:49, Gustavo Barros <gusbrs.2016@gmail.com> 
wrote:

> A fourth issue is point placement after the emphasis is 
> added. `org-emphasis'
> takes a stance here and places point within the emphasis. I do agree 
> with this
> option, but it is still true that sometimes, one might want or need 
> otherwise.
> This, of course, gets more interesting when 
> `org-hide-emphasis-markers' is t.
> And I actually think this issue is still more general.  One thing is 
> to "add
> emphasis markers to existing text", another is "adding text around 
> existing
> emphasis markers".  The first one is superbly dealt with by this
> implementation of `org-emphasize', the second one, as far as I can 
> see, not
> equally so.

After sleeping over this problem, I think I had an interesting idea to 
allow some control of point position in an intuitive fashion.  I thus 
submit it to the list.

Consider the following suggested behavior for `org-emphasize':  i) 
anything in the direction opposite to the emphasis expansion direction 
is ignored, regardless of whether point is at a word boundary or not on 
that side (this corresponds to the current implementation, but goes 
against my initial suggestion of considering the right boundary of a 
word as "part" of the previous word); ii) point never moves (and this is 
different from the current implementation).

Simple, clear cut rules.  And they would make it possible to control 
whether point is placed within or outside the emphasis markers by 
manipulating point position wrt whitespace /before/ calling 
`org-emphasize'.  So, taking the current forward expansion direction, if 
we wanted to emphasize the following word, we would have: i) if the 
point is placed before whitespace preceding the following word, point 
will be left where is is, which will result to be outside the emphasis 
markers; ii) if point is within a word (which includes the left 
boundary) point will end inside the markers; it also hasn't moved, just 
the marker was applied before it.

Some examples, again assuming forward expansion:

#+begin_src org
foo|·bar
foo·|bar
foo·b|ar
foo·bar|
#+end_src

for `M-o *', the results would be:

#+begin_src org
foo|·*bar*
foo·*|bar*
foo·*b|ar*
foo·bar|
#+end_src

Assuming a backwards expansion direction was to exist (and the more I 
think of this, the more I lean towards preferring this as the default), 
we could do the following.

I'm typing something:

#+begin_src org
foo·bar|
#+end_src

But then I decide to emphasize "bar", and only "bar".  I could go with 
`SPC M-o *' to get:

#+begin_src org
foo·*bar*·|
#+end_src

And be able to just keep on typing:

#+begin_src org
foo·*bar*·baz|
#+end_src

I wouldn't say this goes all the way to solve the "adding text around 
existing emphasis markers" problem.  But, as far as my scrutiny went, I 
do think it goes quite a stretch.  And it is quite simple, which should 
make for "intuitive" hopefully.

WDYT?

Best,
Gustavo.



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add mode for automatically unhiding emphasis markers in the current region
  2020-07-05 10:50                     ` Nicolas Goaziou
  2020-07-05 20:49                       ` Gustavo Barros
@ 2020-07-07 15:57                       ` Shankar Rao
  1 sibling, 0 replies; 16+ messages in thread
From: Shankar Rao @ 2020-07-07 15:57 UTC (permalink / raw)
  To: Shankar Rao, Gustavo Barros, emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 5898 bytes --]

Thank you for your hard work on this. It's definitely easier to compare two
concrete blocks of code rather than abstract ideas.

> I agree with you that my solution is somewhat intrusive. Ideally, I would
> > have preferred that my solution could leverage advice functions or some
> Org
> > hook, so that I wouldn't have to modify org.el, but it doesn't seem like
> > there is a straightforward way to do that. The modification of
> > `post-command-hook', similar to one used for `prettify-symbols-mode',
> only
> > occurs if `org-auto-emphasis-mode' is active
>
> The problem is not your implementation, really. It's just that I don't
> think it should be the _built-in_ way to solve emphasis management. IOW,
> we shouldn't need to activate a minor mode to make that management
> tolerable in the first place.
>
> However, I agree that it makes senses as an extension, in the same vein
> as `org-fragtog` for LaTeX fragments.
>

That's a fair point. As I said, I modified `org-do-emphasis-faces' in
org.el only because I couldn't find a less intrusive way of achieving the
functionality I was looking for. Is there a way to make
`org-auto-emphasis-mode' an extension that leaves org.el unmodified?


> > So in your system, in order to interact with emphasis markers, the user
> > would have to learn two different commands? That doesn't seem to be in
> line
> > with the dwim philosophy used in modern emacs packages.
>
> Two different commands? Bah! The change I suggest introduces 7 new
> commands and 12 new bindings! :)
>
> Yet, I claim it is still (somewhat) intuitive.
>

I agree that your change is reasonably intuitive. I find it quite elegant
that you appropriated the M-o binding (which by default runs the
`facemenu-set-*' commands) in orgmode, and that the modifier keys
(*,/,_,~,=,+) map to text emphasis markers. But while I find your change
easy to understand, I find it a bit unwieldy to use. I discuss this further
below.


> > In my opinion, one of the strengths of Org is that the interface is
> > multimodal. One can (in principle) edit documents in much the same way as
> > word processors and rich text editors. However since everything
> underneath
> > is implemented with just text, one can also directly access and
> manipulate
> > this text. The ability to switch between these two modalities is
> extremely
> > powerful and is what sets Org apart from other document editing
> > systems.
>
> You can always toggle `visible-mode' for that.
>
> But, really, I think an option like `org-hide-emphasis-markers' is
> a one-off toggle. Having to, in a way, switch regularly between two
> values is sub-optimal.
>

I completely agree that toggling on and off *all* emphasis markers is
suboptimal. In fact, before I developed this `org-auto-emphasis-mode', my
previous solution was to toggle the emphasis marker at point. Please refer
to this reddit post (
https://www.reddit.com/r/orgmode/comments/grh423/is_it_possible_to_make_orghideemphasismarkers_and/).
Coincidentally, I bound this function to M-o as well.


> Here it is.
>
> The main command is `org-emphasis'. It emphasizes the minimal possible
> area around point, or region. If there's already an emphasis object of
> the desired type around point or region, it extends it forward instead.
> With a prefix argument, it removes the emphasis.
>
> Interactively, the command asks for the type of emphasis to use, but
> I suggest to use dedicated commands instead. Thus, I added a key-binding
> for each of the six emphasis types. For example, for bold, use
>
>       `M-o *'    or    `M-o M-*'
>
> There are equivalent commands for underline (`M-o _` or `M-o M-_'), and
> so on.
>

I tested out your commands and I find your `org-emphasis' to indeed be an
improvement over `org-emphasize'. Since the two commands are so similar, I
would recommend refining this and having it be a replacement for
`org-emphasize'. Here are my comments.

- I like that, in the absence of a region, `org-emphasis' emphasizes the
area around the point. This improves upon `org-emphasize', which inserts a
pair of emphasis markers at point.
- I find the behavior of repeated invocations to expand the area of
emphasis to be useful, but strange. I don't know of any other commands that
expand the area of some property with repeated invocations (except for
`expand-region', which is designed to do that explicitly). To me, it would
be both more straightforward to expand or contract the region (e.g., using
C-right or C-left) and then apply emphasis using M-o.
- I find it unwieldy that to unemphasize, you must use both the prefix
command and remember which marker you chose (e.g. to unbold you must do C-u
M-o *). Prefix commands are usually reserved for special modifications of
commands, and I think unemphasizing is sufficiently common that it
shouldn't be relegated to this space. In word processors like MS Word,
unemphasizing is implemented by repeatedly invoking the keyboard command
(e.g, C-b on plain text bolds it and C-b on bolded text unbolds it). Since
Org doesn't properly render nested emphasis markers, I believe that it
would be more intuitive if unemphasizing was implemented via repeated
invocation (i.e., M-o * on already bolded text) toggle tht emphasis.
- I like Gustavo's idea of using a transient keymap to implement expansion.
In fact, if you implemented it that way, you could use the transient keymap
for expanding the area of emphasis and reserve repeated invocation for
toggling the emphasis
- I also agree with Gustavo that there should be a single command to remove
all emphasis at point/region. Similar to how `org-emphasize' does it, I
suggest that you could use M-o SPC for this.
- I believe that these adding/removing emphasis should not move the point.

I'm glad that I've been able to contribute to this discussion, and I hope
we can reach some consensus for improving emphasis editing in Org!

Shankar

[-- Attachment #2: Type: text/html, Size: 7500 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2020-07-07 16:01 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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
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

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).