Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved count support #147

Open
1 task done
mawkler opened this issue Aug 29, 2022 · 10 comments · May be fixed by #360
Open
1 task done

Improved count support #147

mawkler opened this issue Aug 29, 2022 · 10 comments · May be fixed by #360
Labels
enhancement New feature or request

Comments

@mawkler
Copy link

mawkler commented Aug 29, 2022

Checklist

  • Have you read through :h nvim-surround to see if there might be any relevant information there?

Is your feature request related to a problem? Please describe.

I think it would be really cool if I for instance could do something like 2siw* to make a word bold in markdown (i.e. convert word into **word**), or do the opposite: 2ds* to make text non-bold in markdown (i.e. convert **word** into word).

Describe the solution you'd like

Prepending a count (i.e. a number 1-9) before a surround command performs the surround that many times over the same text-object.

@mawkler mawkler added the enhancement New feature or request label Aug 29, 2022
@smjonas
Copy link
Contributor

smjonas commented Aug 29, 2022

I've had the same feature request here: #86

There might be some relevant info there :) Btw, I still think this feature is useful (and there's no workaround for your usecase, e.g. ds2* doesn't work).

@kylechui
Copy link
Owner

@smjonas It seems like this is slightly different; your feature request was about surrounding larger selections (e.g. two words at a time), whereas this seems to be about surrounding a single word twice. @melkster This sounds like a good idea; unfortunately at the moment I need to first get through the other updates (good query support) and some other issues, and then learn how counting works. Apologies in advance if this takes a while, as I'll have less time to work on this during the school year/internship application season.

@kylechui
Copy link
Owner

kylechui commented Mar 15, 2023

Hello! It's been quite a while (sorry), but I'm productively procrastinating on my schoolwork by working on this plugin 😄 Coming back to this issue, it seems that we kind of have two different ways to approach this problem: prefixing the operator or prefixing the surround, i.e. 2ysiw* vs. ysiw2*.

My current thoughts are that the former has no real disadvantages (and can probably be implemented by leveraging the built-in v:count), while the latter would require me to:

  • Parse numbers myself to see how many times to repeat a given action (seems relatively easy IMO)
  • Force a breaking change where numbers are no longer valid surround keys (a bigger deal)

@kylechui
Copy link
Owner

kylechui commented Aug 30, 2023

I just realized that there's already a bit of inconsistency with how things work for the yss special case. As of right now, 2yss) would surround two lines with parentheses, instead of surrounding the current line with two sets of parentheses. I'm not exactly sure how to reconcile these differences; if anybody has any ideas feel free to let me know!

Edit: The idea of parsing numbers after the motion is selected seems to make the most sense, e.g. 2yss3) would surround two lines with three sets of parentheses, but would be a breaking change and require me to parse the numbers, as mentioned before.

@kylechui
Copy link
Owner

Continuing the tradition of replying once a year (sorry!). It seems like I was mistaken before, and that prefixing the motion with a count already applies the count to the motion, i.e. 2ysaw) will surround two words with (...). Thus 2yss) really isn't a "special case", which makes me even less inclined to change the behavior now. The only real option seems to be something like ysiw10), but like I mentioned earlier, I'm not sure if I want to implement the parsing for that...

@kylechui
Copy link
Owner

kylechui commented Jun 7, 2024

I think I'll close this issue for now since implementing this seems to mandate some kind of breaking change, but if anybody has any new ideas that haven't already been posted in this thread, feel free to comment!

Tangentially related is that with the "sticky" option for move_cursor (soon-to-be-merged in #334), one can just dot-repeat the surround to get multiple.

@kylechui kylechui closed this as not planned Won't fix, can't repro, duplicate, stale Jun 7, 2024
@kylechui
Copy link
Owner

kylechui commented Nov 24, 2024

I haven't solved the issue from a design standpoint (i.e. how to actually get the inputs in), but another person asked about this recently so I'm just saving this implementation snippet here for posterity:

+-- Repeats a delimiter pair n times.
+---@param delimiters delimiter_pair The delimiters to be repeated.
+---@param n integer The number of times to repeat the delimiters.
+---@nodiscard
+M.repeat_delimiters = function(delimiters, n)
+    local acc = { { "" }, { "" } }
+    for _ = 1, n do
+        acc[1][#acc[1]] = acc[1][#acc[1]] .. delimiters[1][1]
+        vim.list_extend(acc[1], delimiters[1], 2)
+        acc[2][#acc[2]] = acc[2][#acc[2]] .. delimiters[2][1]
+        vim.list_extend(acc[2], delimiters[2], 2)
+    end
+    return acc
+end

I tested it out with passing in vim.v.count1, but still decided against actually using this because prefixing a surround with a count caused the count to be used both for the motion and the repeat count, e.g.

-- Before
hello world
-- After: 2ysiw)
((hello world))

As mentioned before, it's ambiguous if this "should" be ((hello)) world or (hello world). The correct behavior here is (hello world), and the only place left to put the repeat count is in the delimiter part, so maybe I'll just bite the bullet and implement the parsing 🤔 If people think it's worth the breaking change let me know!

@kylechui kylechui reopened this Nov 24, 2024
@kylechui
Copy link
Owner

kylechui commented Nov 24, 2024

I'm starting to get sold on the idea that ysiw2* on hello -> **hello** is a good idea (with ds2* to undo it); might try implementing it in a feature branch 🤔

@kylechui kylechui linked a pull request Nov 24, 2024 that will close this issue
@mawkler
Copy link
Author

mawkler commented Nov 26, 2024

@kylechui

As mentioned before, it's ambiguous if this "should" be ((hello)) world or (hello world). The correct behavior here is (hello world)

I personally disagree. To me as a user it makes most sense if 2ysiw) results in ((hello)), since the count is closest to the ys. If the user wants (hello world) they should do ys2iw).

Moreover, ysiw2) introduces a new ambiguity if the user wants to surround something with a number like 2hello2, or if they have created their custom surround that's mapped to a number. Just as an arbitrary example they might want ysiw2 to surround the text with a level 2 heading (subsection{hello}) in LaTeX.

prefixing a surround with a count caused the count to be used both for the motion and the repeat count

I do however understand if you decide to go with ysiw2) from an implementation perspective if it's impossible to implement the former.

@kylechui
Copy link
Owner

Thanks for weighing in! I think the prefix count and middle count get multiplied to form the motion, e.g. 2d3w == d6w == 6dw. I actually tried implementing 2ysiw), however the motion always defaulted to selecting 2iw. I agree that it makes more sense for the prefix count to apply to the number of surrounds, rather than the size of the motion.

As for the suffix count, e.g. ysiw2)---you are right that it is incompatible with number surrounds, and I was considering making a breaking change for this. Actually, either way this will be a breaking change because we have to choose which set of semantics is right:

  • No number surrounds (breaking!), yss2b surrounds 1 line with 2 sets of parentheses (if I can figure this out), 2yssb surrounds 2 lines with 1 set of parentheses
  • Keep number surrounds, 2yssb surrounds 1 line with 2 sets of parentheses (breaking!)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants