all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* [RFC] Add :invisible face attribute
@ 2024-12-18 16:08 Michal Nazarewicz
  2024-12-18 16:52 ` Eli Zaretskii
  2024-12-21  4:51 ` Richard Stallman
  0 siblings, 2 replies; 18+ messages in thread
From: Michal Nazarewicz @ 2024-12-18 16:08 UTC (permalink / raw)
  To: emacs-devel

Introduce :invisible face attribute which makes foreground to be the
same as background rendering the text invisible; or when :invert-video
is also in effect, background is the same as foreground.

Use it in Org mode for org-hide face eliminting the need for
org-find-invisible-foreground function.  This also simplifies
auto-dim-other-buffers NonGNU ELPA package removing the need to
configure a separate hide face for org-hide remap.

To observe the atribute in action, set ‘org-hide-leading-stars’ option,
open NEWS file and enable org-mode.  The initial stars in section
headings are rendered using the new attribute rather than Org mode
needing to explicitly match foregroun to background.

---
 lisp/cus-face.el      |  6 ++++
 lisp/faces.el         | 32 +++++++++++++++--
 lisp/org/org-faces.el |  4 +--
 lisp/org/org.el       | 18 ----------
 src/dispextern.h      |  1 +
 src/xfaces.c          | 80 +++++++++++++++++++++++++++++++++++++------
 6 files changed, 108 insertions(+), 33 deletions(-)

diff --git a/lisp/cus-face.el b/lisp/cus-face.el
index 478092c30cb..b7000747393 100644
--- a/lisp/cus-face.el
+++ b/lisp/cus-face.el
@@ -251,6 +251,12 @@ custom-face-attributes
 	     (const :tag "Off" nil)
 	     (const :tag "On" t)))
 
+    (:invisible
+     (choice :tag "Invisible"
+	     :help-echo "Control whether text should be rendered in the same color as background."
+	     (const :tag "Off" nil)
+	     (const :tag "On" t)))
+
     (:foreground
      (color :tag "Foreground"
 	    :help-echo "Set foreground color (name or #RRGGBB hex spec)."))
diff --git a/lisp/faces.el b/lisp/faces.el
index 05df685c679..6451664d791 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -375,6 +375,7 @@ face-x-resources
     (:underline (".attributeUnderline" . "Face.AttributeUnderline"))
     (:inverse-video (".attributeInverse" . "Face.AttributeInverse"))
     (:extend (".attributeExtend" . "Face.AttributeExtend"))
+    (:invisible (".attributeInvisible" . "Face.AttributeInvisible"))
     (:stipple
      (".attributeStipple" . "Face.AttributeStipple")
      (".attributeBackgroundPixmap" . "Face.AttributeBackgroundPixmap"))
@@ -615,6 +616,15 @@ face-inverse-video-p
  (eq (face-attribute face :inverse-video frame inherit) t))
 
 
