Beorg removes empty lines between headings on sync

From what I understand Beorg should not remove the empty lines between subtrees i.e.

** Level 2

** Level 2

                           < empty space

** Level 2

** Level 2

but when I update an item from the agenda screen, sync via dropbox, and revert the buffer in Emacs the space between my headings is removed:

 * Level 1

** Level 2

** Level 2

** Level 2

** Level 2

This makes it more difficult to read my file as I prefer some empty space to delineate the subtrees.


This is on my list of things to improve. I think there is another forum topic about this. Currently beorg does remove leading and trailing blank lines from what it thinks are the ’notes’ sections which is causing your blank lines to disappear. Ideally I want to allow users to specify that they like a certain number of blank lines to delineate headlines so that when you add new items in beorg it will format it for you automatically.


Cool, I will look forward to that feature.


How are we doing on this? I use one main org document and use spaces to make things clearer. It’s really frustrating that Beorg deletes them all.


You can add the following to your init.org to have beorg add newlines between headlines:

(set! beorg-add-newline-between-headlines #t)

Let me know how you get on with that and if it improves things for you.


Thank Matthew, but that doesn’t seem to make any difference?


Ok my bad! I forgot to wrap it in src!

It does work, thank you.

Is there a possibility to change the blank line at different level headers or have it only create a blank line at certain level headers?


That sounds like it would be a good enhancement. This isn’t currently possible, but I’ll consider this in the future.


Dear Matthew, is there a way to disable this auto formatting? I like to edit my file manually on my computer and may add a newline or not on a specific header. I sometimes prefer different number of newlines so I do it manually, but now when I sync with Beorg and edit the file in it, it removes those newlines, so is there a way to simply disable this feature? Thanks!


Currently there isn’t a way to do this unfortunately. When beorg reads a file it converts it into a representation of what was in the file and then when you make an edit it converts that representation back into text and saves to the same file - so there will always be some level of auto formatting. If you can provide some examples of different ways in which you prefer headlines to be spaced out I can have a think whether that detail could be captured in the representation and then replicated when saved.


Dear Matthew,

First of all, thanks a lot for such an amazing app! Can I offer any help to address this issue free of charge? I was struggling with it too recently. I was researching some workarounds, but didn’t find any good ones. I am a software engineer at Microsoft with 20 years of experience (https://www.linkedin.com/in/anton-dergunov/). I would be happy to try to fix this issue (potentially some other issues) completely free of charge!


“If you can provide some examples of different ways in which you prefer headlines to be spaced out…”

I have 2 ideas.

  1. I see that the following mode was recently added:

(set! beorg-add-newline-between-headlines #t)

I have tested that, but it inserts a newline for every headline. In the original ticket they were asking about the following representation instead:

** Level 2

** Level 2

                           < empty space

** Level 2

** Level 2

So one option could be adding something like:

(set! beorg-add-newline-between-level0-headlines #t)

That option would actually satisty my use case perfectly, because I structure my files like this:

** TODO Task 1

** TODO Task 2

** TODO Task 3

** TODO Task 4

  1. Another idea is a more general implementation. I would guess you store the data as some form of a tree for intermediate representation. I think it could be possible just to introduce there a node to store any newlines explicitly. I know you also consider edits to the internal representation, and that may include movement of nodes. But I think that having these newlines as nodes in the tree would work reasonably well even in this case.

I am happy to help with the implementation of any of these approaches if that’s useful. Or also happy to chat about this topic. Thanks again for your amazing app!


Thanks Anton for some ideas!

Matthew, on my side, I think I would prefer a more general implementation of dealing with this. 

Maybe having a way to “auto format” or not would be useful? Like adding a file property per file and having a default global value from the ini.org file. Or when the beorg-add-newline-between-headlines is set to nil, then Beorg wouldn’t change the amount of newline that are inserted manually

To give you some example of how I write my file:

I’m working with some clients, so I could put my todos like: 

* Client 1
** TODO do that
** TODO do that
** TODO do that

* Client 2
** TODO do that
** TODO do that

  

Or, sometimes I have project or different categories that I would put before my client headers or a feature I’m developing would be a with multiple actions that I need to do to make this feature work, like:       

* Project 1

** Feature 1
*** TODO do that
*** TODO do that

** Feature 2
*** TODO do that
*** TODO do that

* Project 2

** Feature 1
*** TODO do that
*** TODO do that

** Feature 2
*** TODO do that
*** TODO do that

And has you can see from this last one, I added some more spaces before the “Project 2” header to make some emphases and better see it coming when scrolling inside the text file


Thank you, Guillaume! As an engineer, I understand the challenge of supporting all the various types of formatting in the app (how many newlines, where to insert them). This becomes a bit more complicated when you add new tasks or projects. Say, for your example, my second implementation idea would work (which is storing these newlines explicitly in the internal representation). It becomes a bit more complex when you change the order of these projects/features in the application or add new projects/features/tasks. How many spaces should the app add in this case, and how can it guess?

I think that this request could potentially be solved with 2 ideas that I have described above. Let me elaborate them a bit more:

  1. Simply specify the number of newlines to use per level. Right now you can specify 

(set! beorg-add-newline-between-headlines #t)

It makes sense to add the following:

(set! beorg-add-newline-between-level0-headlines #t)

Maybe even (set! beorg-add-newline-between-level1-headlines #t)

That would actually satisfy my use case perfectly, I would not need anything else.

  1. The second approach is more general. Matthew is saying “beorg reads a file it converts it into a representation of what was in the file”. I think the newlines are simply dropped in this internal representation. I think it could be possible to keep them. Either like that:

** Subnode “1 newline” 

** Subnode “Feature 1”

*** Subsubnode “TODO 1”

*** Subsubnode “TODO 2”

** Subnode “1 newline”

** Subnode “Feature 2”

(Alternatively it may be possible to simply store the number of preceding empty lines per every node.)

And when you save that to a file, you can access these newline subnodes and write them back. But this opens the following questions:

A. What if you swap Feature 1 and Feature 2?

  I think in this case you could just drag the preceding newlines, so it becomes:

** Subnode “1 newline” 

** Subnode “Feature 2”

*** Subsubnode “TODO 1”

*** Subsubnode “TODO 2”

** Subnode “1 newline”

** Subnode “Feature 1”

B. What if you create a new item? Should it have preceding newlines.

  I think the solution could be to simply insert as if there were no newlines.

While this may sound complicated, I think that it’s all doable, and I would be happy to contribute if I could.

Otherwise, I was thinking to just ditch the newlines from my org files entirely. My goal is to be able to edit these org files effectively in Emacs, so I need to have some structure. I was also thinking about making the top headlines more visible somehow. I know I can assign bigger font for them, but it still does not look nice. I was looking for a way to insert some extra vertical space for them, but could not find a way yet. I have also created a quick Emacs script to recover the newlines after I saved them in Beorg, but that’s of course not the ideal solution.


Currently my workaround is the function in Emacs below to recover the newlines before level-1 headlines after I have edited any files in Beorg. It reads all org files and recovers them. Not an ideal solution, but hopefully there could be some support in Beorg… :-)

 

** F7 to Reinsert Empty Lines
#+begin_src emacs-lisp
  (defun reinsert-empty-lines-in-org-files ()
    "Reinsert empty lines before first-level headers in all files listed in `org-agenda-files`."
    (interactive)
    (let ((org-files org-agenda-files)
    (modified-files '())
    (total-changes 0))  ;; Track total lines changed across all files
      (dolist (file org-files)
  (with-temp-buffer
    (insert-file-contents file)
    (goto-char (point-min))
    (let ((changes 0))  ;; Counter for the current file
      ;; Insert two newlines before each level-1 header
      (while (re-search-forward "^\\* " nil t)
        (unless (save-excursion
      (forward-line -1)
      (looking-at-p "^\\s-*$"))  ;; Check if the previous line is empty
    (save-excursion
      ;; Move point two characters back, to insert before the "* " header
      (goto-char (- (point) 2))
      (insert "\n"))
    (setq changes (1+ changes))))  ;; Increment change counter
      ;; If changes were made, write the file and record it
      (when (> changes 0)
        (write-region (point-min) (point-max) file)
        (push (cons (file-name-nondirectory file) changes) modified-files)
        (setq total-changes (+ total-changes changes))))))
      ;; Show results in a new buffer
      (let ((output-buffer (get-buffer-create "*Org File Changes*")))
  (with-current-buffer output-buffer
    (erase-buffer)
    (insert (format "Modified files and line changes:\n\n"))
    (dolist (file-change modified-files)
      (insert (format "File: %s, Lines changed: %d\n" (car file-change) (cdr file-change))))
    (insert (format "\nTotal lines changed: %d" total-changes)))
  (display-buffer output-buffer))))

  (global-set-key [f7] 'reinsert-empty-lines-in-org-files)
#+end_src

Well, I understand as well the challenge of supporting all the various types of formatting, which is not what I’m asking. And actually, what I’m thinking is actually the opposite, I think it would be simpler to not auto format the headers and just keep the newlines as part of the content section of the header. This is how the newlines are interpreted in org-mode, for example, when we do a refile the newlines follow at the same time.

So my ideas would be to simply make it possible to disable the auto formatting so the newlines are kept as the content of the header.

The (set! beorg-add-newline-between-headlines #t)could be used for when we add an item from the Beorg UI (like the “add item” button)

Or another idea if we want to make it more configurable would be to make it possible to set beorg-add-newline-between-level0-headlines and beorg-add-newline-between-level1-headlines to a specific number of newlines (this one would be used by default) and also to make if possible to change the value from a file property so this can be changed from file to file


I agree, keeping the newlines as part of the header seems like a good solution. That would work perfectly in my case. If I could help somehow with these updates, I would be very happy! (I think that would just require an update when reading the files (keep the newlines as part of the internal representation) + output them to the file. We also need to consider the case of moving headlines or adding/removing, but I am fine with any behaviour here, ideally consistent to org mode implementation in Emacs.)


Great to see the detail in the above discussion. I will put some more thought into how best to accommodate these requirements.


I have been doing some work on this. It needs a little more testing, but seems to be working well.

I’ve defined two new Scheme variables:

  (defvar beorg-auto-lines-before-headlines #f
          "If #t then beorg will automatically add newlines before headlines, depending on the value of beorg-newlines-before-headlines. If #f then beorg will respect the number of lines before headlines already in a file, and only use beorg-newlines-before-headlines for new items.")

  (defvar beorg-newlines-before-headlines '(1)
          "The first item in this list is the number of blank lines to add before a first level headline, the second item the number of blank lines before a second level heading, etc. The last item in the list is the number of blank lines to add before all other headlines.")

This will probably be the default. It will add a blank line above each headline, regardless of what level it is. However if there are, for example, already 3 lines above a headline then it will remember that and reproduce those blank lines when it saves a modified version of the file.

If you wanted beorg to autoformat a file such that level 1 headlines always had 3 lines above them, level 2 headlines 2 lines, level 3 1 line and all other levels 0 blank lines you would add the following to your init.org:

(set! beorg-auto-lines-before-headlines #t)
(set! beorg-newlines-before-headlines '(3 2 1 0))

That’s super exciting and exactly fits my needs. Actually, either of these two options would work wonders for me (the first one, beorg-auto-lines-before-headlines, being the preference). Let me know if I can help beta-testing that. Otherwise, looking forward to the new version. Thanks a lot! :-)


If anyone would like to help test this please raise a ticket and confirm the email address to send the test invite to.


Thank you, Matthew! I have just opened a ticket and provided my email address: https://appsonthemove.freshdesk.com/support/tickets/33584


Thanks Matthew for the new feature! I’m looking forward to trying this!

I just opened a ticket as well for my email to test!

Thanks and all the best


Thanks again, Matthew, for the awesome new Scheme variables. Sorry for delay with testing (I had flu), but I was just able to test it. TLDR: It works great, I found no issues and it works even better than I expected.

Long story - this is what I have tested:

  1. Just setting (set! beorg-auto-lines-before-headlines #t)

Actually, I think this is the default behavior now. It works perfectly. I tried updating tasks from the Agenda view and from the Files view - in both cases the newlines are respected (I was double checking the same files in Dropbox in VSCode).

I also tried removing, swapping tasks, adding tasks - it worked as expected.

  1. Tried setting just for fun: (set! beorg-newlines-before-headlines ‘(3))

It also worked as expected. Small observation though: I think Beorg was treating this as ‘(3 3 3 3) instead. Meaning that when I have added a sub-headline, it also got 3 leading whitespaces. I changed this to ‘(3 0 0 0) and it now started working as expected.

For my personal taste, I have set the following:

(set! beorg-auto-lines-before-headlines #t) (set! beorg-newlines-before-headlines ‘(1 0 0 0))

And it works wonders for me! :-) Thanks again for great support.

I also think, based on my testing, that this is the current default, and I think it definitely makes sense.

Let me know if I can help with anything else. :-) I can also keep sharing some suggestions for improvements in Beorg (but really, with these changes, the app is so massively useful for me, any other small issues I encountered - they were just minor peculiarities).


Great to hear it is working for you. With regard beorg-newlines-before-headlines the last number in the list covers all headline levels not already specified. So in your example you can just write:

(set! beorg-auto-lines-before-headlines #t)
(set! beorg-newlines-before-headlines '(1 0))

This feature will be paired with a new advanced settings UI which allows for customising of many Scheme variables without needing to create an init.org, hopefully bringing these kinds of features to a wider audience.


Hello, firstly thanks a lot for the updates. As someone who uses 1 newline between all headings, I’ve been using the older option “beorg-add-newline-between-headlines” up until this last october update, and now use the new

(set! beorg-auto-lines-before-headlines #t)
(set! beorg-newlines-before-headlines '(1))

options.

I recently discovered a bug where this option is not respected. If I make a change to a heading from the Beorg Agenda view(single tapping an entry, changing State from TODO to DONE), it will wrongly remove the newline before the heading.

The strange part is, if I do the same change in the Beorg Notes view instead (single tapping the file, single tapping the heading in the outliner, same menu as in agenda view appears, doing the same change there), no newline is removed(correct behavior).

I hope it can be reproduced.


@sxwpb thanks for reporting this issue, and apologies for slow approval of your comment - the system I use seems to almost select comments at random to put into the approval queue. I’ll take a look and see if I can reproduce this.


Hey, just wanted to say thanks for this new feature. I love beorg but found myself resisting adding TODOs and notes on the go because it would mess up my formatting. This update solves the problem. A genuine thank you for prioritizing this.


Thanks for the reply. Regarding the comment approval, it was actually my fault, I somehow completely missed the clear banner that pops up after commenting, that says the comments need to be approved. My apologies.

Download now for iPhone and iPad

Follow us on Mastodon and Bluesky

Privacy Policy | Press Kit