GithubHelp home page GithubHelp logo

andrewradev / switch.vim Goto Github PK

View Code? Open in Web Editor NEW
641.0 12.0 32.0 266 KB

A simple Vim plugin to switch segments of text with predefined replacements

Home Page: http://www.vim.org/scripts/script.php?script_id=4172

License: MIT License

Ruby 57.01% Vim Script 42.99%
cursor substitutions vim-plugin text-manipulation

switch.vim's Introduction

GitHub version Build Status

Screencast!

This plugin is easier to demonstrate than explain. You can find a screencast here.

Usage

The main entry point of the plugin is a single command, :Switch. When the command is executed, the plugin looks for one of a few specific patterns under the cursor and performs a substitution depending on the pattern. For example, if the cursor is on the "true" in the following code:

flag = true

Then, upon executing :Switch, the "true" will turn into "false".

There's a default mapping to trigger the command, gs. Note that this is already a Vim built-in, but it doesn't seem particularly useful.

If you'd like to change the mapping, change the value of g:switch_mapping. For example, to map it to "-", place the following in your .vimrc:

let g:switch_mapping = "-"

To avoid the default mapping completely, set the variable to an empty string:

let g:switch_mapping = ""

See the "customization" section below for information on how to create several mappings with different definitions.

There are three main principles that the substitution follows:

  1. The cursor needs to be on the match. Regardless of the pattern, the plugin only performs the substitution if the cursor is positioned in the matched text.

  2. When several patterns match, the shortest match is performed. For example, in ruby, the following switch is defined:

    { :foo => true }
    # switches into:
    { foo: true }

    This works if the cursor is positioned somewhere on the ":foo =>" part, but if it's on top of "true", the abovementioned true -> false substitution will be performed instead. If you want to perform a "larger" substitution instead, you could move your cursor away from the "smaller" match. In this case, move the cursor away from the "true" keyword.

  3. When several patterns with the same size match, the order of the definitions is respected. For instance, in eruby, the following code can be transformed:

    <% if foo? %>
    could switch into:
    <%# if foo? %>
    but instead, it would switch into:
    <% if true or (foo?) %>

    The second switch will be performed, simply because in the definition list, the pattern was placed at a higher spot. In this case, this seems to make sense to prioritize one over the other. If it's needed to prioritize in a different way, the definition list should be redefined by the user.

Advanced usage

Instead of using the :Switch and :SwitchReverse commands, you can use the autoloaded function switch#Switch. Calling it without any arguments is the same as calling the :Switch command:

:call switch#Switch()
" equivalent to:
:Switch

However, you can also call the function with a dict of options. Instead of :SwitchReverse, you can invoke it with the reverse option:

:call switch#Switch({'reverse': 1})
" or,
:call switch#Switch({'reverse': v:true})
" equivalent to:
:SwitchReverse

The other option you can provide is definitions to set an explicit list of definitions that are different from the built-ins.

:call switch#Switch({'definitions': list_of_definitions})

The switch#Switch() function returns 1 if it succeeded, and 0 if it failed. You can use the return value to decide if you'd like to apply some other mapping.

See below in "Customization" for more details and examples on how to write use this function.

Customization

Note: for more switches by the community, take a look at the wiki

There are two variables that hold the global definition list and the buffer-local definition list -- g:switch_definitions and b:switch_definitions, respectively. These contain the definitions for the built-ins provided by the plugin. In order to add the switches you want, you should override g:switch_custom_definitions and b:switch_custom_definitions instead.

The format of the variables is a simple List of items. Each item can be either a List or a Dict.

List definitions

let g:switch_custom_definitions =
    \ [
    \   ['foo', 'bar', 'baz']
    \ ]

With this definition list, if the plugin encounters "foo" under the cursor, it will be changed to "bar". If it sees "bar", it will change it to "baz", and "baz" would be turned into "foo". This is the simple case of a definition that is implemented (in a slightly different way) by the "toggle.vim" plugin.