+(defun face-invisible-video-p (face &optional frame inherit)
+ "Return non-nil if FACE specifies a non-nil invisible.
+If the optional argument FRAME is given, report on face FACE in that frame.
+If FRAME is t, report on the defaults for face FACE (for new frames).
+If FRAME is omitted or nil, use the selected frame.
+Optional argument INHERIT is passed to `face-attribute'."
+ (eq (face-attribute face :invisible frame inherit) t))
+
+
 (defun face-bold-p (face &optional frame inherit)
   "Return non-nil if the font of FACE is bold on FRAME.
 If the optional argument FRAME is given, report on face FACE in that frame.
@@ -822,6 +832,12 @@ set-face-attribute
 VALUE specifies whether characters in FACE should be displayed in
 inverse video.  VALUE must be one of t or nil.
 
+`:invisible'
+
+VALUE specifies whether characters in FACE should be displayed in
+foreground color the same as background color rendering them
+invisible.  VALUE must be one of t or nil.
+
 `:stipple'
 
 If VALUE is a string, it must be the name of a file of pixmap data.
@@ -1038,6 +1054,17 @@ set-face-inverse-video
 (define-obsolete-function-alias 'set-face-inverse-video-p
                                 'set-face-inverse-video "24.4")
 
+(defun set-face-invisible (face invisible-p &optional frame)
+  "Specify whether face FACE is in invisible.
+INVISIBLE-P non-nil means FACE displays explicitly in invisible.
+INVISIBLE-P nil means FACE explicitly is not in invisible.
+FRAME nil or not specified means change face on all frames.
+Use `set-face-attribute' to \"unspecify\" the invisible attribute."
+  (interactive
+   (let ((list (read-face-and-attribute :invisible)))
+     (list (car list) (if (cadr list) t))))
+  (set-face-attribute face frame :invisible invisible-p))
+
 (defun set-face-bold (face bold-p &optional frame)
   "Specify whether face FACE is bold.
 BOLD-P non-nil means FACE should explicitly display bold.
@@ -1215,7 +1242,7 @@ face-valid-attribute-values
 	   (:slant
             (mapcar (lambda (x) (cons (symbol-name (aref x 1)) (aref x 1)))
 		    font-slant-table))
-	   ((or :inverse-video :extend)
+	   ((or :inverse-video :extend :invisible)
             (mapcar (lambda (x) (cons (symbol-name x) x))
 		    (internal-lisp-face-attribute-values attribute)))
            ((or :underline :overline :strike-through :box)
@@ -1265,6 +1292,7 @@ face-attribute-name-alist
     (:strike-through . "strike-through")
     (:box . "box")
     (:inverse-video . "inverse-video display")
+    (:invisible . "invisible text")
     (:foreground . "foreground color")
     (:background . "background color")
     (:stipple . "background stipple")
@@ -1668,7 +1696,7 @@ face-spec-reset-face
 	     (append
 	      '(:underline nil :overline nil :strike-through nil
 		:box nil :inverse-video nil :stipple nil :inherit nil
-                :extend nil)
+                :extend nil :invisible nil)
 	      ;; `display-graphic-p' is unavailable when running
 	      ;; temacs, prior to loading frame.el.
 	      (when (fboundp 'display-graphic-p)
diff --git a/lisp/org/org-faces.el b/lisp/org/org-faces.el
index 21b23b641ca..ad6af62526d 100644
--- a/lisp/org/org-faces.el
+++ b/lisp/org/org-faces.el
@@ -40,9 +40,7 @@ org-default
   "Face used for default text."
   :group 'org-faces)
 
-(defface org-hide
-  '((((background light)) (:foreground "white"))
-    (((background dark)) (:foreground "black")))
+(defface org-hide '((t :invisible t))
   "Face used to hide leading stars in headlines.
 The foreground color of this face should be equal to the background
 color of the frame."
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 4166738c162..782c2818c82 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -5100,10 +5100,6 @@ org-mode
   ;; Activate `org-table-header-line-mode'
   (when org-table-header-line-p
     (org-table-header-line-mode 1))
-  ;; Try to set `org-hide' face correctly.
-  (let ((foreground (org-find-invisible-foreground)))
-    (when foreground
-      (set-face-foreground 'org-hide foreground)))
   ;; Set face extension as requested.
   (org--set-faces-extend '(org-block-begin-line org-block-end-line)
                          org-fontify-whole-block-delimiter-line)
@@ -5138,20 +5134,6 @@ org-mode-transpose-word-syntax-table
   (abbrev-table-put org-mode-abbrev-table
 		    :parents (list text-mode-abbrev-table)))
 
-(defun org-find-invisible-foreground ()
-  (let ((candidates (remove
-		     "unspecified-bg"
-		     (nconc
-		      (list (face-background 'default)
-			    (face-background 'org-default))
-		      (mapcar
-		       (lambda (alist)
-			 (when (boundp alist)
-			   (cdr (assq 'background-color (symbol-value alist)))))
-		       '(default-frame-alist initial-frame-alist window-system-default-frame-alist))
-		      (list (face-foreground 'org-hide))))))
-    (car (remove nil candidates))))
-
 (defun org-current-time (&optional rounding-minutes past)
   "Current time, possibly rounded to ROUNDING-MINUTES.
 When ROUNDING-MINUTES is not an integer, fall back on the car of
diff --git a/src/dispextern.h b/src/dispextern.h
index 9df6eaf623a..2adb2686188 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1700,6 +1700,7 @@ #define FONT_TOO_HIGH(ft)						\
   LFACE_FONTSET_INDEX,
   LFACE_DISTANT_FOREGROUND_INDEX,
   LFACE_EXTEND_INDEX,
+  LFACE_INVISIBLE_INDEX,
   LFACE_VECTOR_SIZE
 };
 
diff --git a/src/xfaces.c b/src/xfaces.c
index f6264802fa4..1b89bd4eb04 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -1378,6 +1378,7 @@ load_face_colors (struct frame *f, struct face *face,
 {
   Lisp_Object fg, bg, dfg;
   Emacs_Color xfg, xbg;
+  bool invisible;
 
   bg = attrs[LFACE_BACKGROUND_INDEX];
   fg = attrs[LFACE_FOREGROUND_INDEX];
@@ -1391,6 +1392,11 @@ load_face_colors (struct frame *f, struct face *face,
       bg = tmp;
     }
 
+  /* Set foreground to background if invisible.  */
+  invisible = EQ (attrs[LFACE_INVISIBLE_INDEX], Qt);
+  if (invisible)
+    fg = bg;
+
   /* Check for support for foreground, not for background because
      face_color_supported_p is smart enough to know that grays are
      "supported" as background because we are supposed to use stipple
@@ -1405,14 +1411,17 @@ load_face_colors (struct frame *f, struct face *face,
   face->background = load_color2 (f, face, bg, LFACE_BACKGROUND_INDEX, &xbg);
   face->foreground = load_color2 (f, face, fg, LFACE_FOREGROUND_INDEX, &xfg);
 
-  dfg = attrs[LFACE_DISTANT_FOREGROUND_INDEX];
-  if (!NILP (dfg) && !UNSPECIFIEDP (dfg)
-      && color_distance (&xbg, &xfg) < face_near_same_color_threshold)
+  if (!invisible)
     {
-      if (EQ (attrs[LFACE_INVERSE_INDEX], Qt))
-        face->background = load_color (f, face, dfg, LFACE_BACKGROUND_INDEX);
-      else
-        face->foreground = load_color (f, face, dfg, LFACE_FOREGROUND_INDEX);
+      dfg = attrs[LFACE_DISTANT_FOREGROUND_INDEX];
+      if (!NILP (dfg) && !UNSPECIFIEDP (dfg)
+          && color_distance (&xbg, &xfg) < face_near_same_color_threshold)
+        {
+          if (EQ (attrs[LFACE_INVERSE_INDEX], Qt))
+            face->background = load_color (f, face, dfg, LFACE_BACKGROUND_INDEX);
+          else
+            face->foreground = load_color (f, face, dfg, LFACE_FOREGROUND_INDEX);
+        }
     }
 }
 
@@ -1803,6 +1812,7 @@ #define LFACE_FONTSET(LFACE)	    AREF (LFACE, LFACE_FONTSET_INDEX)
 #define LFACE_EXTEND(LFACE)	    AREF (LFACE, LFACE_EXTEND_INDEX)
 #define LFACE_DISTANT_FOREGROUND(LFACE) \
   AREF (LFACE, LFACE_DISTANT_FOREGROUND_INDEX)
+#define LFACE_INVISIBLE(LFACE)	    AREF (LFACE, LFACE_INVISIBLE_INDEX)
 
 /* True if LFACE is a Lisp face.  A Lisp face is a vector of size
    LFACE_VECTOR_SIZE which has the symbol `face' in slot 0.  */
@@ -1912,6 +1922,10 @@ check_lface_attrs (Lisp_Object attrs[LFACE_VECTOR_SIZE])
 	   || RESET_P (attrs[LFACE_FONTSET_INDEX])
 	   || NILP (attrs[LFACE_FONTSET_INDEX]));
 #endif
+  eassert (UNSPECIFIEDP (attrs[LFACE_INVISIBLE_INDEX])
+	   || IGNORE_DEFFACE_P (attrs[LFACE_INVISIBLE_INDEX])
+	   || RESET_P (attrs[LFACE_INVISIBLE_INDEX])
+	   || SYMBOLP (attrs[LFACE_INVISIBLE_INDEX]));
 }
 
 
