GithubHelp home page GithubHelp logo

Comments (9)

AndrewRadev avatar AndrewRadev commented on June 18, 2024 1

There already is a config option that does that:

switch.vim/doc/switch.txt

Lines 813 to 819 in c534f11

*g:switch_find_smallest_match*
>
let g:switch_find_smallest_match = 0
<
This variable controls whether the plugin will attempt to find the smallest
match for the area under the cursor. If it's set to 0, all the different
matches will simply be attempted in the order they're defined.

You can try it out, my personal thinking is it would end up causing weird issues, but it was added by request, and I haven't heard about problems, so who knows :)

from switch.vim.

AndrewRadev avatar AndrewRadev commented on June 18, 2024 1

This can't work, because both a variable starting with const and a variable not starting with const match \([A-Za-z][A-Za-z0-9_:<>]*\). If you'd like to make these two work together, you need to add a "not starting with const" clause:

au FileType cpp let g:switch_custom_definitions = [
        \   switch#Words(['public', 'private']),
        \   switch#Words(['first', 'second']),
        \ {
          \  'const \([A-Za-z][A-Za-z0-9_:<>]*\)&': '\1',
          \  '\%(const \)\@!\([A-Za-z][A-Za-z0-9_:<>]*\)' : 'const \1&'
        \ }
      \ ] + g:switch_custom_definitions " this has the other switches that I want to be lower precedence

I've got an explanation for a similar case in the documentation:

switch.vim/doc/switch.txt

Lines 256 to 271 in d9a8cf6

Another interesting example is the following definition:
>
autocmd FileType php let b:switch_custom_definitions =
\ [
\ {
\ '<?php echo \(.\{-}\) ?>': '<?php \1 ?>',
\ '<?php \%(echo\)\@!\(.\{-}\) ?>': '<?php echo \1 ?>',
\ }
\ ]
<
In this case, when in the "php" filetype, the plugin will attempt to remove
the "echo" in "<?php echo 'something' ?>" or vice-versa. However, the second
pattern wouldn't work properly if it didn't contain "\%(echo\)\@!". This
pattern asserts that, in this place of the text, there is no "echo".
Otherwise, the second pattern would match as well. Using the |\@!| pattern in
strategic places is important in many cases.

from switch.vim.

unphased avatar unphased commented on June 18, 2024 1

That would definitely appear to work for me, thank you for the details! Gosh if only all software maintainers would approach things like you do... programming would be a much more pleasurable trade.

The switch#NormalizedCaseWords(['yes', 'no']), that I have put into my g:switch_custom_definitions has been working fine for now.

What I was originally looking for was essentially something I can inject into a specific spot in my ordered list in g:switch_custom_definitions. But what you've provided is superior to that because now I have the tools to programmatically take g:switch_builtins and turn it from a dict and splice it as a list into my definition at the location I need, and should I find a desire to further breakdown or adjust their priority order I could customize it straightforwardly as you described.

I guess I should not set g:switch_no_builtins as the environment is shared by vim buffers (that is my understanding of the g: VimL variable scoping), until when I inject the builtin definitions into my ordered list for all filetypes. Very useful, you have indeed thought of everything for the config.

Thanks for the assistance :)

from switch.vim.

unphased avatar unphased commented on June 18, 2024

I tested reversing the order in the list and unfortunately it still grabbed the shorter inner match. I was hoping that it might just take the first match in the list and run with it, which would allow for superior control.

from switch.vim.

unphased avatar unphased commented on June 18, 2024

Some quick hunting in code reveals switch#match#IsBetter that indicates to me that it's doing the exact thing that's getting in my way, maybe we can just add a config option to make it dumber and just scan the matches in order of declaration and short circuit?

from switch.vim.

unphased avatar unphased commented on June 18, 2024

That's spectacular, and I'll report back in particular if it results in other problems.

from switch.vim.

unphased avatar unphased commented on June 18, 2024

I was able to get my desired behavior working with the following config:

au FileType cpp let g:switch_custom_definitions = [ 
        \   switch#Words(['public', 'private']),
        \   switch#Words(['first', 'second']),
        \ {
          \  'const \([A-Za-z][A-Za-z0-9_:<>]*\)&': '\1'
        \ },
        \ {
          \  '\([A-Za-z][A-Za-z0-9_:<>]*\)' : 'const \1&'
        \ }
      \ ] + g:switch_custom_definitions " this has the other switches that I want to be lower precedence

let g:switch_find_smallest_match = 0

