kkinnear / zprint

Executables, uberjar, and library to beautifully format Clojure and Clojurescript source code and s-expressions.
MIT License
547 stars 46 forks source link

"Smart" comment changes feedback #297

Open NoahTheDuke opened 1 year ago

NoahTheDuke commented 1 year ago

Hey Kim!

.zprint.edn, redacted for brevity and private-code reasons:

{:style [:how-to-ns :community]
 :map {:comma? false :sort? false}
 :list {:option-fn ...}
 :vector {:wrap-after-multi? false}
 :fn-map {...}}

I've run zprint 1.2.6 over my company's codebase, which has been using 1.2.5 since release. There are 176 files changed, all of the changes are comment changes, and the changes are somewhere between "changes for the sake of changes" and actively worse. Here are some samples from where the comment changes feel worse with little to no benefit. (I've done my best to obfuscate sensitive info with abcdefg with the same length so you understand the shape.)

Removing line breaks. In many places, the line break was meaningful to the author so removing it hasn't improved the comment. In the occasional place, it "fixes" an issue of the comment being incorrectly formatted by a previous zprint version, but then it reflows the entire comment.

-  ;; Optimization
-  ;; Get combined records and save in batches
+  ;; Optimization. Get combined records and save in batches
         ;; another in qwerty records. For example, if this source is
-        ;; Abcdefghijk,
-        ;; its data will still be nested under the abcdefg qwerty records.
-        ;; But deleting for abcdefg will cascade and remove all qwerty company
-        ;; documents.
+        ;; Abcdefghijk, its data will still be nested under the abcdefg
+        ;; qwerty records. But deleting for abcdefg will cascade and remove
+        ;; all qwerty company documents.
-    ;; xxx-level account xxx rules (3) +
-    ;; aaa1 abdcs -> aaa2 + aaa2 abdcs -> aaa1 (2) +
-    ;; aaa1 abdcs -> aaa3 + aaa3 abdcs -> aaa3 (2)
+    ;; xxx-level account xxx rules (3) + aaa1 abdcs -> aaa2 + aaa2 abdcs ->
+    ;; aaa1 (2) + aaa1 abdcs -> aaa3 + aaa3 abdcs -> aaa1 (2)
                                           ;; TODO: Fix this. This is weird,
-                                          ;; despite the UI cooperating with
-                                          ;; it...
-                                          ;; The only status code we should show
-                                          ;; alongside a value is "OK"
+                                          ;; despite the UI cooperating
+                                          ;; with it... The only status
+                                          ;; code we should show alongside
+                                          ;; a value is "OK"
                ;; clj-wiremock is using some stuff from jetty related
-               ;; projects.
-               ;; This is forcing consistent jetty projects umbrella.
+               ;; projects. This is forcing consistent jetty projects
+               ;; umbrella.
-  ; {:org-id 123 :name "Abcde"} ->
-  ; [{:externalId 'external_org-id' :value "123"},
+  ; {:org-id 123 :name "Abcde"} -> [{:externalId 'external_org-id' :value
+  ; "123"},
   ;  {:externalId 'external_name' :value \"Sabre\"}]

Adding line breaks when the comment is under the line length (80). Sometimes it reflows the rest of the comment, and sometimes it doesn't.

-;;     (with-dynamic-redefs [apis.abcdefgh/get-abcdefghijklm (fn [_ _] [])]
+;;     (with-dynamic-redefs [apis.abcdefgh/get-abcdefghijklm (fn [_ _]
+;;     [])]
-    ;;TODO: The user that posted the message would also get the notification
+    ;;TODO: The user that posted the message would also get the
+    ;;notification
     ;;      We need to think about how to avoid this
-          ;;-------------------END RUN asd-asdfg-asdfghj job-------------------
+          ;;-------------------END RUN asd-asdfg-asdfghj
+          ;;job-------------------
-     ;; %2F is a slash (/). If there is a slash or other strange characters,
+     ;; %2F is a slash (/). If there is a slash or other strange
+     ;; characters,
      ;; we treat it as a separate domain, as maybe this is legitimate. We
 ;; We stash the original value of a function so we can monkey patch it and
 ;; restore from tests. As the feature is temporary, we have simply made
-;; changes severly local like this so we can remove the code with the least
+;; changes severly local like this so we can remove the code with the
+;; least
 ;; possible chance of introducing a regression
-; Old-style database component. This was originally in crossbeam.db. It was
+; Old-style database component. This was originally in crossbeam.db. It
+; was
 ; moved
-; here because it needs to use a function from pgdb, which created a circular
+; here because it needs to use a function from pgdb, which created a
+; circular
 ; reference.

Hope this helps.

kkinnear commented 1 year ago

First, thanks for taking the time giving me examples of what doesn't look good. It will definitely help me make "smart wrap" smarter. Plus, it looks like you encountered some outright bugs toward the end where it didn't flow comments together. When I get to the details, I'm hoping to be able to reproduce those, but it will be a day or two until I get there.

From a top level, you almost certainly know that you can get rid of all of this "smart" stuff by setting {:comment {:smart-wrap? false}}. So you can still get whatever utility that 1.2.6 provides without having to interact with any of this. Though I'm glad you didn't take that route immediately, since you have given me plenty to work on.

Also, if you are using smart wrap, you can get rid of the border by {:comment {:smart-wrap {:border 0}}}. So nothing will wrap until it is actually at the width (whatever width you use).

I'm wondering where you are with the entire idea of "smart wrap"?

  1. It is just dumb, and you don't want to use it. You gave me some things to show me why it is dumb, but you don't see any utility in it.
  2. It might be interesting if it didn't mess up so much, and you gave me some things to think about and fix so that, if I fixed them, you might be interested in using it.

If you are thinking #1, then thanks again for giving me some good examples of problems.

If you are thinking #2, then still thanks, and I'd be interested in working with you to improve the smarts of "smart wrap".

Some of the things will be a bit of a challenge, as your first example with Optimization is very similar to what smart wrap is designed to fix -- cases where the previous not so smart wrapping put a bunch of single words each on their own line. But in this case I can see that maybe if we have a single word that is capitalized, and the next comment's first word is also capitalized, then we wouldn't flow the second back up onto the first. There are already a bunch of heuristics like that in "smart wrap" already, and adding a few (or even a lot) more wouldn't be a bad thing.

In fact, I can see how to prevent all but the second problem in your first set of 6 problems.

I believe that all of your second set of problems would be prevented by your changing {:comment {:smart-wrap {:border 0}}}. That doesn't mean that I don't see some potential bugs in what is happening with the default border, but I believe that there would be no changes in your second set if you reduced the border to 0.

Thanks again for giving me this information to work with, I really appreciate it!

NoahTheDuke commented 1 year ago

Great reply, thanks.

I'm in camp #2; the places where poor changes are made are frustrating because I am on a big team and don't want to deal with merge conflicts or unnecessary work in CI to appease the formatter, but the concept of smarter comment formatting is welcome.

{:border 0} explains all of the "weirdness" I saw and I think that will clear up the majority of the unnecessary changes.

The first set of problems seems to me (purely from observation and your comment) to come from the smart wrapper trying to fix formatting foibles from previous versions of zprint. Maybe it shouldn't worry about that? Comment styles and formatting are generally deliberate and in my opinion seem outside the purview of zprint when they're within the line length.

For example, the pseudo code with arrows I posted, or the Observation "header", or the markdown-style numbered points with indentation to match, or the TODO with indentation to match.

On the other hand, that's an argument against code formatters in general lol, so maybe I should shut up. 😉

kkinnear commented 1 year ago

Thanks for the feedback!

Before I dive into why I did "smart wrap" at all, I want to mention that I forgot to mention {:style :minimal-smart-wrap} to you yesterday. In looking at your first set of problems, :minimal-smart-wrap appears to prevent most (maybe all?) of them. It is hard to tell, because it is kind of fiddly to test your problems since they are all dependent on exact spacing with respect to the width. But from a first pass of testing, it looks like you might find :minimal-smart-wrap to be a real help. It also sets the :border 0 as we discussed yesterday. It would be interesting to see what :minimal-smart-wrap does for you, not least since I created it thinking specifically about you and your desire to have minimal code changes after passing code through zprint!

Since you care, a bit of background on why I did "smart wrap" at all. It wasn't particularly because I wanted to fix up previous problems in the less-than-smart wrapping. There was an issue logged a while ago, #271, where it was pointed out that multiple formats of the same file fairly frequently ended up changing the file a couple of times until it settled down into a stable point. I found and fixed a number of problems that were causing that behavior, largely in the code formatting heuristics where they were, for lack of a better word, discontinuous. There are a lot of places where the number of lines something takes to format is compared this way against that way, and the shortest is considered "better". There were places in the heuristics where when the number of lines something took varied by a single line then a different heuristic would come into play and do things a lot differently. I fixed those as much as I could without totally changing everything.

But the part that was left was that, when a block of comments got moved to the right and exceeded the width, there would sometimes be multiple new lines added, since each line that exceeded the width became two lines. Since the code formatting heuristics are driven largely by line count, and comment lines count (yes, more on that later), then things might be very different the next time the file was formatted. Since the comment wrapping is done once, as a post processing pass, after all of the code formatting is completed.

The changes in smart wrap are largely to allow several lines to wrap when they have exceeded the width, but perhaps only add one total line to the file instead of a lot of very short lines. That minimizes the multi-run changes when no code changes have occurred. Then when the block of code moves back left on a later run (after some code changes), it doesn't look terrible either. And if it moves left "enough", it will be reformatted to take fewer lines.

And, yes, the "reformatted to take fewer lines" is also to clean up the problems from the dumb wrapping in the past.

I looked at having the code formatting not count comment lines, but that still wasn't going to fix up the problems in the past. It also was likely to be as big a change (or bigger) than the smart wrap on its own regarding existing files (like your codebase). It also didn't fix the dumb wrapping at all, which was really dumb. So I went for smart wrap instead.

Obviously I could still remove comment lines from consideration of source code formatting and its heuristics, and that might be a good thing to do at some point. (Which I'm sure you know is "engineer" for "not right now").

Anyway, I'm still working through your problems, but it would be very interesting to see if the number of changes decreased a lot if you used {:style :minimal-smart-wrap}.

Thanks for listening...

NoahTheDuke commented 1 year ago

The history and reasoning for this is completely understandable. Counting comment lines vs not counting them is hard! That's a tricky question.

{:style :minimal-smart-wrap} reduces the number of changed files to 36 and highlights a number of places where previous formatting did a bad job with a comment and fixes it which is great! Was hard to see these cases in the other diffs earlier. We'll use this going forward.

After looking at the new changes and working through some of the edge cases, the only feedback I have is that sometimes a comment has multiple paragraphs (ending with periods) with no empty line, which to me reads as "distinct thoughts". But then the smart formatting combines them:

   ;; so changes made within abcd-abcde-abcdefg.txt will be reflected upon
-  ;; deployment.
-  ;; I felt comfortable downloading from the abcdefghij abcde
+  ;; deployment. I felt comfortable downloading from the abcdefghij abcde

I can see why they're combined if the previous line doesn't end in a period, but I'm confused why they're combined when the previous line does end in a period. Can that be configured?

kkinnear commented 1 year ago

Three more comments...

First, I've analyzed the remaining set of problems, and it looks like :style :minimal-smart-wrap will help those out (in many cases because of its :border 0, but that is not all).

Second, I can't seem to reproduce this failure to be "smart" -- i.e., 'we treat it ...' should flow up to follow 'characters,' whenever 'characters, ' wraps, and for me it does.

-     ;; %2F is a slash (/). If there is a slash or other strange characters,
+     ;; %2F is a slash (/). If there is a slash or other strange
+     ;; characters,
      ;; we treat it as a separate domain, as maybe this is legitimate. We

Whenever 'characters' wraps, then the next comments flow up to follow it. Which is odd, given I've tried to use as much of your config as you've shared. Not a big deal., as :minimal-smart-wrap should also fix this by not wrapping 'characters'. But it is interesting and a bit disturbing.

Unless this is a top level comment? It doesn't look to be so, but that would explain it.

These next two look to be top-level comments, and they are never smartly wrapped. But I see a bug, in that the :border 5 from "smart-wrap" is being used here to wrap these comments, and they will never be smart. That's a bug. In fact, it might well be that zprint should never wrap top level comments. Since it will never move them left or right, wrapping them may be a mistake. I'll have to think on that. Thanks a lot for sending me these problems!

 ;; We stash the original value of a function so we can monkey patch it and
 ;; restore from tests. As the feature is temporary, we have simply made
-;; changes severly local like this so we can remove the code with the least
+;; changes severly local like this so we can remove the code with the
+;; least
 ;; possible chance of introducing a regression

and

-; Old-style database component. This was originally in crossbeam.db. It was
+; Old-style database component. This was originally in crossbeam.db. It
+; was
 ; moved
-; here because it needs to use a function from pgdb, which created a circular
+; here because it needs to use a function from pgdb, which created a
+; circular
 ; reference.

Third, if you really think that zprint shouldn't be messing with comments, you can just say {:comment {:wrap? false}} and all comment wrapping will be gone. Which I hope you don't do, at least not before you try :minimal-smart-wrap on your codebase.

Thanks!

kkinnear commented 1 year ago

I'm glad that :minimal-smart-wrap did something useful for you. 36 files is a lot better than 176, and I'm pleased you see something worthwhile happening in at least some of the changes in the 36.

Regarding paragraphs and complete thoughts... The is some configurability in the smart wrap code, since it uses a bunch of regular expressions to decide what should be in a group of comments that can flow together and what should not. There is no code that looks at multiple lines and says "this looks like a paragraph". There are regular expressions for deciding what lines should be grouped together in a "comment group" and allowed to flow across newlines.

There is no regular expression for exactly what you want, but I can simulate it closely by adding an additional regular expression to finish off a comment group. Which would be what you want, but this set of regexs doesn't allow the line to flow either way with the previous lines. So it will disallow the following line to flow back up onto it (as you want), but it will also disallow the line with the period to flow back up to the one before it, or the one before it to flow down onto the line with the period. Which isn't really what you want, though it does work for your example:

zprint.core=> (print i297n)
(test-comment
  ;; so changes made within abcd-abcde-abcdefg.txt will be reflected upon
  ;; deployment.
  ;; I felt comfortable downloading from the abcdefghij abcde
  )

; The default

zprint.core=> (czprint i297n {:parse-string? true})
(test-comment
 ;; so changes made within abcd-abcde-abcdefg.txt will be reflected upon
 ;; deployment. I felt comfortable downloading from the abcdefghij abcde
)

; With a new style :comment-paragraph defined and used in the same call

zprint.core=> 
(czprint i297n
         {:parse-string? true,
          :style :comment-paragraph,
          :style-map {:comment-paragraph
                        {:comment {:smart-wrap {:end+skip-cg
                                                  [#"^;+\s*$" #"^;+\s*\(.*\)$"
                                                   #"^;+\s*[A-Z]\w+\:$"
                                                   #"[a-z][a-z]\.$"]}}}}})
(test-comment
 ;; so changes made within abcd-abcde-abcdefg.txt will be reflected upon
 ;; deployment.
 ;; I felt comfortable downloading from the abcdefghij abcde
)

I'm thinking that I will create a new style called :comment-paragraph that will do what you want, though it will still only look at a single line, not multiple lines.

If you add the above :comment-paragraph style to your style map in .zprint.edn, and then use it in your :style vector, when I release 1.2.7, you can keep it in your :style vector, and remove the definition from your :style-map and things should stay the pretty much the same.

My thinking is that the temporary style defined above will keep your paragraphs from running together, and then the permanent style will enable you to keep them that way long term. In my testing, there might be a small amount of comment wrapping change, since the line with the period is now not in the previous comment group, and one of the heuristics about wrapping involves the variance of the line lengths in a comment group -- which changes if you leave out a line. But it should not be much.

Thoughts?

NoahTheDuke commented 1 year ago

Interesting! I think that would work well for us. Thanks for all of the additional help.

kkinnear commented 1 year ago

I have just made the changes to actually have something ending in two lower case letters and a period terminate a comment group. Thus, the next line will not flow up onto the line ending with a period, but the period line will flow back and forth with its previous line as necessary.

Now I'm thinking that maybe this should just be the default for smart-wrap. It might keep things from flowing together when they might otherwise want to do so, but it isn't unreasonable to let you separate thoughts by putting a period and going to another line. Right now the only way to do that is with a blank line.

I'm not sure anyone beside you and I would notice the difference. And having one less style isn't a bad thing.

I'm guessing that you think this would be fine for everyone, but would be interested in any thoughts you have.

NoahTheDuke commented 1 year ago

Seems like a good default given how small the change is.

kkinnear commented 1 year ago

Looking over what the change with "line ending with two lowercase letters and period" did to the comments in the tests made me wonder if it was a good idea for a default. Then I realized that if zprint ever wrapped a line so that a word ending with a period became the last thing in a line, that would never go away. I wasn't wild about that as a default.

That said, I did make the change part of :minimal-smart-wrap, so that if you use that style, lines ending with a word and period will not end up with subsequent lines flowing up to them. I think it fits well with :minimal-smart-wrap.

I've also fixed the bug where top level comments were getting wrapped using the :smart-wrap border. I'm contemplating a quick release of 1.2.7 to get all of these changes out before a lot of folks adopt 1.2.6.

kkinnear commented 1 year ago

I just released 1.2.7. Thanks again for noticing the things that you did and doing the work to submit an issue with them. It helped me find both a very unfortunate bug and also rework some things so that it will work better for everybody, in addition to working better for your environment (which is one that I expect others share). It is always a pleasure to work with you.

You should be good with :style :minimal-smart-wrap.

NoahTheDuke commented 4 months ago

Hey Kim! My team dragged their feet so I'm just now attempting to update us to 1.2.8.

I've set the style to :minimal-smart-wrap and ran it over our codebase. Most everything looks good enough, some places that need help (mostly folks forgetting periods so reflowing ruins the implied sentence), but there are still some places where things aren't quite right according to what you suggested above.

It mainly seems to be that the logic for determining when to keep or remove a line break is inconsistent. I'll only post one example because they all look like this.

 (deftest all-overlaps-when-sharing-rules-change-test--multiple-pops
   ;; test scenario
-  ; Org 1 is using the overlaps endpoint.
-  ; Org 1 has two pops -- at least 1 record is exclusive to each pop (not the
-  ; same pops).
-  ; Org 2 has two pops, initially both visible and with full overlaps for org 1
-  ; initial call to overlaps endpoints returns all overlaps, on both populations
-  ; org1 stops sharing pop 1 with org 2 (not a default rule).
+  ; Org 1 is using the overlaps endpoint. Org 1 has two pops -- at least 1
+  ; record is exclusive to each pop (not the same pops). Org 2 has two pops,
+  ; initially both visible and with full overlaps for org 1 initial call to
+  ; overlaps endpoints returns all overlaps, on both populations org1 stops
+  ; sharing pop 1 with org 2 (not a default rule).
   ; Subsequent call to overlaps endpoint returns:

To describe what I'm seeing, there's a complete sentence on one line, a line break, a complete sentence that spans two lines, a line break, a complete sentence that spans three lines, a line break, and then a sentence fragment on one line that ends in a colon (there's a bullet point list after that).

All three complete sentences are reflowed into a single paragraph spanning 5 lines. The sentence fragment is left on its own line.

Based on what you said back in September, I would have expected that all lines ending in a period with subsequent lines starting with capital letters would be left alone. Maybe I misread you (you said you added it to smart-wrap's default, but it's possible it's not included in :minimal-smart-wrap).

Is there a bug here or have I misunderstood how :minimal-smart-wrap works or is there a configuration I'm missing?

Thanks so much for your tireless work.

kkinnear commented 4 months ago

Wow, good catch! That's a bug (well, two of them actually) in :minimal-smart-wrap. My apologies for testing it poorly. The real world is always more interesting.

The bugs:

  1. When looking for a period at the end of a line to end the comment group, the current code requires two lower case characters prior to the period. Two of your cases have ) prior to the period, and that causes them to not be detected as the period ending the line (at least for ending the comment group, elsewhere it is done differently when merging lines).
  2. When not in a comment group, the first comment starts a comment group. Which the "Org 1 is using the overlaps endpoint." does. However, the code that recognizes it as the start of a comment group doesn't check to see if it should also end the comment group immediately. Sigh.

I have worked with the other regexes to see if I can kind of trick it into doing the right thing regarding #2, and I can make this simple example come out ok, but I think it will not work perfectly in general. I can fix the #1 bug relatively easily with a change to the configuration. That will not, however, fix your problem, since the second the "... endpoint." will collect the next sentence due to bug #2.

The problem with doing the partial fix for #2 is that the last line with the "." will not be part of the comment group above it. That isn't necessarily terrible, so if you wanted to try that you could put this in as a definition of :minimal-smart-wrap in the :style-map:

{:minimal-smart-wrap
   {:comment {:smart-wrap {:border 0,
                           :end+skip-cg [#"^;+\s*$" #"^;+\s*[A-Z]\w+\:$"
                                         #"^;+\s*(\{|\(|\[|.*\)$|.*\}$|.*\]$)"
                                         #"\.$"],
                           :end-cg [#"\.$"],
                           :last-max 80,
                           :max-variance 200,
                           :space-factor 100}}}}

You have two choices:

  1. You can turn off :smart-wrap?, and wait for 1.2.9.
  2. You can try the above and see if you like it. It might work for you, and I am pretty sure that if you use it, it won't make things worse when I do actually fix this bug. I still need to work through some details, but I don't think the above change is actually the "correct" fix for this problem, but as I say, I don't think it will cause periods to end up not ending lines. That would be a problem when the right code comes along, as things would have flowed together.

I was about to release 1.2.9 (like today or tomorrow), but I'll hold it to fix this bug. It probably won't release this week (now), but hopefully early next week. For what that's worth.

kkinnear commented 4 months ago

I have fixed this in 1.2.9, so that your example now works correctly. My next task is to release 1.2.9, which will probably take a few days, but it expect it will be soon.

(czprint i297q {:parse-string? true :style :minimal-smart-wrap})
(deftest all-overlaps-when-sharing-rules-change-test--multiple-pops
  ;; test scenario
  ; Org 1 is using the overlaps endpoint.
  ; Org 1 has two pops -- at least 1 record is exclusive to each pop (not the
  ; same pops).
  ; Org 2 has two pops, initially both visible and with full overlaps for org 1
  ; initial call to overlaps endpoints returns all overlaps, on both populations
  ; org1 stops sharing pop 1 with org 2 (not a default rule).
  ; Subsequent call to overlaps endpoint returns:
  ;  o this
  ;  o is
  ;  o a
  ;  o test
  (stuff and bother))

When hacking your example to make it a bit less nice on input, I found that :minimal-smart-wrap wasn't all that lovely on output (to me at least, but then I like the default :smart-wrap). I created a new style :sentence-smart-wrap that looks better to me, and you might want to give it a try. You could probably do all of your code with :minimal-smart-wrap and then later do :sentence-smart-wrap and that would work. The reverse wouldn't work, :sentence-smart-wrap flows some things together that :minimal-smart-wrap won't "unflow", if that makes any sense.

Here is what I mean:

; Your basic test, with additional newlines

(print i297r)
 (deftest all-overlaps-when-sharing-rules-change-test--multiple-pops
   ;; test scenario
  ; Org 1 is using the overlaps endpoint.
  ; Org 1 has two pops -- at least 1 record is
  ; exclusive to each pop (not the
  ; same pops).
  ; Org 2 has two pops, initially both
  ; visible and with full overlaps for org 1
  ; initial call to overlaps endpoints returns all overlaps,
  ; on both populations
  ; org1 stops sharing pop 1 with org 2 (not a default rule).
  ; Subsequent call to
  ; overlaps endpoint returns:
  ;  o this
  ;  o is
  ;  o a
  ;  o test
  (stuff and bother))

; Minimal smart wrap

 (czprint i297r {:parse-string? true :style :minimal-smart-wrap})
(deftest all-overlaps-when-sharing-rules-change-test--multiple-pops
  ;; test scenario
  ; Org 1 is using the overlaps endpoint.
  ; Org 1 has two pops -- at least 1 record is
  ; exclusive to each pop (not the
  ; same pops).
  ; Org 2 has two pops, initially both visible and with full overlaps for org 1
  ; initial call to overlaps endpoints returns all overlaps, on both
  ; populations org1 stops sharing pop 1 with org 2 (not a default rule).
  ; Subsequent call to
  ; overlaps endpoint returns:
  ;  o this
  ;  o is
  ;  o a
  ;  o test
  (stuff and bother))

; Sentence smart wrap

(czprint i297r {:parse-string? true :style :sentence-smart-wrap})
(deftest all-overlaps-when-sharing-rules-change-test--multiple-pops
  ;; test scenario
  ; Org 1 is using the overlaps endpoint.
  ; Org 1 has two pops -- at least 1 record is exclusive to each pop (not
  ; the same pops).
  ; Org 2 has two pops, initially both visible and with full overlaps for
  ; org 1 initial call to overlaps endpoints returns all overlaps, on both
  ; populations org1 stops sharing pop 1 with org 2 (not a default rule).
  ; Subsequent call to overlaps endpoint returns:
  ;  o this
  ;  o is
  ;  o a
  ;  o test
  (stuff and bother))

In any case, thank you very much for reporting the shortcomings in :minimal-smart-wrap. I really appreciate it. Please let me know if, once you get 1.2.9,it still doesn't do what you want.

kkinnear commented 4 months ago

I have released 1.2.9 just now, so you can try this out whenever you want.