@@ -2911,6 +2925,13 @@ merge_face_ref (struct window *w,
 		  else
 		    err = true;
 		}
+	      else if (EQ (keyword, QCinvisible))
+		{
+		  if (EQ (value, Qt) || NILP (value))
+		    to[LFACE_INVISIBLE_INDEX] = value;
+		  else
+		    err = true;
+		}
 	      else
 		err = true;
 
@@ -3484,6 +3505,19 @@ DEFUN ("internal-set-lisp-face-attribute", Finternal_set_lisp_face_attribute,
       old_value = LFACE_EXTEND (lface);
       ASET (lface, LFACE_EXTEND_INDEX, value);
     }
+  else if (EQ (attr, QCinvisible))
+    {
+      if (!UNSPECIFIEDP (value)
+	  && !IGNORE_DEFFACE_P (value)
+	  && !RESET_P (value))
+	{
+	  CHECK_SYMBOL (value);
+	  if (!EQ (value, Qt) && !NILP (value))
+	    signal_error ("Invalid invisible face attribute value", value);
+	}
+      old_value = LFACE_INVISIBLE (lface);
+      ASET (lface, LFACE_INVISIBLE_INDEX, value);
+    }
   else if (EQ (attr, QCforeground))
     {
       HANDLE_INVALID_NIL_VALUE (QCforeground, face);
@@ -3977,7 +4011,8 @@ DEFUN ("internal-set-lisp-face-attribute-from-resource",
   else if (EQ (attr, QCweight) || EQ (attr, QCslant) || EQ (attr, QCwidth))
     value = intern (SSDATA (value));
   else if (EQ (attr, QCinverse_video)
-           || EQ (attr, QCextend))
+           || EQ (attr, QCextend)
+           || EQ (attr, QCinvisible))
     value = face_boolean_x_resource_value (value, true);
   else if (EQ (attr, QCunderline)
 	   || EQ (attr, QCoverline)
@@ -4203,6 +4238,8 @@ DEFUN ("internal-get-lisp-face-attribute", Finternal_get_lisp_face_attribute,
     value = LFACE_INHERIT (lface);
   else if (EQ (keyword, QCextend))
     value = LFACE_EXTEND (lface);
+  else if (EQ (keyword, QCinvisible))
+    value = LFACE_INVISIBLE (lface);
   else if (EQ (keyword, QCfont))
     value = LFACE_FONT (lface);
   else if (EQ (keyword, QCfontset))
@@ -4231,7 +4268,8 @@ DEFUN ("internal-lisp-face-attribute-values",
   if (EQ (attr, QCunderline) || EQ (attr, QCoverline)
       || EQ (attr, QCstrike_through)
       || EQ (attr, QCinverse_video)
-      || EQ (attr, QCextend))
+      || EQ (attr, QCextend)
+      || EQ (attr, QCinvisible))
     result = list2 (Qt, Qnil);
 
   return result;
@@ -5360,7 +5398,10 @@ gui_supports_face_attributes_p (struct frame *f,
 				def_attrs[LFACE_STRIKE_THROUGH_INDEX]))
       || (!UNSPECIFIEDP (lattrs[LFACE_BOX_INDEX])
 	  && face_attr_equal_p (lattrs[LFACE_BOX_INDEX],
-				def_attrs[LFACE_BOX_INDEX])))
+				def_attrs[LFACE_BOX_INDEX]))
+      || (!UNSPECIFIEDP (lattrs[LFACE_INVISIBLE_INDEX])
+	  && face_attr_equal_p (lattrs[LFACE_INVISIBLE_INDEX],
+				def_attrs[LFACE_INVISIBLE_INDEX])))
     return false;
 
   /* Check font-related attributes, as those are the most commonly
@@ -5549,6 +5590,17 @@ tty_supports_face_attributes_p (struct frame *f,
 	test_caps |= TTY_CAP_STRIKE_THROUGH;
     }
 
+  /* invisible video */
+  val = attrs[LFACE_INVERSE_INDEX];
+  if (!UNSPECIFIEDP (val))
+    {
+      if (face_attr_equal_p (val, def_attrs[LFACE_INVERSE_INDEX]))
+	return false;		/* same as default */
+      /* Always supported since it just copies bg to fg.  XXX: Is this
+	 true?  I actually have no idea what this function is supposed
+	 to do. */
+    }
+
   /* Color testing.  */
 
   /* Check if foreground color is close enough.  */