You might want this to work for different capitalizations, like with true and True and TRUE. You might also want to also affect only word boundaries. While you could use the more complicated dict definition, a simple way to tackle these scenarios is with modifier functions:

  • switch#NormalizedCase
  • switch#Words
  • switch#NormalizedCaseWords

Here's how you might use these:

let g:switch_custom_definitions =
    \ [
    \   switch#NormalizedCase(['one', 'two']),
    \   switch#Words(['three', 'four']),
    \   switch#NormalizedCaseWords(['five', 'six']),
    \ ]

The result of this is that:

  • The first definition would switch between "one" and "two", between "One" and "Two", and between "ONE" and "TWO".
  • The second definition would switch between "three" and "four" only at word boundaries, as if the patterns have \< and \> modifiers added to them.
  • The third would switch between "five"/"six", "Five"/"Six", "FIVE"/"SIX" only at word boundaries with a combination of the above.

See :help switch-internals for some information on the underlying data format if you'd like to use a different method to generate definitions (like, say, loading JSON).

Leaving lists aside, the more complicated (and more powerful) way to define a switch pattern is by using a Dict. In fact, a list definition is processed into three dict definitions, one for each pair of switches.

Dict definitions

autocmd FileType eruby let b:switch_custom_definitions =
    \ [
    \   {
    \     ':\(\k\+\)\s\+=>': '\1:',
    \     '\<\(\k\+\):':     ':\1 =>',
    \   },
    \ ]

When in the eruby filetype, the hash will take effect. The plugin will look for something that looks like :foo => and replace it with foo: , or the reverse -- foo: , so it could turn it into :foo =>. The search string is fed to the search() function, so all special patterns like \%l have effect in it. And the replacement string is used in the :substitute command, so all of its replacement patterns work as well.

Notice the use of autocmd FileType eruby to set the buffer-local variable whenever an eruby file is loaded. The same effect could be achieved by placing this definition in ftplugin/eruby.vim.

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 "" 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.

For even more complicated substitutions, you can use the nested form.

Nested dict definitions

The following expression replaces underscored identifier names with their camelcased versions.

let b:switch_custom_definitions = [
      \   {
      \     '\<[a-z0-9]\+_\k\+\>': {
      \       '_\(.\)': '\U\1'
      \     },
      \     '\<[a-z0-9]\+[A-Z]\k\+\>': {
      \       '\([A-Z]\)': '_\l\1'
      \     },
      \   }
      \ ]

If the cursor is on "foo_bar_baz", then switching would produce "fooBarBaz" and vice-versa. The logic is as follows:

  • The keys of the dict are patterns, just like the "normal" dict version.
  • The values of the dict are dicts with patterns for keys and replacements for values.

The goal of this form is to enable substituting several different kinds of patterns within the limits of another one. In this example, there's no way to define this switch using the simpler form, since there's an unknown number of underscores in the variable name and all of them need to be replaced in order to make the switch complete.

The nested patterns differ from the simple one in that each one of them is replaced globally, only within the limits of the "parent" pattern.

