I have this code:
import {
one,
two,
three,
four,
} from "../myfile";
I am trying to delete everything between the curly braces. I position my cursor anywhere between (or on) the curly braces and type di{. I am getting this:
import {
} from "../myfile";
When I am expecting this:
import {} from "../myfile";
Is there a way to achieve what I want?
There is no dedicated way to achieve that.
Here is how I do it:
caB{}<Esc>
But you could do it like this:
diBkJx
or like this:
gwiBdiB
or possibly a dozen other ways.
You can map it to something easier for the fingers if you need to do that often.
Reference:
:help c
:help aB
:help d
:help iB
:help k
:help J
:help x
:help gw
---EDIT---
FWIW, I've been puzzled by that behaviour for years.
I think the core of the issue is that there is no text after the { on the same line and no text before the } on the same line, but which character seems important.
import {___(3 spaces) If you append characters of _any_ kind to {,
one, including whitespace, then the selection
two, includes them.
} from "../myfile";
import {xxx
one,
two,
} from "../myfile";
import {xxx If you prepend whitespace characters to },
one, then they are ignored.
two,
} from "../myfile";
import {xxx If there is even _one_ non-whitespace
one, character in those prepended to },
two, then the selection includes them all.
x } from "../myfile";
I am really not sure about the rationale, here.
Related
Sorry for the bad title but
With this code,,,
import { amethod, methodb, methodc } from '../../utils/mockData';
how do you make this
import {
amethod,
methodb,
methodc
} from '../../utils/mockData';
with VIM? I mean how can I do it fast?
What I do is to
go to the first method.
press Enter
go to the end of the method..
press Enter...
go to the second method.
6....
...
It's so slow with VIM. Can we do this fast in VIM? I think I can this much faster with my mouse :(
import { amethod, methodb, methodc } from '../...';
^
f ;r<CR>;.;.;.
doesn't strike me as particularly slow. A tad too repetitive, maybe?
Here is a slightly smarter (but probably not that smart) approach:
ciB " change in brackets
<CR><CR> " insert two carriage returns
<Up> " move up one line
<C-r>" " insert previous content of brackets
<Esc> " leave insert mode
:s/,/,\r/g<CR> " put each symbol on its own line
=iB " re-indent the content of brackets
that can be mapped for convenience:
nnoremap <key> ciB<CR><CR><Up><C-r>"<Esc>:s/,/,\r/g<CR>=iB
Or you can look for a proper plugin that handles corner cases gracefully.
#romainl had a good answer, but you can also use replace for this particular case:
:%s/\([,{]\)/\1\n/g
With the cursor on line1 and col1, you can press this in normal mode:
f 4#=';r^M'
then press ENTER.
Note: for the ^M you press Ctrl-v then Enter
I have got this
import {
amethod,
methodb,
methodc
} from '../../utils/mockData';
Using this:
:%s/\v\{\zs( \w+,?)+ \ze}/\=substitute(submatch(0), " ", "\n\t", "g")
\v ............ very magic regex (avoid many backslashes)
{ ............ literal {
\zs ........... vim trick that marks the start of the pattern
( ............ start of regex group 1
<Space> ....... literal space inside group 1
\w+ ........... one word or more
,? ........... optional coma
+ ............ quantifier for the group (at least one)
<Space>
\ze ........... end of our vim search
The substitute function has three parts like a normal vim substitution and the submatch(0) corresponds to our regex, hence we are substituting in our regex one space for one line breake and two tabs.
Assuming I have the following code:
bool myCopiedFunc() {
Some code that I've written;
The cursor is on this line; <<<<<<<<<<<<<<
if (something) {
bool aValue;
some of this is inside braces;
return aValue;
}
if (somethingElse) {
this is also inside braces;
bool anotherValue;
{
more braces;
}
return anotherValue;
}
return false;
}
I decide I want to rewrite the remainder of the function, from the line with the cursor on it.
To replace up to a char on the same line, I can use ct<char> e.g. ct;
To replace up to and including a char on the same line I can use cf<char> e.g. cf;
To replace up to a string across multiple lines, I can use c/<string> e.g. c/return false
To replace up to and including a string across multiple lines, I can use... ?? e.g. ??
I can't just search for a semicolon, as there are an unknown number of them between the cursor and the end of the function, and counting them would be slow.
I can't just search for a closing brace, as there are several blocks between the cursor and the end of the function, and counting all closing braces would be slow.
With the help of code highlighting, I can easily see that the unique string I can search for is return false.
Is there an elegant solution to delete or change up to and including a string pattern?
I've already looked at a couple of related questions.
Make Vim treat forward search as "up to and including" has an accepted answer which doesn't answer my question.
In my case, I settled for deleting up to the search string, then separately deleting up to the semicolon, but it felt inefficient, and like it would have been quicker to just reach for the mouse. #firstworldproblems
To replace up to and including a string across multiple lines, I can
use... ?? e.g. ??
The / supports offsets.
In your case, you are gonna need the e offset, that is, c/foo/e.
You may want to know more details about "search offset":
:h offset
If you'll replace up to the closing brace associated to your current scope, you have c]}.
If you're looking for the end of the function, even if it means crossing to the upper scope, you'll need a plugin if the function may not be 0-indented as it's the case in C++, Java... See the related Q/A on vi.SE
Say I have the following python array literal:
def f():
arr = [
1,
2,
3
]
I want to delete everything in the brackets so that it becomes this:
def f():
arr = []
How can I do that with minimal commands in vim?
These are some of my attempts:
Using di] will delete the text, but not the empty newlines, leaving a lot of whitespace I'd have to delete:
def f():
arr = [
]
Using da] will delete the newlines, but also the brackets:
def f():
arr =
You can simply do:
ca[[]<Esc>
or:
ca][]<Esc>
See :help text-objects.
With your cursor on the first opening bracket ([), press V, followed by %. This will select the block which you then can join J, followed by di[.
Select the lines in visual mode (v) and use J to remove newlines. Then use di[.
Or if there are many lines, di[ first, after which you move the cursor to top line and then J. This will potentially leave a space between the brackets which has to be removed with x.
I find using a code formatter shortcut saves a lot of time
If you install vim prettier, you could do di[ <leader>p
Using the formatter in JS for example means I don't have to remove extra spacing, jump to end of line to insert ;, or fix indenting etc
I've already read several questions and answers:
Vim: Use tabs for indentation, spaces for alignment with C source files
Vim: Align continous lines with spaces
But none of them offers a solution for me.
I really want to apply the "Indent with tabs, align with spaces" principle, but when it comes to auto-indentation, I failed to teach Vim how to do that right.
Consider the code, assuming tabstops == 3, shiftwidth == 3
(>-- means tab, and . (a dot) means space):
{
>--long a = 1,
>-->--..b = 2,
>-->--..c = 3;
}
So, it indents with tabs as much as possible, and then fills the rest with spaces. But it is actually a very bad approach: when someone will read this code with different tab size, the code will be messed up. Here what it will look like with tab size equal to 8 chars:
{
>-------long a = 1,
>------->-------..b = 2,
>------->-------..c = 3;
}
It is horrible. The problem is that Vim doesn't distinguish between indentation and alignment.
To make it look correctly with whatever the tab size is, the code should be indented this way:
{
>--long a = 1,
>--.....b = 2,
>--.....c = 3;
}
Then, this code will look nice whatever that tab size is. For example, 8 chars:
{
>-------long a = 1,
>-------.....b = 2,
>-------.....c = 3;
}
How to achieve this?
The most powerful way to influence indenting in Vim is via 'indentexpr'. From its :help:
The expression must return the number of spaces worth of indent. It
can return "-1" to keep the current indent (this means 'autoindent' is
used for the indent).
As this returns the number of spaces, not the rendered indent itself, and Vim only so far supports tab-, space-, or maximal-number-of-tab-followed-by-spaces (called softtabstop), this cannot be done.
So, if you really want to use this indent method (I personally like it for its purity and elegance, too! (but I don't employ it)), you have to turn off auto-indenting and auto-formatting and do the entire stuff manually by yourself, unfortunately.
As you already pointed out, vim cannot distinguish if you're pressing tab to indent or because you're trying to align text, so is not possibile to automatize the behaviour you want.
Closest thing you can do is to try to play with softtabstop and different values for tabstop, but this way you get the reverse of what you asked for: pressing a tab is going to insert as much spaces possibile before using a tab.
On a side note, if you want your code to always look like you intended, you could try directly setting expandtab.
Spaces always look the same, so
{
.........long a = 1,
..............b = 2,
..............c = 3;
}
is how your code will always appear.
I have this code:
def foo(c: Char) = c match {
case 'a': 'B'
}
My cursor is on the space after =. I want to delete everything until, including, the }. How can I do that?
Can I do the same where the cursor is anywhere on the first line? Anywhere in the block (and place the cursor after the =)?
d/}/e
does the job.
d/} deletes until the } but adding the /e flag moves the cursor on the last char of the match, effectively deleting everything between the cursor and the }, inclusive.
Using visual selection works too, in a slightly more intuitive way:
v/}<CR>d
Try with this: d%.
The d is for delete and the % moves between braces.
This should work:
d}
This deletes one paragraph forward.
You can achieve something like this with the EasyMotion plugin.