@@ -5968,6 +6020,9 @@ realize_default_face (struct frame *f)
   if (UNSPECIFIEDP (LFACE_INVERSE (lface)))
     ASET (lface, LFACE_INVERSE_INDEX, Qnil);
 
+  if (UNSPECIFIEDP (LFACE_INVISIBLE (lface)))
+    ASET (lface, LFACE_INVISIBLE_INDEX, Qnil);
+
   if (UNSPECIFIEDP (LFACE_FOREGROUND (lface)))
     {
       /* This function is called so early that colors are not yet
@@ -6716,6 +6771,9 @@ realize_tty_face (struct face_cache *cache,
       face->background = tem;
     }
 
+  if (!NILP (attrs[LFACE_INVISIBLE_INDEX]))
+    face->foreground = face->background;
+
   if (tty_suppress_bold_inverse_default_colors_p
       && face->tty_bold_p
       && face->background == FACE_TTY_DEFAULT_FG_COLOR
@@ -7342,6 +7400,7 @@ init_xfaces (void)
   face_attr_sym[LFACE_FONTSET_INDEX] = QCfontset;
   face_attr_sym[LFACE_DISTANT_FOREGROUND_INDEX] = QCdistant_foreground;
   face_attr_sym[LFACE_EXTEND_INDEX] = QCextend;
+  face_attr_sym[LFACE_INVISIBLE_INDEX] = QCinvisible;
 }
 
 void
@@ -7381,6 +7440,7 @@ syms_of_xfaces (void)
   DEFSYM (QCbox, ":box");
   DEFSYM (QCinherit, ":inherit");
   DEFSYM (QCextend, ":extend");
+  DEFSYM (QCinvisible, ":invisible");
 
   /* Symbols used for Lisp face attribute values.  */
   DEFSYM (QCcolor, ":color");
-- 
2.45.2




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

* Re: [RFC] Add :invisible face attribute
  2024-12-18 16:08 Michal Nazarewicz
@ 2024-12-18 16:52 ` Eli Zaretskii
  2024-12-18 18:05   ` Michal Nazarewicz
  2024-12-21 17:46   ` Jim Porter
  2024-12-21  4:51 ` Richard Stallman
  1 sibling, 2 replies; 18+ messages in thread
From: Eli Zaretskii @ 2024-12-18 16:52 UTC (permalink / raw)
  To: Michal Nazarewicz; +Cc: emacs-devel

> From: Michal Nazarewicz <mina86@mina86.com>
> Date: Wed, 18 Dec 2024 17:08:12 +0100
> 
> Introduce :invisible face attribute which makes foreground to be the
> same as background rendering the text invisible; or when :invert-video
> is also in effect, background is the same as foreground.
> 
> Use it in Org mode for org-hide face eliminting the need for
> org-find-invisible-foreground function.  This also simplifies
> auto-dim-other-buffers NonGNU ELPA package removing the need to
> configure a separate hide face for org-hide remap.
> 
> To observe the atribute in action, set ‘org-hide-leading-stars’ option,
> open NEWS file and enable org-mode.  The initial stars in section
> headings are rendered using the new attribute rather than Org mode
> needing to explicitly match foregroun to background.

Thanks.

A new face attribute adds quite a bit of complexity, so we should
really believe this is a good idea.  Given that this can already be
achieved without a new attribute, I'm not sure.  Is this really a
frequent need/situation?

But let's see what others think about this.

> @@ -2911,6 +2925,13 @@ merge_face_ref (struct window *w,
>  		  else
>  		    err = true;
>  		}
> +	      else if (EQ (keyword, QCinvisible))
> +		{
> +		  if (EQ (value, Qt) || NILP (value))
> +		    to[LFACE_INVISIBLE_INDEX] = value;
> +		  else
> +		    err = true;
> +		}

Does this mean that the result of merging two faces with different
values for :invisible will depend on the order of the merge?  That is,
does the nil value override the t value?  Or am I missing something?

Btw, I think "invisible" is not the best name for this, because that's
not really what will happen on display.  It's more like "illegible" or
something to that effect.



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

* Re: [RFC] Add :invisible face attribute
  2024-12-18 16:52 ` Eli Zaretskii
@ 2024-12-18 18:05   ` Michal Nazarewicz
  2024-12-21 17:46   ` Jim Porter
  1 sibling, 0 replies; 18+ messages in thread
From: Michal Nazarewicz @ 2024-12-18 18:05 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

On Wed, Dec 18 2024, Eli Zaretskii wrote:
> A new face attribute adds quite a bit of complexity, so we should
> really believe this is a good idea.  Given that this can already be
> achieved without a new attribute, I'm not sure.  Is this really a
> frequent need/situation?

Yes, agreed.  org-hide is the only face I’m aware of and this only came
up as I was working on auto-dim-other-buffers.

To quickly recap, auto-dim-other-buffers adds a face remap to default
face which changes its background.  The problem is that if default
background is changed, text rendered with org-hide becomes visible.  So
now I also need to remap org-hide.

This by itself I could live with, but it creates friction for users who
need to not only customise auto-dim-other-buffers-face (which specifies
the remap background) but also auto-dim-other-buffers-hide-face.

There are actually two minor bugs in Org mode that this patch fixes.
First is when default face is changed after org-mode is initialised:

    (setq org-hide-leading-stars t)
    (org-mode)
    (insert "\n*** Foo\n")        ; the first two stars are invisible
    (set-face-background 'default "red")  ; the starts become visible

Second is when running with frames on multiple displays, e.g. starting
org-mode on terminal frame with black background makes org-hide use
black foreground.  But that’s visible on X11 frame which uses white
background.

This is why I’ve not gone with Org’s way of initialising the hide face
when the mode is first enabled.

>> @@ -2911,6 +2925,13 @@ merge_face_ref (struct window *w,
>>  		  else
>>  		    err = true;
>>  		}
>> +	      else if (EQ (keyword, QCinvisible))
>> +		{
>> +		  if (EQ (value, Qt) || NILP (value))
>> +		    to[LFACE_INVISIBLE_INDEX] = value;
>> +		  else
>> +		    err = true;
>> +		}

> Does this mean that the result of merging two faces with different
> values for :invisible will depend on the order of the merge?  That is,
> does the nil value override the t value?  Or am I missing something?

The behaviour is the same as for other boolean attributes, e.g. extend
or inverse-video, so yes, if the attribute is specified multiple times
one overrides the other.

There’s a related difference in how org-hide works now vs with this
patch.  Currently, selecting text which uses org-hide makes the text
visible; with this patch it remains invisible unless region face is
changed to include :invisible nil.

> Btw, I think "invisible" is not the best name for this, because that's
> not really what will happen on display.  It's more like "illegible" or
> something to that effect.

Not sure I’m a fan of illegible but I’m happy to go with whatever name.

By the way, two other ideas I had were:
a) add another value for :inverse-video (e.g. ‘:inverse-video
   'foreground’ makes foreground same as background) or
b) add a pseudo colour so one could write ‘:foreground "background"’.

-- 
Best regards
ミハウ “𝓶𝓲𝓷𝓪86” ナザレヴイツ
«If at first you don’t succeed, give up skydiving»



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

* Re: [RFC] Add :invisible face attribute
  2024-12-18 16:08 Michal Nazarewicz
  2024-12-18 16:52 ` Eli Zaretskii
@ 2024-12-21  4:51 ` Richard Stallman
  2024-12-21 16:09   ` Michal Nazarewicz
                     ` (2 more replies)
  1 sibling, 3 replies; 18+ messages in thread
From: Richard Stallman @ 2024-12-21  4:51 UTC (permalink / raw)
  To: Michal Nazarewicz; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > Introduce :invisible face attribute which makes foreground to be the
  > same as background rendering the text invisible; or when :invert-video
  > is also in effect, background is the same as foreground.

Why is this feature worth having>  What is useful about it?

  > Use it in Org mode for org-hide face eliminting the need for
  > org-find-invisible-foreground function.

Ia that the sole benefit of this feature?
I don't think it is sufficent reason to add the feature
and write the changes to document it.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





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

* Re: [RFC] Add :invisible face attribute
  2024-12-21  4:51 ` Richard Stallman
@ 2024-12-21 16:09   ` Michal Nazarewicz
  2024-12-21 18:05     ` Kévin Le Gouguec
  2024-12-23  6:19   ` Jean Louis
  2024-12-23  6:22   ` Jean Louis
  2 siblings, 1 reply; 18+ messages in thread
From: Michal Nazarewicz @ 2024-12-21 16:09 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

On Fri, Dec 20 2024, Richard Stallman wrote:
>   > Introduce :invisible face attribute which makes foreground to be the
>   > same as background rendering the text invisible; or when :invert-video
>   > is also in effect, background is the same as foreground.
>
> Why is this feature worth having>  What is useful about it?
>
>   > Use it in Org mode for org-hide face eliminting the need for
>   > org-find-invisible-foreground function.
>
> Ia that the sole benefit of this feature?
> I don't think it is sufficent reason to add the feature
> and write the changes to document it.

Yes, the use-cases I’m aware of are around org-hide.  To sum up:
* The feature would make org-hide easier as described above.
* It addresses two minor bugs with org-hide I’ve mentioned in the other
  mail.
* For code outside of Emacs, it makes auto-dim-other-buffers slightly
  more user friendly.

-- 
Best regards
ミハウ “𝓶𝓲𝓷𝓪86” ナザレヴイツ
«If at first you don’t succeed, give up skydiving»



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

* Re: [RFC] Add :invisible face attribute
  2024-12-18 16:52 ` Eli Zaretskii
  2024-12-18 18:05   ` Michal Nazarewicz
@ 2024-12-21 17:46   ` Jim Porter
  2024-12-21 18:28     ` Ihor Radchenko
  1 sibling, 1 reply; 18+ messages in thread
From: Jim Porter @ 2024-12-21 17:46 UTC (permalink / raw)
  To: Eli Zaretskii, Michal Nazarewicz; +Cc: emacs-devel

On 12/18/2024 8:52 AM, Eli Zaretskii wrote:
>> From: Michal Nazarewicz <mina86@mina86.com>
>> Date: Wed, 18 Dec 2024 17:08:12 +0100
>>
>> Introduce :invisible face attribute which makes foreground to be the
>> same as background rendering the text invisible; or when :invert-video
>> is also in effect, background is the same as foreground.
[snip]
> 
> A new face attribute adds quite a bit of complexity, so we should
> really believe this is a good idea.  Given that this can already be
> achieved without a new attribute, I'm not sure.  Is this really a
> frequent need/situation?
> 
> But let's see what others think about this.

I'm just brainstorming here, but could Org use a display spec with 
specified spaces[1] to make Emacs render a space of the appropriate 
width? That requires a bit of computation, but it's how 
'visual-wrap-prefix-mode' and SHR handle (roughly) similar sorts of things.

If it's too difficult to get the existing specified spaces to work 
properly here, maybe we could enhance them? For example, perhaps you 
could have a display spec like this:

   '(space :width "**")

Which would mean "make a space as wide as the string '**'". That might 
even allow simplifying some of the code in 'visual-wrap-prefix-mode' 
(specifically, the parts that compute the width of the prefix; see 
'visual-wrap--content-prefix').

Still, if the existing specified space code is enough, it's probably 
best not to add even more complexity to it.

[1] 
https://www.gnu.org/software/emacs/manual/html_node/elisp/Specified-Space.html



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

* Re: [RFC] Add :invisible face attribute
  2024-12-21 16:09   ` Michal Nazarewicz
@ 2024-12-21 18:05     ` Kévin Le Gouguec
  2024-12-21 18:30       ` Ihor Radchenko
  2024-12-22 15:20       ` Michal Nazarewicz
  0 siblings, 2 replies; 18+ messages in thread
From: Kévin Le Gouguec @ 2024-12-21 18:05 UTC (permalink / raw)
  To: Michal Nazarewicz; +Cc: rms, emacs-devel

Michal Nazarewicz <mina86@mina86.com> writes:

> On Fri, Dec 20 2024, Richard Stallman wrote:
>>   > Introduce :invisible face attribute which makes foreground to be the
>>   > same as background rendering the text invisible; or when :invert-video
>>   > is also in effect, background is the same as foreground.
>>
>> Why is this feature worth having>  What is useful about it?
>>
>>   > Use it in Org mode for org-hide face eliminting the need for
>>   > org-find-invisible-foreground function.
>>
>> Ia that the sole benefit of this feature?
>> I don't think it is sufficent reason to add the feature
>> and write the changes to document it.
>
> Yes, the use-cases I’m aware of are around org-hide.  To sum up:
> * The feature would make org-hide easier as described above.
> * It addresses two minor bugs with org-hide I’ve mentioned in the other
>   mail.

Drive-by idea, from another org-hide-leading-stars user who encounters
the first bug occasionally (or rather, a variant thereof, when
highlighting headings with faces like region or hl-line):

Would it make sense to fix these bugs by making Org apply a
  '(display (space :width 1))
property on every star to hide?  (Suggesting one prop per char, instead
of prop'ing the whole prefix with a single (space :width N), since AFAIU
that would prevent users from moving point within the prefix?)

Possibly a hot air suggestion: not super familiar with display props, so
they may have undesirable side-effects?  Also not sure how to apply them
& keep them updated "robustly".  The current org-hide face is applied
via font-lock so no extra bookkeeping required; '(elisp) Search-based
Fontification' suggests font-lock does support applying arbitrary
properties - and clearing them, using font-lock-extra-managed-props.

This is completely armchair reading of the manual tho, never toyed with
display properties.  Mostly curious if this is something that could make
sense in theory.  AFAIU this "solution" would not address your second
use-case anyway:

> * For code outside of Emacs, it makes auto-dim-other-buffers slightly
>   more user friendly.



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

* Re: [RFC] Add :invisible face attribute
  2024-12-21 17:46   ` Jim Porter
@ 2024-12-21 18:28     ` Ihor Radchenko
  2024-12-21 18:52       ` Jim Porter
  0 siblings, 1 reply; 18+ messages in thread
From: Ihor Radchenko @ 2024-12-21 18:28 UTC (permalink / raw)
  To: Jim Porter; +Cc: Eli Zaretskii, Michal Nazarewicz, emacs-devel

Jim Porter <jporterbugs@gmail.com> writes:

> I'm just brainstorming here, but could Org use a display spec with 
> specified spaces[1] to make Emacs render a space of the appropriate 
> width? That requires a bit of computation, but it's how 
> 'visual-wrap-prefix-mode' and SHR handle (roughly) similar sorts of things.

If one uses display spec, editing the text underneath will become
tricky. Org mode is first and foremost a text format and should remain
editable using normal text editing commands.

Of course, third-party packages are free to make such visual changes, if
they believe that they constitute an improvement.

-- 
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>



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

* Re: [RFC] Add :invisible face attribute
  2024-12-21 18:05     ` Kévin Le Gouguec
@ 2024-12-21 18:30       ` Ihor Radchenko
  2024-12-22 14:38         ` Kévin Le Gouguec
  2024-12-22 15:20       ` Michal Nazarewicz
  1 sibling, 1 reply; 18+ messages in thread
From: Ihor Radchenko @ 2024-12-21 18:30 UTC (permalink / raw)
  To: Kévin Le Gouguec; +Cc: Michal Nazarewicz, rms, emacs-devel

Kévin Le Gouguec <kevin.legouguec@gmail.com> writes:

> Drive-by idea, from another org-hide-leading-stars user who encounters
> the first bug occasionally (or rather, a variant thereof, when
> highlighting headings with faces like region or hl-line):

IMHO, this is not a bug, but a feature :)

-- 
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>



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

* Re: [RFC] Add :invisible face attribute
  2024-12-21 18:28     ` Ihor Radchenko
@ 2024-12-21 18:52       ` Jim Porter
  0 siblings, 0 replies; 18+ messages in thread
From: Jim Porter @ 2024-12-21 18:52 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: Eli Zaretskii, Michal Nazarewicz, emacs-devel

On 12/21/2024 10:28 AM, Ihor Radchenko wrote:
> Jim Porter <jporterbugs@gmail.com> writes:
> 
>> I'm just brainstorming here, but could Org use a display spec with
>> specified spaces[1] to make Emacs render a space of the appropriate
>> width? That requires a bit of computation, but it's how
>> 'visual-wrap-prefix-mode' and SHR handle (roughly) similar sorts of things.
> 
> If one uses display spec, editing the text underneath will become
> tricky. Org mode is first and foremost a text format and should remain
> editable using normal text editing commands.

Hmm. Doing a bit of testing in a scratch buffer, I think if each hidden 
character had its own display spec, editing seems to work ok. At least 
in the sense that I can delete each character like I'd expect. There 
might be other problems with this though, e.g. keeping the display specs 
updated, or performance issues...

For a completely different idea, I seem to recall some discussion around 
an :opacity face attribute. That would be useful for themes, e.g. to 
de-emphasize some text by reducing the opacity, and then here we could 
just set the :opacity to zero. I can't find the thread about this, but I 
recall there being some debate about how it should work; for example, if 
instead we should support RGBA for :foreground.



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

* Re: [RFC] Add :invisible face attribute
  2024-12-21 18:30       ` Ihor Radchenko
@ 2024-12-22 14:38         ` Kévin Le Gouguec
  2024-12-22 15:28           ` Michal Nazarewicz
  0 siblings, 1 reply; 18+ messages in thread
From: Kévin Le Gouguec @ 2024-12-22 14:38 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: Michal Nazarewicz, rms, emacs-devel

Ihor Radchenko <yantar92@posteo.net> writes:

> Kévin Le Gouguec <kevin.legouguec@gmail.com> writes:
>
>> Drive-by idea, from another org-hide-leading-stars user who encounters
>> the first bug occasionally (or rather, a variant thereof, when
>> highlighting headings with faces like region or hl-line):
>
> IMHO, this is not a bug, but a feature :)