However when I set them inside as a pair, like this:

        \ {
          \  'const \([A-Za-z][A-Za-z0-9_:<>]*\)&': '\1',        
          \  '\([A-Za-z][A-Za-z0-9_:<>]*\)' : 'const \1&'
        \ },

it does not work properly, it will just keep matching the second one so instead of toggling the const-refness of a type it will just continually add const to the front and & to the end. I did also try reversing the order of these but that didn't work.

Could you help me figure out why it behaves that way? I also noticed that even without overriding g:switch_find_smallest_match this same behavior happens. Indeed without overriding g:switch_find_smallest_match, separating it out into two entries does not work either, because of course it will always choose the smallest match.

So now I wonder if there is a different mechanism i would need to use to get this working in any capacity without overriding g:switch_find_smallest_match.

from switch.vim.

unphased avatar unphased commented on June 18, 2024

Thank you!

One last question: Given the above revelations I can carefully order my switches in terms of priority, which is working well. However, all custom definitions seem to take priority over builtin ones, so now I'm struggling with how to convince it to prioritize the builtin true/false switch over my const ref one in cpp files. I would have ran into this even earlier since I also use the camelCase/PascalCase/snake_case/CAPS_CASE/kebab-case switcher, despite it's questionable utility, luckily those regexes do not trigger on single words like true and false, and it has been an eye opening example of what's possible with this plugin.

What do you think? How could we adjust the priority of built in ones to custom ones? Maybe I just add the true/false as another switch#Words entry in the custom list? I don't see any drawbacks with that yet.

from switch.vim.

AndrewRadev avatar AndrewRadev commented on June 18, 2024

If you've already put in the work to order things by priority, you could skip the built-in list altogether and try to pick only the parts that interest you. All the definitions are located in a big dictionary:

let g:switch_builtins =
\ {
\ 'ampersands': ['&&', '||'],
\ 'capital_true_false': {
\ '\C\<True\>': 'False',
\ '\C\<False\>': 'True',
\ },
\ 'true_false': {
\ '\C\<true\>': 'false',
\ '\C\<false\>': 'true',
\ },
\ 'ruby_hash_style': {
\ ':\(\k\+\)\s*=>\s*': '\1: ',
\ '\<\(\k\+\): ': ':\1 => ',
\ },
\ 'ruby_oneline_hash': {
\ '\v\{(\s*:(\k|["''])+\s*\=\>\s*[^,]+\s*,?)*}': {
\ ':\(\%\(\k\|["'']\)\+\)\s*=>': '\1:',
\ },
\ '\v\{(\s*(\k|["''])+:\s*[^,]+,?)*\s*}': {
\ '\(\%\(\k\|["'']\)\+\):': ':\1 =>',
\ },
\ },
\ 'ruby_lambda': {
\ 'lambda\s*{\s*|\([^|]\+\)|': '->(\1) {',
\ '->\s*(\([^)]\+\))\s*{': 'lambda { |\1|',
\ 'lambda\s*{': '-> {',
\ '->\s*{': 'lambda {'
\ },
\ 'ruby_if_clause': {
\ 'if true or (\(.*\))': 'if false and (\1)',
\ 'if false and (\(.*\))': 'if \1',
\ 'if \%(true\|false\)\@!\(.*\)': 'if true or (\1)',
\ },
\ 'ruby_string': {
\ '"\(\k\+\%([?!]\)\=\)"': '''\1''',
\ '''\(\k\+\%([?!]\)\=\)''': ':\1',
\ ':\(\k\+\%([?!]\)\=\)\@>\%(\s*=>\)\@!': '"\1"\2',
\ },
\ 'ruby_short_blocks': {
\ '\(\k\+\)(&:\(\k\+[!?]\=\))': '\1 { |x| x\.\2 }',
\ '\(\k\+\)\s\={\s*|\(\k\+\)|\s*\2.\(\S\+\)\s*}': '\1(&:\3)',
\ },
\ 'ruby_array_shorthand': {
\ '\v\[\s*%((["''])%([^"'']\s@!)+\1,?\s*)*]': {
\ '\[': '%w(',
\ '\v\s*(["''])(%([^"'']\s@!)+)\1,?(\s)*': '\2\3',
\ '\s*]': ')',
\ },
\ '\v\%w\(\s*%([^"'',]\s*)+\)': {
\ '%w(\s*': '[''',
\ '\v(\s+)@>\)@!': ''', ''',
\ '\s*)': ''']',
\ },
\ '\v\[\s*%(:\@{0,2}\k+,?\s*)+\]': {
\ '\[': '%i(',
\ '\v\s*:(\@{0,2}\k+),?(\s)*': '\1\2',
\ '\s*]': ')',
\ },
\ '\v\%i\(\s*%(\@{0,2}\k+\s*)+\)': {
\ '\v\%i\((\s*)@>': '[:',
\ '\v(\s+)@>\)@!': ', :',
\ '\s*)': ']',
\ },
\ },
\ 'ruby_fetch': {
\ '\v(%(\%@<!\k)+)\[(.{-})\]': '\1.fetch(\2)',
\ '\v(\k+)\.fetch\((.{-})\)': '\1[\2]',
\ },
\ 'ruby_assert_nil': {
\ 'assert_equal nil,': 'assert_nil',
\ 'assert_nil': 'assert_equal nil,',
\ },
\ 'rspec_should': ['should ', 'should_not '],
\ 'rspec_expect': {
\ '\(expect(.*)\)\.to ': '\1.not_to ',
\ '\(expect(.*)\)\.to_not ': '\1.to ',
\ '\(expect(.*)\)\.not_to ': '\1.to ',
\ },
\ 'rspec_to': {
\ '\.to ': '.not_to ',
\ '\.not_to ': '.to ',
\ '\.to_not ': '.to ',
\ },
\ 'rspec_be_truthy_falsey': ['be_truthy', 'be_falsey'],
\ 'eruby_if_clause': {
\ '<% if true or (\(.*\)) %>': '<% if false and (\1) %>',
\ '<% if false and (\(.*\)) %>': '<% if \1 %>',
\ '<% if \%(true\|false\)\@!\(.*\) %>': '<% if true or (\1) %>',
\ },
\ 'eruby_tag_type': {
\ '<%= \(.*\) %>': '<% \1 %>',
\ '<% \(.*\) -\?%>': '<%# \1 %>',
\ '<%# \(.*\) %>': '<%= \1 %>',
\ },
\ 'php_echo': {
\ '<?php echo \(.\{-}\) ?>': '<?php \1 ?>',
\ '<?php \%(echo\)\@!\(.\{-}\) ?>': '<?php echo \1 ?>',
\ },
\ 'cpp_pointer': {
\ '\(\k\+\)\.': '\1->',
\ '\(\k\+\)->': '\1.',
\ },
\ 'javascript_function': {
\ '\(async \)\?function\s*\(\k\+\)\s*()\s*{': 'const \2 = \1() => {',
\ '\(async \)\?function\s*\(\k\+\)\s*(\([^()]\{-},[^()]\{-}\))\s*{': 'const \2 = \1(\3) => {',
\ '\(async \)\?function\s*\(\k\+\)\s*(\(\k\+\))\s*{': 'const \2 = \1\3 => {',
\ '\%(var \|let \|const \)\?\(\k\+\)\s*=\s*\(async \)\?function\s*(': '\2function \1(',
\ '\%(var \|let \|const \)\?\(\k\+\)\s*=\s*\(async \)\?(\([^()]\{-}\))\s*=>\s*{': '\2function \1(\3) {',
\ '\%(var \|let \|const \)\?\(\k\+\)\s*=\s*\(async \)\?\(\k\+\)\s*=>\s*{': '\2function \1(\3) {',
\ },
\ 'javascript_arrow_function': {
\ 'function\s*()\s*{': '() => {',
\ 'function\s*(\([^()]\{-},[^()]\{-}\))\s*{': '(\1) => {',
\ 'function\s*(\(\k\+\))\s*{': '\1 => {',
\ '(\([^()]\{-}\))\s*=>\s*{': 'function(\1) {',
\ '\(\k\+\)\s*=>\s*{': 'function(\1) {',
\ },
\ 'javascript_es6_declarations': {
\ '\<var\s\+': 'let ',
\ '\<let\s\+': 'const ',
\ '\<const\s\+': 'let ',
\ },
\ 'coffee_arrow': {
\ '^\(.*\)->': '\1=>',
\ '^\(.*\)=>': '\1->',
\ },
\ 'coffee_dictionary_shorthand': {
\ '\([{,]\_s*\)\@<=\(\k\+\)\(\s*[},]\)': '\2: \2\3',
\ '\([{,]\_s*\)\@<=\(\k\+\): \?\2\(\s*[},]\)': '\2\3',
\ },
\ 'clojure_string': {
\ '"\(\k\+\)"': '''\1',
\ '''\(\k\+\)': ':\1',
\ ':\(\k\+\)': '"\1"\2',
\ },
\ 'clojure_if_clause': {
\ '(\(if\|if-not\|when\|when-not\) (or true \(.*\))': '(\1 (and false \2)',
\ '(\(if\|if-not\|when\|when-not\) (and false \(.*\))': '(\1 \2',
\ '(\(if\|if-not\|when\|when-not\) (\@!\(.*\)': '(\1 (or true \2)',
\ },
\ 'scala_string': {
\ '[sf"]\@<!"\(\%(\\.\|.\)\{-}\)""\@!': 's"\1"',
\ 's"\(\%(\\.\|.\)\{-}\)"': 'f"\1"',
\ 'f"\(\%(\\.\|.\)\{-}\)"': '"""\1"""',
\ '[sf"]\@<!"""\(.\{-}\)"""': 's"""\1"""',
\ 's"""\(.\{-}\)"""': 'f"""\1"""',
\ 'f"""\(.\{-}\)"""': '"\1"',
\ },
\ 'elixir_list_shorthand': {
\ '\[\%(\k\|[''", ]\)\+\]': {
\ '\[': '\~w(',
\ '[''"]\(\k\+\)[''"],\=': '\1',
\ ']': ')',
\ },
\ '\~w(\%(\k\|\s\)\+)a': {
\ '\~w(': '[',
\ '\(\k\+\) ': ':\1, ',
\ '\(\k\+\))a': ':\1]',
\ },
\ '\~w(\%(\k\|\s\)\+)a\@!': {
\ '\~w(': '[',
\ '\(\k\+\) ': '"\1", ',
\ '\(\k\+\))': '"\1"]',
\ },
\ '\[\%(\k\|[:, ]\)\+\]': {
\ '\[': '\~w(',
\ ':\(\k\+\),\=': '\1',
\ ']': ')a',
\ },
\ },
\ 'rust_void_typecheck': {
\ '\(let\s*\%(mut\s*\)\=\k\+\) = ': '\1: () = ',
\ '\(let\s*\%(mut\s*\)\=\k\+\): () = ': '\1 = ',
\ },
\ 'rust_turbofish': {
\ '\(\k\+\)(': '\1::<Todo>(',
\ '\(\k\+\)::<\%(\k\|\s\|[<>,]\)\+>(': '\1(',
\ },
\ 'rust_string': {
\ '"\([^"]*\)"': 'r"\1"',
\ 'r"\([^"]*\)"': 'r#"\1"#',
\ 'r#"\([^"]*\)"#': '"\1"',
\ },
\ 'rust_is_some': {
\ '\<is_some\>': 'is_none',
\ '\<is_none\>': 'is_some',
\ },
\ 'rust_assert': {
\ '\<assert_eq!': 'assert_ne!',
\ '\<assert_ne!': 'assert_eq!',
\ },
\ 'cargo_dependency_version': {
\ '^\s*\([[:keyword:]-]\+\)\s*=\s*\(["''].\{-}["'']\)': '\1 = { version = \2 }',
\ '^\s*\([[:keyword:]-]\+\)\s*=\s*{\s*version\s*=\s*\(["''].\{-}["'']\)\s*}': '\1 = \2',
\ },
\ 'vim_script_local_function': {
\ '\<s:\(\h\w\+\)(': '<SID>\1(',
\ '<SID>\(\h\w\+\)(': 's:\1(',
\ }
\ }

So you could, for example, add g:switch_builtins.true_false to your list. But I guess you also want to stop the built-ins from being loaded, which you can achieve by setting g:switch_no_builtins to 1:

switch.vim/doc/switch.txt

Lines 358 to 374 in d9a8cf6

If you want to only use some built-in definitions, you can set the
|g:switch_no_builtins| variable to 1 and then just use your
|g:switch_custom_definitions| and |b:switch_custom_definitions| variables to
re-use the built-in definitions. To make this easier, you can use the
patterns from the |g:switch_builtins| list:
>
autocmd FileType ruby let b:switch_definitions =
\ [
\ g:switch_builtins.ruby_hash_style,
\
\ { 'my_own_pattern': 'my_own_replacement' },
\
\ g:switch_builtins.rspec_should,
\ ]
<
See the section below, |switch-builtins| for information on the built-in
patterns, including their names in the |g:switch_builtins| dictionary.

Would that work for your use cases?

from switch.vim.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.