Ihor Radchenko <[email protected]> writes:

> "J.D. Smith" <[email protected]> writes:

>> Actually there is one trick I thought of to make an edit-free "appear"
>> flavor that would work in the same way:
>>
>> 1. Hide entity/link/keyword/etc. markers using a custom `invisible'
>>    symbol, e.g. `org-hide', which is on the `buffer-invisibility-spec'.
>>
>> 2. When entering text flanked by hidden boundaries, apply an overlay
>>    which specifies another bogus `invisible' symbol, like `org-nada',
>>    one that is /not/ on the `buffer-invisibility-spec' list.
>
> Can simply specify 'invisible nil.

Not in my testing.  There are many scenarios where a `nil' value does
not override a non-`nil' value in Emacs, despite what is advertised
(IME).  This is on v30.

>> I think that would work pretty nicely.  In fact, you could have one, the
>> other, or both features (cursor change + unhide).  I can work something
>> up soon.  Is there a release version I should be targeting?
>
> The next release will be Org 10.0.
>
>> Simple demo with both features:
>>
>>  (setq-local buffer-invisibility-spec '(org-hide)
>>              my/ov (make-overlay 0 0 nil nil t))
>>  (overlay-put my/ov 'invisible 'org-nada)
>>  (cursor-sensor-mode 1)
>>
>>  (defun my/appear-sensor (_win _pos type)
>>    (if (eq type 'entered)
>>        (let ((beg (1- (previous-single-property-change (1+ (point)) 
>> 'cursor-sensor-functions)))
>>              (end (next-single-property-change (1- (point)) 
>> 'cursor-sensor-functions)))
>>          (move-overlay my/ov beg end)
>>          (setq cursor-type 'bar))
>>      (setq cursor-type 'box)
>>      (move-overlay my/ov 0 0)))
>>
>>  (let* ((star (propertize "*" 'invisible 'org-hide 'rear-nonsticky 
>> '(invisible)))
>>         (ent (propertize (concat "FOO" star) 'cursor-sensor-functions 
>> '(my/appear-sensor))))
>>    (dotimes (_ 3) (insert "\n" "Some " star ent " or another")))
>
> This feels weird:
>
> 1. Only one star gets revealed

Small mistake (in one direction, from left; see below).

> 2. Moving -> out of the emphasis followed by <- feels not right

Is that because point moves to the position it would have occupied if
there were no `*' at all?  Maybe you prefer the movement to "stay
adjacent" to the formerly hidden-marker text.

If you comment out the overlay moves, you'll see that this type of
motion is more awkward with cursor-only changes, as point seems "not to
make progress" as you move out from the hidden text.  Some people might
prefer that behavior, so it could be an option.  Or could just:

- Unhiding markers?  Moving out keeps point adjacent.
- Just changing cursor?  Moving out continues naturally.

Please try the below demo command `my/try-inside'.  This version fixes
both issues you noticed, and handles edits at the boundary better
(though in real org, font-lock would supersede this).

If people like how this looks, I can work something up for org v10.

Questions:

- A feature branch on savannah, or mailing list patches?

- A separate file (thinking `org-inside.el' or similar), or implement
  within `org.el'?  I guess either way the font-locking support would
  need to be there.

Options I'm considering:

- A minor mode users can enabled/disable (would turn off/on
  cursor-sensor-mode).  Or this could require `org-mode-restart'.

- A custom var to configure desired options when "inside": cursor change
  (if desired, including cursor type and/or face), marker unhiding.

Ideas welcome.

++++
;;;  -*- lexical-binding: t; -*-

(defvar-local my/try-inside-overlay nil)

(defun my/appear-sensor (_win _pos type)
  (if (eq type 'entered)
      (let ((beg (1- (previous-single-property-change (1+ (point)) 
'cursor-sensor-functions)))
            (end (next-single-property-change (point) 
'cursor-sensor-functions)))
        (move-overlay my/try-inside-overlay beg end)
        (setq cursor-type 'bar))
    (setq cursor-type 'box)
    (move-overlay my/try-inside-overlay 0 0)
    (setq disable-point-adjustment t)))

(defun my/try-inside ()
  (interactive)
  (let ((buf (get-buffer-create "*org-hidden-test*")))
    (with-current-buffer buf
      (erase-buffer)
      (delete-all-overlays)
      (my/try-inside-mode 1)
      (insert "* Move point in and out of the text FOO below:\n")
      (let* ((front-star (propertize "*" 'invisible 'org-hide 'rear-nonsticky 
'(invisible)))
             (back-star (propertize "*" 'invisible 'org-hide
                                    'rear-nonsticky '(invisible 
cursor-sensor-functions)))
             (ent (concat front-star
                          (propertize (concat "FOO" back-star)
                                      'cursor-sensor-functions 
'(my/appear-sensor)
                                      'front-sticky 
'(cursor-sensor-functions)))))
        (dotimes (_ 3) (insert "\n" "Some " ent " or another"))))
    (pop-to-buffer buf)))

(define-minor-mode my/try-inside-mode
  "Demo mode for org-inside."
  :global nil
  (setq my/try-inside-overlay (make-overlay 0 0 nil nil t))
  (overlay-put my/try-inside-overlay 'invisible 'org-nada)
  (setq-local buffer-invisibility-spec '(org-hide))
  (cursor-sensor-mode 1))

Reply via email to