Yeah, there is some appeal in revealing the actual text when
highlighting it or moving over it (which of course, spelled like that,
brings to mind the reveal-mode integration in authinfo--hide-passwords,
but not sure there's anything interesting to take out of that free
association).

(Does the :invisible attribute preserve that "feature"?)



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

* Re: [RFC] Add :invisible face attribute
  2024-12-21 18:05     ` Kévin Le Gouguec
  2024-12-21 18:30       ` Ihor Radchenko
@ 2024-12-22 15:20       ` Michal Nazarewicz
  1 sibling, 0 replies; 18+ messages in thread
From: Michal Nazarewicz @ 2024-12-22 15:20 UTC (permalink / raw)
  To: Kévin Le Gouguec; +Cc: rms, emacs-devel

On Sat, Dec 21 2024, Kévin Le Gouguec wrote:
> AFAIU this "solution" would not address your second use-case anyway:

> Michal Nazarewicz <mina86@mina86.com> writes:
>> * For code outside of Emacs, it makes auto-dim-other-buffers slightly
>>   more user friendly.

It would actually address it.  If Org switched to using non-face method
of hiding the stars I would no longer need to care about org-hide in
auto-dim-other-buffers.

-- 
Best regards
ミハウ “𝓶𝓲𝓷𝓪86” ナザレヴイツ
«If at first you don’t succeed, give up skydiving»



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

* Re: [RFC] Add :invisible face attribute
  2024-12-22 14:38         ` Kévin Le Gouguec
