nobiot / org-transclusion

Emacs package to enable transclusion with Org Mode
https://nobiot.github.io/org-transclusion/
GNU General Public License v3.0
942 stars 48 forks source link

Fringe indicator not shown upon loading buffer #126

Open cashpw opened 2 years ago

cashpw commented 2 years ago

What did you expect to happen?

I expect the fringe I have configured (see below) to appear after loading a file containing a transclusion. The transcluded text in the image below begins with "This is a new thing" and ends with "#+end_quote".

What actually happened?

The transclusion was unadorned (see below) in the fringe and looked as if it were any other bit of text in the file. I was able to see the fringe indicator only after removing (org-transclusion-remove) and adding (org-transclusion-add) it again.

  1. 2022-01-17-20-57-44_screenshot
  2. Move (point) over the transclusion.
  3. M-x org-transclusion-remove
  4. M-x org-transclusion-add
  5. 2022-01-17-20-52-44_screenshot

    Relevant config

I am running Doom Emacs with the following config:

;; packages.el
(package! org-transclusion)

;; config.el
(use-package! org-transclusion
  :after org
  :config
  (setq
   left-fringe-width 14
   org-transclusion-exclude-elements '(property-drawer
                                       keyword)
   org-transclusion-extensions-loaded t
   org-transclusion-extensions '(org-transclusion-src-lines
                                 org-transclusion-font-lock
                                 org-transclusion-indent-mode))
  ;; Re-load extensions to activate `org-transclusion-indent-mode'.
  (org-transclusion-load-extensions-maybe t)
  (add-hook! 'org-mode-hook 'org-transclusion-mode)
  ;; (set-face-attribute
  ;;  'org-transclusion-fringe nil
  ;;  :foreground "white"
  ;;  :background nil)
  (define-fringe-bitmap 'org-transclusion-fringe-bitmap
    [17 34 68 136 68 34 17]
    nil nil 'center))

Versions

nobiot commented 2 years ago

Thanks for using Org-transclusion.

I cannot reproduce the issue on my end. I tested with a minimal set up with only org-transclusion and relevant part of your conifg. See the image and code below.

Screenshot from 2022-01-18 11-53-08

I don't use Doom so don't know exactly what use-package!, add-hook! do, but I think it's safe to say your issue is caused by the loading sequence. Ensure to load org-transclusion before define-fringe-bitmap. I suspect it may be done after your custom bitmap definition and thus org-transclusion overrides it.


Script for minimal setup I used:

As noted in the comment of the script, I removed my own config directory and files, and did `emacs -l load-org-trasnclusion.el (the filename of this script).

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

;; Test after removing config files
;; In terminal:
;;    $ emacs -l load-org-trasclusion.el

(package-refresh-contents)
(package-install 'org-transclusion)
(add-hook 'org-mode-hook #'org-transclusion-mode)
(with-eval-after-load 'org-transclusion
  (define-fringe-bitmap 'org-transclusion-fringe-bitmap
    [17 34 68 136 68 34 17]
    nil nil 'center))
cashpw commented 2 years ago

Thank you for investigating! I'm afraid I'm rather new to emacs and haven't been able to dig up much more in my own debugging. I have loaded emacs with a minimal Doom configuration; however, the issue persists. My assumption is that there is some code either in Doom or provided by Doom which overrides the fringe properties of the transcluded text.

One oddity: The fringe bitmap does show up as soon as I make changes to and save the file in question. Not sure what to make of that.

cashpw commented 2 years ago

2022-01-18-06-12-59_screenshot

The fringe bitmap which indicates the transclusion source is visible when I first load the file.

nobiot commented 2 years ago

Yes. The source one uses a different fringe bitmap and you don't change it, so I don't think it is related.

My guess is that before your custom bitmap appears, the standard one is actually used. It's just not visible against the dark background of the theme you use.

nobiot commented 2 years ago

I think you need to move this hook definition elsewhere, outside the org-transclusion part of use-package! or add it to :init part.

(add-hook! 'org-mode-hook 'org-transclusion-mode)

Notice in my config add-hook is not included in eval-after-load?

I think you want to activate org-transclusion in every org file you visit. Does it actually work in the very first org you visit immediately after you launch Emacs?

The way you put add-hook! looks a bit odd to me. The hook would get added only after the org-transclusion has been loaded first time. But this does not happen until you load org. So the sequence seems to me like this:

You launch Emacs -> You visit an Org file -> Emacs loads Org -> Emacs loads org-transclusion -> Emacs add-hook -> Control returns to you. It’s just adding a hook, not activating org-transclusion-mode. You then need manually do it. The second org file onwards, the hook is active so transclusion-mode turns on automatically.

I can’t tell why bitmap gets does not get changed in the first call to org-transclusion.

nobiot commented 2 years ago

Okay, I can reproduce your issue on Doom but I cannot on my vanilla Emacs. I now suspect there might something different between the two in the way Emacs loads org-indent-mode and the extension org-transclusion-indent-mode.... I cannot be sure.

I'm sorry but it's really hard to support Doom users properly; it's too complex for me.

rtrppl commented 2 years ago

I may have a similar issue with plain Emacs (not using Doom). I was able to change the color for the fringe of the source, but not for org-transclusion-fringe. Is there a setting that could override org-transclusion-fringe? My apologies, if this is an unrelated issue. I am using the "zenburn" theme.

Bildschirmfoto 2022-01-22 um 22 30 27

Bildschirmfoto 2022-01-22 um 22 34 05

I love the idea of this for writing a non-fiction book!

rtrppl commented 2 years ago

Quick follow-up: It works for me if I turn on the "indent-mode" of the org-transclusion-extensions.

Bildschirmfoto 2022-01-23 um 09 29 15
nobiot commented 2 years ago

Thank you. I think your issue is unrelated but Id like to investigate further. Do you use the built-in org-indent-mode? It does not look like you do from the screen shots. it’s a little strange that you would have to turn on this extension…

rtrppl commented 2 years ago

I actually do use it. There was just no headline in the screenshots above. After adding one, I do see another weird thing: if I open the transclusion, the indent in the source is lost.

Bildschirmfoto 2022-01-23 um 09 46 48
nobiot commented 2 years ago

I see; that explains. Thank you. org-indent-mode rather aggressively inserts the indentation, and I have struggled to support it (it was not supported originally and later added it only as an extension).

At the moment, unfortunately losing the source’s indentation is an expected behavior and limitation. I will need to add it to the user manual as a known limitation…

rtrppl commented 2 years ago

Thanks for the response. It does not bother me but org-transclusion also seems to introduce a first-line indentation.

Bildschirmfoto 2022-01-23 um 13 43 08

jlcolbert commented 2 years ago

I have a Doom solution:

(use-package! org-transclusion
  ;; :defer t
  :after org
  :init   ; you technically don't need to put map! in this :init section, you could put it outside the use-package! declaration
  (map!
    :map "<f12>" #'org-transclusion-add ; you don't need global-map with the map! macro
    :leader
    :prefix "n"
    :desc "Org Transclusion Mode" "t" #'org-transclusion-mode)
  :config
  (add-to-list 'org-transclusion-extensions 'org-transclusion-indent-mode)
  (custom-set-faces! `(org-transclusion-fringe ; the backwards tick as opposed to apostrophe is *crucial*
                        :foreground ,(doom-color 'green)
                        :background ,(doom-color 'green))))

To set the fringe colors, you need to use custom-set-faces!. To make sure it fits well with your theme, use doom-color plus the name of the color you want. I cycled through light and dark themes, and the green changed appropriately for each one. I imagine it would work fine with whatever other colors you choose.

You don't need to explicitly require the indent extension after adding it to the list. At least, things still work fine when I don't. And you can either explicitly defer the package until you call it, or you can have it load after org. Both worked fine.

When I tried using a hook to load in every org buffer, I would have to disable the mode and enable it again in order for it to work. Having the mode off until called works fine for my workflow.

nobiot commented 2 years ago

@jlcolbert Thank you for sharing this!

jlcolbert commented 2 years ago

@nobiot No problem! Here's my full configuration with the keybindings:

(use-package! org-transclusion
  :defer t
  :config
  (add-to-list 'org-transclusion-extensions 'org-transclusion-indent-mode)
  (custom-set-faces! `(org-transclusion-fringe
                        :foreground ,(doom-color 'green)
                        :background ,(doom-color 'green)))
  (map! :map org-transclusion-map ; if you put :after org-transclusion in this map declaration, you don't need to put it in use-package!
    :prefix "C-c"
    [backtab] #'org-cycle ; Doom has `org-toggle-inline-images' bound to C-c TAB, but has `org-cycle' bound to global TAB in evil normal state
    "D" #'org-transclusion-demote-subtree
    "O" #'org-transclusion-move-to-source
    "P" #'org-transclusion-promote-subtree
    "d" #'org-transclusion-remove
    "e" #'org-transclusion-live-sync-start
    "g" #'org-transclusion-refresh
    "o" #'org-transclusion-open-source))

(map! "<f12>" #'org-transclusion-mode
      :leader ; in Doom the leader key is SPC (if you have evil enabled)
      (:prefix "n"
        (:prefix ("T" . "transclusion")
          :desc "add" "a" #'org-transclusion-add
          :desc "add all" "A" #'org-transclusion-add-all
          :desc "make from link" "m" #'org-transclusion-make-from-link)))

I will continue to play around with the bindings to see if I can get them all in one declaration, but I don't claim to know how a lot of this works beyond reading the docs and playing around until something sticks.

vleonbonnet commented 1 year ago

@nobiot

Thanks for using Org-transclusion.

I cannot reproduce the issue on my end.

I am able to reproduce this issue on vanilla Emacs as well, you can use the following configuration:


;; Test after removing config files
;; In terminal:
;;    $ emacs -l load-org-trasclusion.el

(package-refresh-contents)
(package-install 'org-transclusion)
(add-hook 'org-mode-hook #'org-transclusion-mode)
(with-eval-after-load 'org-transclusion
  (define-fringe-bitmap 'org-transclusion-fringe-bitmap
    [17 34 68 136 68 34 17]
    nil nil 'center))

(custom-set-variables
 '(org-startup-indented t)
 '(org-transclusion-extensions
   '(org-transclusion-src-lines org-transclusion-font-lock org-transclusion-indent-mode))
   )
ahmed-shariff commented 1 year ago

I also have the same issue, but I don't use org-indent. I was playing around to see what was happening:

The org-transclusion-content-insert function seems to be setting the line-prefix and warp-prefix for the corresponding region as text-properties for the transclusion region. But uses the overlays to modify that for the source region. After transcluding, when checking the text-properties of the tranclusion region, line-prefix and warp-prefix are nil. I don't fully understand how font lock and text properties work, but I am assuming this is why the source buffer has the fringe and the tranclusion buffer doesn't. With the cursor on the tranclusion region, if I do the following:

(overlay-put (text-clone-make-overlay (marker-position (get-text-property (point) 'org-transclusion-beg-mkr)) (marker-position (get-text-property (point) 'org-transclusion-end-mkr)) (current-buffer)) 'wrap-prefix (org-transclusion-propertize-transclusion))

(which is using overlay to set the line-prefix and warp-prefix by extracting other values in the text properties) I get the fringe in the buffer.

As a workaround, I am doing the following:

  (defun org-transclusion-content-insert-add-overlay (beg end)
    "Add fringe after transclusion."
    (overlay-put (text-clone-make-overlay beg end (current-buffer))
                 'line-prefix
                 (org-transclusion-propertize-transclusion))
    (overlay-put (text-clone-make-overlay beg end (current-buffer))
                 'wrap-prefix
                 (org-transclusion-propertize-transclusion)))

  (add-hook 'org-transclusion-after-add-functions #'org-transclusion-content-insert-add-overlay)
ahmed-shariff commented 1 year ago

@nobiot is it worth refactoring so that adding the fringe is done with the overlay functions instead of text-properties?

nobiot commented 1 year ago

@ahmed-shariff Thanks for the workaround and sharing. Much appreciated.

I have to ask what is your "same issue" is.

This thread has been dormant for a while, and I can see there were multiple issues (albeit being similar) discussed above. If you are so inclined, I'd appreciate if you could open an new issue with a fresh description of what it is that your workaround addresses.

Having said this, however, I am sorry that I don't have much capacity right now to deep-dive into the issue. I imagine it would not be trivial. My gut is at the moment inclined to saying it is probably not worth refactoring to switch from text-props to overlays. An overlay is already added back recently (so now we have both) with https://github.com/nobiot/org-transclusion/commit/bc24be23348a6849868b6c49b865e56a175b50c5:

image

The green color is a face to the overlay, while the fringe's vertical line comes from the text-props. I think you could play with it to add the line- and wrap-prefix.

I had switched from overlays to text-properties some time before adding the overlay back. My notes do not really give me much as to why the removal (my bad), but I believe it is related to the behavior with undo. Text-props are part of the text, so they are in sync with the text when you undo -- you can undo org-transclusion-add. The behavior of having overlay only will be anti-intuitive especially when you use the live-sync function and undo together.

nobiot commented 1 year ago

This commit 4f9b8fa from around 2 years ago and before v1.0.0 already introduced some feature to cater to text-property for yanking from the live-sync. Just reinforcing my gut feel that switching from text-prop to overlay would be unlikely to be trivial. Just FYI @ahmed-shariff

ahmed-shariff commented 1 year ago

Thank you for the quick reply. Apologize for necroing this thread, I'll open a new issue for this discussion.