Note that this particular example is NOT included as a built-in, since it may overshadow other ones and is probably not that useful, either (it's rare that a language would require changing between the two forms). An example usage may be within javascript, if your server-side variables are underscored and the client-side ones need to be camelcased. For something more complete, you can take a look at this gist.

You could also use a separate mapping for that.

Separate mappings

While there's a default mapping for :Switch, you could actually define several mappings with your own custom definitions:

let g:variable_style_switch_definitions = [
      \   {
      \     '\<[a-z0-9]\+_\k\+\>': {
      \       '_\(.\)': '\U\1'
      \     },
      \     '\<[a-z0-9]\+[A-Z]\k\+\>': {
      \       '\([A-Z]\)': '_\l\1'
      \     },
      \   }
      \ ]
nnoremap + :call switch#Switch({'definitions': g:variable_style_switch_definitions})<cr>
nnoremap - :Switch<cr>

With this, typing - would invoke the built-in switch definitions, while typing + would switch between camelcase and underscored variable styles. This may be particularly useful if you have several clashing switches on patterns that match similar things.

More complicated mappings

By using the switch#Switch() function, you can also write more complicated mappings that check if a switch succeeded, and apply some fallback if it didn't. The function returns 1 for success and 0 for failure.

For example, if you want to switch, or fall back to activating the speeddating plugin, you could map <c-a> and <c-x> like so:

" Don't use default mappings
let g:speeddating_no_mappings = 1

" Avoid issues because of us remapping <c-a> and <c-x> below
nnoremap <Plug>SpeedDatingFallbackUp <c-a>
nnoremap <Plug>SpeedDatingFallbackDown <c-x>

" Manually invoke speeddating in case switch didn't work
nnoremap <c-a> :if !switch#Switch() <bar>
      \ call speeddating#increment(v:count1) <bar> endif<cr>
nnoremap <c-x> :if !switch#Switch({'reverse': 1}) <bar>
      \ call speeddating#increment(-v:count1) <bar> endif<cr>

Builtins

Here's a list of all the built-in switch definitions. To see the actual definitions with their patterns and replacements, look at the file plugin/switch.vim.

Global

  • Boolean conditions:

    foo && bar
    foo || bar
    
  • Boolean constants:

    flag = true
    flag = false
    
    flag = True
    flag = False
    

Ruby

  • Hash style:

    foo = { :one => 'two' }
    foo = { one: 'two' }
  • If-clauses:

    if predicate?
      puts 'Hello, World!'
    end
    
    if true or (predicate?)
      puts 'Hello, World!'
    end
    
    if false and (predicate?)
      puts 'Hello, World!'
    end
  • Rspec should/should_not:

    1.should eq 1
    1.should_not eq 1
  • Tap:

    foo = user.comments.map(&:author).first
    foo = user.comments.tap { |o| puts o.inspect }.map(&:author).first
  • String style:

    foo = 'bar'
    foo = "baz"
    foo = :baz

    (Note that it only works for single-word strings.)

  • Ruby block shorthands:

    do_something { |x| x.some_work! }
    do_something(&:some_work!)
  • Array shorthands:

    ['one', 'two', 'three']
    %w(one two three)
    [:one, :two, :three]
    %i(one two three)

    (In this case, be careful to not have the cursor on one of the strings/symbols, or you'll trigger the string switch as seen above.)

PHP "echo" in tags:

<?php "Text" ?>
<?php echo "Text" ?>

Eruby

  • If-clauses:

    <% if predicate? %>
      <%= 'Hello, World!' %>
    <% end %>
    
    <% if true or (predicate?) %>
      <%= 'Hello, World!' %>
    <% end %>
    
    <% if false and (predicate?) %>
      <%= 'Hello, World!' %>
    <% end %>
  • Tag type:

    <% something %>
    <%# something %>
    <%= something %>
  • Hash style:

    <% foo = { :one => 'two' } %>
    <% foo = { one: 'two' } %>

Haml

  • If-clauses:

    - if predicate?
      Hello, World!
    
    - if true or (predicate?)
      Hello, World!
    
    - if false and (predicate?)
      Hello, World!
  • Tag type:

    - something
    -# something
    = something
  • Hash style:

    %a{:href => '/example'}
    %a{href: '/example'}

C++ pointer dots/arrows:

Object* foo = bar.baz;
Object* foo = bar->baz;

JavaScript

  • Function definitions:

    function example(one, two) { }
    var example = function(one, two) { }
  • ES6-style arrow functions:

    var example = function(one, two) { }
    var example = (one, two) => { }
  • ES6-style variable declarations:

    var example
    let example
    const example
    // var -> let
    // let -> const
    // const -> let

    Switching to var from const or let is unsupported, since it's assumed to be an unlikely case.

CoffeeScript arrows

functionCall (foo) ->
functionCall (foo) =>

CoffeeScript dictionary shorthands

foo = {one, two}
foo = {one: one, two}

Clojure

  • String style:

    "baz"
    'bar
    :baz

    (Note that it only works for single-word strings, such as baz, b-a-z, or **.)

  • If-clauses:

    (if predicate?
      (prn "Hello, world!")
      (prn "oh..."))
    
    (if (or true predicate?)
      (prn "Hello, world!")
      (prn "oh..."))
    
    (if (and false predicate?)
      (prn "Hello, world!")
      (prn "oh..."))

    (Note that it also works for if-not, when, and when-not.)

Scala

  • String style:
    "foo bar"
    s"foo bar"
    f"foo bar"
    """foo bar"""
    s"""foo bar"""
    f"""foo bar"""

Git Rebase

  • Git Rebase Commands
      pick -> fixup -> reword -> edit -> squash -> exec -> break -> drop -> label -> reset -> merge -> (loops back to pick)
    
      p -> fixup
      f -> reword
      r -> edit
      e -> squash
      s -> exec
      x -> break
      b -> drop
      d -> label
      l -> reset
      t -> merge
      m -> pick
    

Elixir

Charlist -> Binary -> Atom

foo = 'bar'
foo = "bar"
foo = :bar

Elixir list shorthands

["one", "two", "three"]
~w(one two three)

[:one, :two, :three]
~w(one two three)a

Capitalized boolean constants :

flag = True
flag = False

Rust

Void typecheck

let value = complicated_expression();
let value: () = complicated_expression();

TOML

Particularly for files named Cargo.toml with the toml filetype (not built-in, but there are plugins for it):

structopt = "0.3.5"
structopt = { version = "0.3.5" }

Markdown

Task items

- [ ] Task 1
- [x] Task 1

Similar work

This plugin is very similar to two other ones:

Both of these work on replacing a specific word under the cursor with a different one. The benefit of switch.vim is that it works for much more complicated patterns. The drawback is that this makes extending it more involved. I encourage anyone that doesn't need the additional power in switch.vim to take a look at one of these two.

Contributing

If you'd like to hack on the plugin, please see CONTRIBUTING.md first.

Issues

Any issues and suggestions are very welcome on the github bugtracker.

switch.vim's People

Contributors

aileot avatar akarzim avatar alxgnon avatar andrewradev avatar benknoble avatar chocolateboy avatar dependabot[bot] avatar glittershark avatar jyrodgers avatar keithamus avatar mg979 avatar p0deje avatar rstankov avatar shanesmith avatar sherwinyu avatar syngan avatar ujihisa avatar y-kamiya avatar ytian81 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

switch.vim's Issues

be_falsey be_truthy in Ruby

Hi,

Since Rspec prefers be_falsey and be_truthy instead of be_false and be_true, current behaviour doesn't really work with specs. It converts be_falsey to be_truey.

Maybe it's time to add another matcher.

How do I perform nested switching

I wish to switch between 3 strings: '', ' Y' and '* N'

I tried the following settings:

let g:switch_find_smallest_match = 0
let g:switch_custom_definitions = [['* Y', '* N', '*']]

but this doesn't seem to work. What am I missing here?

Introduce a way to set priority/precedence?

If we have a situation in which two switch operations could happen based on where the cursor is, it is ambiguous which switch is performed. I'm currently using this magical gist https://gist.github.com/othree/5655583 and currently (as an example...) I want to introduce a switch that toggles between a type T and its const T& counterpart for C++ but what happens is that if my cursor is on top of the type name it will of course run the fancy change-variable-case-style switch. I'd like to make it so that the change-variable-case-style switch is the lowest priority, rather than as it is now where I would basically be experiencing more pressure to delete it as I begin to use switch more heavily.

Although it works just fine to move the cursor to a suitable place it picks up the other switch and does the right thing. But it's not exactly ideal.

What do you think? This should not introduce much of a performance hit.

Actually, I'm going to go and play around with reordering the g:switch_custom_definitions list order, it may be possible to control priority inherently by ordering the definition.

Request: .to and .not_to in Ruby

Hi,

When editing tests one quite often needs to flip between .to and .not_to (or .to_not) in RSpec tests (ft=ruby).

Also be_truthy and be_falsey similar to true and false.

Can this be added? Thanks.

Treat slim as ruby

Hi,

Could you please treat slim as ruby? I usually do set ft=ruby and then set ft=slim after changing things. Or maybe there is a setting for that?

Does not working eruby_tag_type in eruby filetype.

I want use Switch command at eruby tag. e.g. <%= 'Hello, World!' %>
But it is not working.
Looking at the result of b:switch_definitions, the result is the same as that of filetype ruby.
スクリーンショット 2020-01-08 1 17 38

Do you have any solutions?

nested patterns change all matches from cursor to EOF

Hi there, this occured to me when using the ruby_array_shorthand builtin:

['foo'] 
['bar']
['far']
something
['boo']

becomes

['foo'] 
%w(bar)
[far)
something
[boo)

when executing :Switch while the cursor is in column 1 of line 2.
Only the second and third rule are being applied everywhere, apparently.

Reverse switching

Is there a possibility to iterate the list in reverse so it could be mapped to a key?

Btw, thank you for the plugin and wiki, I will upload my latex configuration after some cleaning.

[wiki] Anyone know how to write a substitution for React props?

I mainly work with React. Lately, I find myself often needing to do this transform:

<Thing foo={data} />
<Thing foo={`${data}`} />

It's very tedious even with vim-surround, and it's an ideal use-case for this plugin, but the special meanings of the characters involved have given me a headache.

I've been slowly grinding my way up the Vim ladder since I started college in 2012. Plenty of times I've figured out how to do a regular expression that saved me hours upon hours of labor time over the course of the next months, and those are the times I'm really glad I'm obstinate enough to have stuck with it for this long, because it was a whim to begin with.

Sometimes, though, you've just gotta ask for help.

Can anyone write this transform? It might be a good one to add to the wiki.

Find match on cursor line

This is strictly speaking not an issue but just and idea. Currently the cursor needs to be on the word, but often times there is only one relevant word in a line that needs to be toggled, at least in my use cases. It would be nice if it worked like vim's <C-A> and <C-X> (add and subtract) feature and just find the first relevant match on the line and operates on that.

If I get time and there is general interest and no one wants to work on it, I will do it.

Undo moves the cursor to the beginning of the line

On this line:

expect(page).|not_to have_link 'Refund'

With the cursor at |, gs will toggle between not_to and to, as expected. If I subsequently undo, however, the cursor moves to the beginning of the line. Is it possible for the cursor to remain where it was before the undo?

Support for verymagic expressions

The pattern used in keys of dictionaries doesn't seem to support verymagic expressions.

I get the following error Pattern not found: \%>13c\v<MyRegexp>\%<41c

Help file first line format

Hey,

Please format the first line of the help file in doc/switch.txt like :help write-local-help says. This way it shows up properly on :help-s listing.

Preserve casing

Hey,

I've got quite a list of antonyms set up. Occasionally, those words occur in camel case inside other words. E.g. findFirst <=> findLast with first and last being set up as Switch.vim definitions. It'd be great if the casing be preserved when switching. Same when switch constants: FIRST and LAST.

Thanks!

Switch.vim pollutes search history

When toggling true to false in C++, I get

\%>33c\Ctrue\m\%<39c

in my search history, while . to -> results in

\%>4c\(\k\+\)->\m\%<17c

I think the solution is to use call search("pattern"), instead of using / but I couldn't find the slash in the source to change, so this is probably something different

g:switch_find_largest_match

In short I propose to add a possibility to choose the longest match.

I have some common definitions for switching yes<->no.
For the latex there is a series of font size commands, which also include \normalsize. The latex configuration is added to the buffer configuration.

The problem is that when font size is switched to \normalsize, then the line is matched by no which is transformed to yes.

I would actually expect matching algorithm to choose the largest matching string for substitution. In this case it's guaranteed that the short match is not a substring of some longer match. Therefore I propose to add an option to check for the largest match. It may be also a string option, allowing to choose between several options: longest, shortest, sequential (or something like this).

Switching between unicode characters doesn't seem to be working:

I have the following in ftplugin/notes.vim:
let g:switch_custom_definitions = ['•', '✔', '✗']

but when my cursor is on and I try to execute :Switch I get the following error:

Error detected while processing function <SNR>60_Switch..switch#Switch:
line    8:
E706: Variable type mismatch for: mapping
Press ENTER or type command to continue

true / false switches to Capitals by default

i've just installed your plugin (master branch) and tried with my php file.
after :Switch true becomes False and then every time in capitals. I think it should not behave like this.

Unite with vim-speeddating

Any way to combine with tpope/vim-speeddating to reuse <C-a>/<C-x> ?
Likewise to execute original mapping if no definition match current word ?

Varying case lists

I've tried to implement LaTeX font size commands switching which contains \large, \Large, \LARGE sequence. It seems that switch.vim can not correctly handle them.

Here is MWE:

        let g:switch_custom_definitions =
            \ [
            \   [ 'test', 'Test', 'TEST' ],
            \ ]

Not depending on the initial word, it switches to Test and stops there.

Failure when string to replace is followed by an EOL

I am programming in Python, and I am trying to use switch on a line with a boolean flag on it.

Nothing happens if I try switch on this line:

train_layers_1to3 = True

It will works fine on these:

train_layers_1to3 = (True) -> train_layers_1to3 = (False), or
train_layers_1to3 = True -> train_layers_1to3 = False

Is this a bug, or is it just me?

Switch {} and do end in ruby files

Hi,
Is it possible to add switch between {} and do end in ruby files? I am actively refactoring code all the time and cleaning up using rubocop advise. Changing block syntax is not very fun.

Thanks.

Add ability to use global flag in switch mappings

In python I've found that sometimes I need to change dictionary to a list of key, value pairs. So from that

{'key1: 'value1', 'key2': 'value2'}

(('key1', 'value1), ('key2', 'value2'))

I don't think it's possible with current implementation because of lack of ability to use g modifier.

plugin works if opening a file from command line, doesn't work if opening a file from vim

Hi Andrew,

First of all, many thanks for your effort building and maintaining this project.

I've played a bit a few months ago and just came back to it and realized that is not working if I open a file from vim.

  1. I start vim in my terminal and open a file from vim using :e /path/to/file
  • this case Switch plugin won't work - eg. not changing 'foo' to 'bar', seemingly has no effect at all
  1. I start vim in my terminal passing /path/to/file as an argument vim /path/to/file
  • Switch plugin works as intended

I tried with this minimal 4 lines .vimrc

     call plug#begin('~/.vim/plugged')
        Plug 'AndrewRadev/switch.vim'
     call plug#end()
       let b:switch_custom_definitions = [ ['foo', 'bar', 'baz'] ]

Thanks,
Szilveszter

vim: 8.0.494 compiled from source using ./configure --enable-python3interp=dynamic --enable-cscope --enable-rubyinterp --without-x --disable-gui && make && sudo make install
Switch: latest version ddc0697

"." repeats always forward, even if the last used command was "SwitchReverse"

Hello,

I'd like to suggest the following change:

function! s:SwitchReverse()
  silent call switch#Switch({'reverse': 1})
  silent! call repeat#set(":Switch\<cr>")
endfunction

to

function! s:SwitchReverse()
  silent call switch#Switch({'reverse': 1})
  silent! call repeat#set(":SwitchReverse\<cr>") " <- Change here
endfunction

I can create a pull request if favored.

Reverse ability stopped working

Reverse ability stopped working after #bb71ada.
Did I miss something since last update? 😕

Example

let g:switchQuotes = [
  \ {
  \  '''\(.\{-}\)''': '"\1"',
  \  '"\(.\{-}\)"':   '''\1''',
  \  '`\(.\{-}\)`':   '''\1'''
  \ }
  \]

" old
nnoremap <silent> ! :<C-u>silent! call switch#Switch(g:switchQuotes, {'reverse': 1})<CR>
" new (?)
nnoremap <silent> ! :<C-u>silent! call switch#Switch({'definitions': g:switchQuotes}, {'reverse': 1})<CR>

Result

Quotes are changed once and the pattern/mapping completely stops working.

PS. Please, add silent to switch#Switch by default. Thank you for such a useful plugin!

More built-ins - or a wiki?

Every once in a while I add a few custom switches for this myself. I am guessing that some of them are re-inventing the wheel, others might be useful to other people.

Adding to the built-ins is probably problematic, I am not sure - people might have very specific ideas on how to do switches themselves.

But what would be nice is to have something like a collaborative wiki, where everyone can share their custom switches. People could copy/paste them then - or take them as inspiration.

What do you think?

Enable switching booleans anywhere on the line and returning to original cursor position

Great plugin! 👍

It would be awesome to be able to switch (bools) anywhere on the line and then have the cursor return to the original position. Possibly related to #49 and #14.

I implemented a function to do this for Python. I dunno if it can be used to upgrade the plugin, but it could be useful for someone else, so maybe include it as an example in the documentation?

function! MySwitch()                                                            
    let save_pos = getpos(".")                                                   
    call search('true\|false', '', line('.'))                                           
    execute 'Switch'                                                             
    call setpos(".", save_pos)                                                   
endfunction                                                                     
nmap <Leader>s :call MySwitch()<CR> 

I've used this function as a bool only toggle plug-in vim-toggle-bool

Switching all the flags at once

Hello,
Thank you for sharing the nice library.

I'm wondering if I could switch all the flags in a file at once.
Suppose I have a bash script like

#!/usr/bin/env bash

if true; then
    ./script1.sh
fi

if true; then
    ./script2.sh
fi

if true; then
    ./script13sh
fi

if true; then
    ./script4.sh
fi

I sometimes need to stop running all the scripts.
It would be nice to accomplish this by typing like gas

I would be happy if you could consider this.
Thank you.

Add default mapping

This seems like a pretty damn cool plugin - I think it could possibly be useful enough to add a default mapping like you did for splitjoin. I nominate gs, because it literally does nothing (for [n] seconds, actually).

Undefined variable: g:switch_builtins and invalid expression error on startup when opening a Ruby file and loading the plugin through NeoBundle

I'm using neovim 0.4.3.

After updating switch.vim, I started getting the following error on startup when opening a Ruby file:

Error detected while processing /Users/rav/.vim/bundle/switch.vim/ftplugin/ruby/switch.vim:
line   21:                                                                                                    
E121: Undefined variable: g:switch_builtins
E15: Invalid expression: [   g:switch_builtins.ruby_hash_style,   g:switch_builtins.ruby_oneline_hash,   g:switch_buil
tins.ruby_lambda,   g:switch_builtins.ruby_if_clause,   g:switch_builtins.rspec_should,   g:switch_builtins.rspec_expe
ct,   g:switch_builtins.rspec_to,   g:switch_builtins.rspec_be_truthy_falsey,   g:switch_builtins.ruby_string,   g:swi
tch_builtins.ruby_short_blocks,   g:switch_builtins.ruby_array_shorthand,   g:switch_builtins.ruby_fetch,   g:switch_b
uiltins.ruby_assert_nil ]

I tried commenting out all plugins, removing them from the bundle directory, but the error was still there.

I created an empty vimrc which only sourced switch.vim and the error was gone. After I removed NeoBundle code from my vimrc and directly sourced only switch.vim, the error was also gone.

So I went to do a git bisect, because the plugin worked without problems before updating it to recent master. I found that the commit 2bf6516 is the problematic one.

However, I have no idea how to further debug this. Any pointers will be appreciated!

Add case insesitivity

It would be neat if adding

let g:switch_custom_definitions =
    \ [
    \   ['foo', 'bar', 'baz']
    \ ]

would also handle
Foo -> Bar
FOO -> BAR
etc. without having to specify all cases for each entry.
This is implemented in Toggle.vim

Custom switch definition list ordering

Hey,

I wanted to add a few switches for res <=> req and request <=> response and did so via appending them to g:switch_custom_definitions:

let switch_custom_definitions =
    \ [
    \   ["request", "response"],
    \   ["req", "res"]
    \ ]

However, it turns out the shortest match wins, so request turns to resuest.

I was of course able to rewrite it via the dict mechanism and added a few \> in there for good measure, but how about respecting the order of those custom definitions so such common subset cases could be handled without more verbose regexps? Especially when each individual switch list does respect order. :)

Add VIM 7.3+ alert

It isn't a bug, but it would be nice to add an "alert" in the README telling that this plugin only work with VIM 7.3 or higher, since it uses the strwidth function.

help with a bash switch?

Hey Andrew, i really like your plugin! Thx for the awesome work! I use it many times daily.

Now i wanted to ask you, if you can help me with a bash switch.

I want to switch between the following variable declarations:

"${test_var}"
${test_var}
$test_var

The declarations could be placed everywhere.

Is that one easy for you?

Thx again for the plugin!

Feature request: Ruby lambdas

Hi,

Not sure if it goes to SplitJoin or Switch or both. Maybe first transformation can be done in Switch and the second one in SplitJoin.

It would be great if I could get rid of the old Ruby lambda syntax lambda { |x| } and convert:

lambda { |x| whatever(x) }

->(x) { whatever(x) }

This is one-way transformation. But the next one should be reversible:

->(x) { whatever(x) }

lambda do |x|
  whatever(x)
end

Please let me know what you think as this might be hard to make.

Less aggressive switching between - and = in slim/haml

When you switch the output statement = in slim and probably haml it turns it into -.

Okay but could you not do it from the middle of the line? I was bitten by it many times when I was replacing => with new ruby hash syntax, so I press /=><cr> then n-n-n-n-n- until I replace them all but it's been a few times when the next - turns current line from = to - and that disables the output.

The solution would be to do the replacement only if the cursor is either on or before the = in the line.

Hope my explanation makes any sense, I accidentally commented important parts like this a few times.

switch#NormalizedCase and word boundaries

switch#NormalizedCase doesn't seem to let me prevent it from matching internally in a word. Specifically, if I have switch#NormalizedCase(['or', 'and']), then switch will turn sorry into sandry, but if I try switch#NormalizedCase(['\<or\>', '\<and\>']), then 2 or 3 turns into 2 <and> 3 with the angle brackets carried along for the ride.

(Apologies if I've just missed it, and don't think I've ever said so but splitjoin and switch are 2 of the 3 best kept vim secrets in my opinion so super thanks for having written them!)

Simple switch

In Erlang it's useful to switch betweeh the forms "..." and <<"...">> so I've attempted to define:

au FileType erlang let b:switch_custom_definitions =
            \ [
            \   'string_binaries' : {
            \     '<<"\([^"]*\)">>': '"\1"',
            \     '"\([^"]*\)"':     '<<"\1">>',
            \   }
            \ ]

But this doesn't work so well when I'm inside the angled bracketed quotes as it keeps adding more angle brackets. Is it possible to do this right?

Try builtin switches _after_ custom

Hey,

There are a couple of useful switches built in that I'd like to use, but occasionally I have a need to add a more specific override. For example, with the latest addition to switch between a JavaScript function declaration (

\ 'javascript_function': {
), combined with a linear search (switch_find_smallest_match = 0), my simpler ["function*", "function"] fails to match.

Have you thought about first looking in the custom definitions and only then falling back to builtins? With a smallest match search it didn't matter, but with a linear search it makes more sense to me to first try possible overrides.

Cheers

Invert logical expression, using De Morgan Law

It would be nice if I could transform an Boolean expression using De Morgan's Theorems. It's useful when you want to convert an 'if' expression into an 'else', or simply switch the form of your expression.

image

Examples:
Selecting first OR term (!(A && B)) in the next expression and switching:
!(A && B) || C
wold give:
(A && B) || C

Anywhere in the expression:
A || B && (C || D)
transforms the whole expression into:
!(A || B) || !(C || D)
Simplifying further:
(!A && !B) || (!C && !D)

I think you get the idea...
Maybe the language servers have some functions that could help with the tokenization.

Multiline matches?

I'm trying to make a matcher to switch the different ruby block styles.

In other words, switch between:

do_something do |x|
  x.now!
end

do_something { |x| x.now! }

do_something(&:now!)

It looks like switch only looks for matches on the current line though. Am I right? If so, what do you think about multiline matching?

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.