@ 2024-12-22 15:28           ` Michal Nazarewicz
  0 siblings, 0 replies; 18+ messages in thread
From: Michal Nazarewicz @ 2024-12-22 15:28 UTC (permalink / raw)
  To: Kévin Le Gouguec, Ihor Radchenko; +Cc: rms, emacs-devel

>> Kévin Le Gouguec <kevin.legouguec@gmail.com> writes:
>>> Drive-by idea, from another org-hide-leading-stars user who encounters
>>> the first bug occasionally (or rather, a variant thereof, when
>>> highlighting headings with faces like region or hl-line):

> Ihor Radchenko <yantar92@posteo.net> writes:
>> IMHO, this is not a bug, but a feature :)

On Sun, Dec 22 2024, Kévin Le Gouguec wrote:
> Yeah, there is some appeal in revealing the actual text when
> highlighting it or moving over it (which of course, spelled like that,
> brings to mind the reveal-mode integration in authinfo--hide-passwords,
> but not sure there's anything interesting to take out of that free
> association).
>
> (Does the :invisible attribute preserve that "feature"?)

Yes, in fact :invisible is arguably better because the effect can be
configured.  You can add :invisible nil to region or hl-line face and
then the stars are show; or you can leave :invisible unspecified and the
stars remain hidden.

-- 
Best regards
ミハウ “𝓶𝓲𝓷𝓪86” ナザレヴイツ
«If at first you don’t succeed, give up skydiving»



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

* Re: [RFC] Add :invisible face attribute
  2024-12-21  4:51 ` Richard Stallman
  2024-12-21 16:09   ` Michal Nazarewicz
@ 2024-12-23  6:19   ` Jean Louis
  2024-12-23  6:22   ` Jean Louis
  2 siblings, 0 replies; 18+ messages in thread
From: Jean Louis @ 2024-12-23  6:19 UTC (permalink / raw)
  To: Richard Stallman; +Cc: Michal Nazarewicz, emacs-devel

* Richard Stallman <rms@gnu.org> [2024-12-21 07:54]:
> [[[ To any NSA and FBI agents reading my email: please consider    ]]]
> [[[ whether defending the US Constitution against all enemies,     ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> 
>   > Introduce :invisible face attribute which makes foreground to be the
>   > same as background rendering the text invisible; or when :invert-video
>   > is also in effect, background is the same as foreground.
> 
> Why is this feature worth having>  What is useful about it?

It would be useful to me:

I have tables made out of Box Drawing Characters which I display in
the Org file and which I would like to use for multi-column display of
some information. Here is not a proper, though similar example:

╔════════════════════════╦════════╦══════════════════════════════╦═══════╗
║ Total number of people ║ 242775 ║ Total Hyperdocuments         ║ 64891 ║
╠════════════════════════╬════════╬══════════════════════════════╬═══════╣
║ People in last week    ║ 18     ║ Hyperdocuments in last week  ║ 186   ║
╠════════════════════════╬════════╬══════════════════════════════╬═══════╣
║ People in last month   ║ 175    ║ Hyperdocuments in last month ║ 879   ║
╚════════════════════════╩════════╩══════════════════════════════╩═══════╝

In some cases I do not want Box Drawing Characters be displayed, then
I would make them simply invisible on the top level of Emacs instead
of changing the underlying library to display " " space.

I was in fact thinking that invisible property already exists in
Emacs. Just these days I started using tables with the " " space to
solve that problem. It looks as below:
                                                                          
  Total number of people   242775   Total Hyperdocuments           64891  
                                                                          
  People in last week      18       Hyperdocuments in last week    186    
                                                                          
  People in last month     175      Hyperdocuments in last month   879    
                                                                          
Property invisible helps to remove some for display or demonstration unwanted characters.

Jean Louis



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

* Re: [RFC] Add :invisible face attribute
  2024-12-21  4:51 ` Richard Stallman
  2024-12-21 16:09   ` Michal Nazarewicz
  2024-12-23  6:19   ` Jean Louis
@ 2024-12-23  6:22   ` Jean Louis
  2024-12-23 13:43     ` Eli Zaretskii
  2 siblings, 1 reply; 18+ messages in thread
From: Jean Louis @ 2024-12-23  6:22 UTC (permalink / raw)
  To: Richard Stallman; +Cc: Michal Nazarewicz, emacs-devel

* Richard Stallman <rms@gnu.org> [2024-12-21 07:54]:
> [[[ To any NSA and FBI agents reading my email: please consider    ]]]
> [[[ whether defending the US Constitution against all enemies,     ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> 
>   > Introduce :invisible face attribute which makes foreground to be the
>   > same as background rendering the text invisible; or when :invert-video
>   > is also in effect, background is the same as foreground.
> 
> Why is this feature worth having>  What is useful about it?


(info "(elisp) Special Properties")

I think it already exists in Emacs:

‘invisible’
     A non-‘nil’ ‘invisible’ property can make a character invisible on
     the screen.  *Note Invisible Text::, for details.

(info "(elisp) Invisible Text")


Jean Louis



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

* Re: [RFC] Add :invisible face attribute
  2024-12-23  6:22   ` Jean Louis
@ 2024-12-23 13:43     ` Eli Zaretskii
  0 siblings, 0 replies; 18+ messages in thread
From: Eli Zaretskii @ 2024-12-23 13:43 UTC (permalink / raw)
  To: Jean Louis; +Cc: rms, mina86, emacs-devel

> Date: Mon, 23 Dec 2024 09:22:33 +0300
> From: Jean Louis <bugs@gnu.support>
> Cc: Michal Nazarewicz <mina86@mina86.com>, emacs-devel@gnu.org
> 
> >   > Introduce :invisible face attribute which makes foreground to be the
> >   > same as background rendering the text invisible; or when :invert-video
> >   > is also in effect, background is the same as foreground.
> > 
> > Why is this feature worth having>  What is useful about it?
> 
> 
> (info "(elisp) Special Properties")
> 
> I think it already exists in Emacs:
> 
> ‘invisible’
>      A non-‘nil’ ‘invisible’ property can make a character invisible on
>      the screen.  *Note Invisible Text::, for details.
> 
> (info "(elisp) Invisible Text")

That's a different feature.  Its effect on display is very different.



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

* [RFC] Add :invisible face attribute
@ 2024-12-24 23:58 Psionic K
  0 siblings, 0 replies; 18+ messages in thread
From: Psionic K @ 2024-12-24 23:58 UTC (permalink / raw)
  To: Emacs developers; +Cc: mina86

Hi Michal, I didn't read the patch.  Did you manage to cover emojis?
Using the foreground=background hack in Emacs 30 does not work for
those glyphs.  I noticed this when implementing the "peel" effect for
dslide list item revelation. 🎄🎅



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

* Re: [RFC] Add :invisible face attribute
@ 2024-12-25  0:20 Psionic K
  0 siblings, 0 replies; 18+ messages in thread
From: Psionic K @ 2024-12-25  0:20 UTC (permalink / raw)
  To: Emacs developers; +Cc: jporterbugs

> I recall there being some debate about how it should work; for example, if instead we should support RGBA for :foreground

Coupling color and alpha when composing faces would make it really
difficult to work with regions, which will have a lot of faces and
would have to be interrogated for each color.

In any case, occluding text without causing re-flow of the contents is
important.  I've used the hacky version of such functionality in both
dslide and MoC and I'm sure people with greater imagination will only
use it better.



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

end of thread, other threads:[~2024-12-25  0:20 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-24 23:58 [RFC] Add :invisible face attribute Psionic K
  -- strict thread matches above, loose matches on Subject: below --
2024-12-25  0:20 Psionic K
2024-12-18 16:08 Michal Nazarewicz
2024-12-18 16:52 ` Eli Zaretskii
2024-12-18 18:05   ` Michal Nazarewicz
2024-12-21 17:46   ` Jim Porter
2024-12-21 18:28     ` Ihor Radchenko
2024-12-21 18:52       ` Jim Porter
2024-12-21  4:51 ` Richard Stallman
2024-12-21 16:09   ` Michal Nazarewicz
2024-12-21 18:05     ` Kévin Le Gouguec
2024-12-21 18:30       ` Ihor Radchenko
2024-12-22 14:38         ` Kévin Le Gouguec
2024-12-22 15:28           ` Michal Nazarewicz
2024-12-22 15:20       ` Michal Nazarewicz
2024-12-23  6:19   ` Jean Louis
2024-12-23  6:22   ` Jean Louis
2024-12-23 13:43     ` Eli Zaretskii

Code repositories for project(s) associated with this external index

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.