I'm trying to create a script what permits me to select a few lines and create a virtualedit block around it; 1 column after the longest line.
This is my code
function! VirtualEdit()
let EndLine = line("'>")
set virtualedit = all
let maxlength = max(map(range(line("'<"), line("'>")), "virtcol([v:val, '$'])"))-1
call cursor(1,maxlength+1)
normal "^Q".EndLine."jc<space><ESC>"
set virtualedit = ''
endfunction
What it must do is
1) Control the longest line in my selection (maxlength).
2) Put the cursor on the first line in the selection at the column of the longest line +1 column.
3) Than Activate Visual Block selection (on my windows pc the command is C-Q)
4) Extend the visual block till the last line in the selection (the command on my pc for moving down = "j").
5) Than use the "c" key to insert a "space" character and ESC to exit the insert mode in order to fill the virtual block column with spaces.
However I can't find out how to use a variable (Endline) in a normal command.
I noted also that keys as and don't work in my above example.
What did I wrong?
You have many errors here:
:set does not let you have spaces around =
:set does not accept expressions, thus set ve='' is let &ve="''", not let &ve='' which is :set ve=.
:normal command also does not accept expressions, it accepts strings that are just executed. Thus :normal "^ is trying to use register ^, fails (no such register) and stops processing the rest of the line. Use :execute to pass expressions to :normal.
:normal command does not accept <Key> syntax. Neither do viml expressions, they have "\<Key>" instead (note: only double quotes and with backslash). ^Q syntax is not accepted by anybody and having raw control codes (displayed by vim as ^Q) inside a text file is not the best idea.
Don’t use :normal without a bang. Most of time you don’t need it (you need to replace ^Q with \<C-v> in this case though because it is a mapping).
Don’t hardcode virtualedit value. Instead of
set ve=all
<...>
set ve=
use
let savedve=&ve
set ve=all
try
<...>
finally
let &ve=savedve
endtry
{N}j means “N lines down”, not “go to N’th line”. “Go to N’th line” is {N}gg or {N}G.
You have let maxlen=<...>-1 and the on only line where maxlen is used you have maxlen+1. It is strange.
If you fix this you can proceed, but you don’t need adjusting virtualedit and using :normal at all:
function AddSpaces()
let [lstart, lend]=[line("'<"), line("'>")]
if lstart>lend
let [lstart, lend]=[lend, lstart]
endif
let maxcol=max(map(range(lstart, lend), "virtcol([v:val, '$'])"))
let newlines=map(range(lstart, lend), 'printf("%-'.maxcol.'s", getline(v:val))')
call setline(lstart, newlines)
endfunction
Related
I'm having a hard time finding the documentation for this. How do I read/write text from the current buffer in my vim functions?
More concretely, if my buffer contains the words foo bar how would write a function to overwrite the word bar with cat so that in the end my buffer contains foo cat?
You can use the substitute ex command inside a function. For example
function! ReplaceBar()
:%s/bar/cat/g
endfunction
This defines a function. The % character means operate on the entire buffer. This searches for bar, replaces it with cat, and the g flag replaces every instance on a line, not just the first.
You can run this function by typing :call ReplaceBar() and hitting enter. Often it's convenient to define a function that does this kind of work, then define a command that calls it:
command! -nargs=0 Bar call ReplaceBar()
That command can be run by typing :Bar.
To access line(s), you can use the getline() function. setline() updates those lines in the buffer. Likewise, new lines are inserted via append().
The latter can also be done with :put ={variable or expression}, and replacements with :substitute. What is better depends on the particular use case. The benefit of the former, lower-level functions is that they don't clobber stuff like the expression register, last used search pattern, search history, etc.
In neovim, they have nvim_put. A few examples:
:call nvim_put(['cat'], 'c', v:false, v:true) ; insert 'cat' right where the cursor is, as if you typed `:normal! icat`
:call nvim_put(['cat'], 'l', v:true, v:true) ; insert 'cat' on the next line
Others have covered the use of :put pretty well, so I won't cover it myself.
I am using TeXnicCenter to edit a LaTeX document.
I now want to remove a certain tag (say, emph{blabla}} which occurs multiple times in my document , but not tag's content (so in this example, I want to remove all emphasization).
What is the easiest way to do so?
May also be using another program easily available on Windows 7.
Edit: In response to regex suggestions, it is important that it can deal with nested tags.
Edit 2: I really want to remove the tag from the text file, not just disable it.
Using a regular expression do something like s/\\emph\{([^\}]*)\}/\1/g. If you are not familiar with regular expressions this says:
s -- replace
/ -- begin match section
\\emph\{ -- match \emph{
( -- begin capture
[^\}]* -- match any characters except (meaning up until) a close brace because:
[] a group of characters
^ means not or "everything except"
\} -- the close brace
and * means 0 or more times
) -- end capture, because this is the first (in this case only) capture, it is number 1
\} -- match end brace
/ -- begin replace section
\1 -- replace with captured section number 1
/ -- end regular expression, begin extra flags
g -- global flag, meaning do this every time the match is found not just the first time
This is with Perl syntax, as that is what I am familiar with. The following perl "one-liners" will accomplish two tasks
perl -pe 's/\\emph\{([^\}]*)\}/\1/g' filename will "test" printing the file to the command line
perl -pi -e 's/\\emph\{([^\}]*)\}/\1/g' filename will change the file in place.
Similar commands may be available in your editor, but if not this will (should) work.
Crowley should have added this as an answer, but I will do that for him, if you replace all \emph{ with { you should be able to do this without disturbing the other content. It will still be in braces, but unless you have done some odd stuff it shouldn't matter.
The regex would be a simple s/\\emph\{/\{/g but the search and replace in your editor will do that one too.
Edit: Sorry, used the wrong brace in the regex, fixed now.
\renewcommand{\emph}[1]{#1}
any reasonably advanced editor should let you do a search/replace using regular expressions, replacing emph{bla} by bla etc.
I usually use Geany or Hi-Tide under Debian (GNU/Linux) for firmware development, mainly C (but also reading old assembler). I document code using single-line comments, and it really annoys me when I retype something and have to manually re-break every following line to keep it in the 80-character margin.
Is there a text editor that can re-wrap consecutive single-line comments (and do this automatically while I type)? That is, given:
/// This is a really long line that should have been wrapped at "that" but was not.
/// This sentence is in the same
/// paragraph as the last.
...I want an editor that will re-wrap this to
/// This is a really long line that
/// should have been wrapped at "that"
/// but was not. This sentence is in
/// the same paragraph as the last.
...preferably doing this sensibly while I type.
I've tried:
Hi-Tide (based on Eclipse 3.3)
Geany
jEdit
UniversalIndentGUI + a bunch of prettifiers (I couldn't find any formatters that worked, and it's not a great workflow either)
GVim - next line begins //should have been... instead of /// should have been...
Update: just to elaborate on my accepted answer - I've gone with the snapshot emacs and an extra filladapt mode was also required
In Emacs, to start automatic wrapping, enter auto-fill-mode. To set the line width, run C-u ⟨columns⟩ C-x f.
Emacs, or really CC Mode, will anticipate your commenting structure, so that typing
/// This is a really long line that shoul will result in
/// This is a really long line that
/// shoul‸
And you can refill a paragraph at any time with M-q.
If you want to do refills automatically with each keypress, well there may well be some interal command or third-party library out there, but off-hand you can use this elisp code:
;;; Can't advise SELF-INSERT-COMMAND, so create a wrapper procedure.
(defun self-insert-refill (n)
(interactive "p")
(self-insert-command n))
;;; Advise SELF-INSERT-REFILL to execute FILL-PARAGRAPH after every
;;; keypress, but *only* if we're inside a comment
(defadvice self-insert-refill (after refill-paragraph)
(let ((face (or (get-char-property (point) 'read-face-name)
(get-char-property (point) 'face))) )
(if (and (eq face 'font-lock-comment-face)
(not (string= " " (this-command-keys)))) ; Spaces would get deleted on refill.
(fill-paragraph))))
(ad-activate 'self-insert-refill)
(add-hook 'c-mode-hook
;; Remap SELF-INSERT-COMMAND to be SELF-INSERT-REFILL.
(local-set-key [remap self-insert-command] 'self-insert-refill) ))
This is probably not very robust or in keeping with best-practice, and likely not wholly satisfactory, as it won't work for general editing, e.g. C-d and backspace, and it slows down the editor somewhat, but it's a start.
Vim most certainly can do this.
First, you need to tell Vim that "///" is a comment prefix (it isn't by default):
:set comments^=:///
If you want wrapping to occur as-you-type, set your preferred textwidth:
:set textwidth=80
To format existing paragraphs, use any variation of the gq command. For example, you could:
Select a paragraph visually and type gq, or
Type gqj to re-wrap from the current line to the end of the paragraph
I spent some time trying to write a 'helper' macro to test a parameter for a new value, else use the existing value -- default values exist for all parameter positions.
I wanted to be able to write:
\foo{left}{nil}{}{20pt}
so that the second parameter would used its current value but the third value would be the value empty string. I wanted to use the notation:
\edef\pA{\isnil{#1}{\pA){#1}} % one for each parameter
I defined \isnil like so:
\def\nil{nil}
\def\isnil#1#2#3{%
\edef\nilTest{#1}%
\ifx\nilTest\nil#2\else#3\fi
}
but when I tried to run it, TeX complained that \nilTest is an undefined control sequence.
That is true of course, but I want \pA to hold a value, not a recipe for a value, so it must be an \edef which means that all the macro test will be expanded but while will the \edef not protect the \nilTest -- is this a place to use \noexpand -- that did not seem to work for me.
EDIT: no digits in \cs names (yeah, I knew that.)
Why doesn't your solution work? \edef\pA{\isnil{#1}{\pA){#1}} expands \isnil and gets \edef\nilTest{.... Now \edef is not expandable and falls into a sequence of \pA as the first element. An attempt to expand the next macro \nilTest fails.
Use \setpar from the following code to change your parameter.
\def\nil{nil}
\def\setpar#1#2{%
\edef\nilTest{#2}%
\ifx\nilTest\nil\else\let#1\nilTest\fi}
\def\first{old first}
\def\second{old second}
\setpar \first{nil}
\setpar \second{new}
first = ``\first'', second = ``\second''
P.S. Do not use digits in your macro.
Given this line of code in C:
printf("%3.0f\t%6.1f\n", fahr, ((5.0/9.0) * (fahr-32)));
Is there a way to delete or yank from the first bold parenthesis to its matching parenthesis? I thought about df), but that only will get you to just after the 9.0.
Is there a similar way to get vim to grab everything between matching braces, regardless of newlines?
What about dib or di(.
It will delete the inner (...) block where the cursor is.
I love text-object motions and selections!
Various Motions: %
The % command jumps to the match of the item under the cursor. Position the cursor on the opening (or closing) paren and use y% for yanking or d% for deleting everything from the cursor to the matching paren.
This works because % is a "motion command", so it can be used anywhere vim expects such a command. From :help y:
["x]y{motion} Yank {motion} text [into register x]. When no
characters are to be yanked (e.g., "y0" in column 1),
this is an error when 'cpoptions' includes the 'E'
flag.
By default, "item" includes brackets, braces, parens, C-style comments and various precompiler statements (#ifdef, etc.).
There is a plugin for "extended % matching" that you can find on the Vim homepage.
You can read the documentation on % and related motion commands by entering :help various-motions in command mode.
object-select
There is another set of motion commands that you can use in Visual mode to select various text objects.
To solve your specific problem you would do the following:
printf("%3.0f\t%6.1f\n", fahr, ((5.0/9.0) * (fahr-32)));
^
Let's say your cursor is positioned at ^. Enter the following sequence to select the part you are looking for:
v2a)
First v enters Visual mode, then you specify that you want to go 2 levels of parens up. Finally the a) selects "a block". After that you can use d or x to delete, etc.
If you don't want to include the outer parens, you can use "inner block" instead:
v2i)
See :help object-select for the complete list of related commands.
To delete all that is inside a pair of parentheses, you can always issue di( and its derivatives.
Note :
As #porglezomb suggested in his comment, you can use a ("along with") instead of i ("inside") to include the parentheses. So, using da( deletes everything inside ( and ) including ( and ).
Deleting text inside the immediate outer pair of parentheses :
So, for this line of code
printf("%3.0f\t%6.1f\n", fahr, ((5.0/9.0) * (fahr-32)));
^ ^
| |
\_______\___---> Cursor range
assuming that your cursor is inside the above mentioned cursor range, you can issue the following commands :
di( --> Deletes '5.0/9.0'
ci( --> Substitutes '5.0/9.0'
yi( --> Yanks '5.0/9.0'
Deleting text inside the n-th outer pair of parentheses :
To grab everything inside the n-th outer pair of parentheses, just add n before the above command. So, with the same cursor position as above,
2di( --> Deletes '(5.0/9.0) * (fahr-32)'
2ci( --> Substitutes '(5.0/9.0) * (fahr-32)'
2yi( --> Yanks '(5.0/9.0) * (fahr-32)'
3di( --> Deletes '"%3.0f\t%6.1f\n", fahr, ((5.0/9.0) * (fahr-32))'
3ci( --> Substitutes '"%3.0f\t%6.1f\n", fahr, ((5.0/9.0) * (fahr-32))'
3yi( --> Yanks '"%3.0f\t%6.1f\n", fahr, ((5.0/9.0) * (fahr-32))'
You can use d% for deleting and y% for yanking.
Place your cursor on the first parenthesis, then press v%y or v%d.
Try ci[block-surrounder]
In your case, place the cursor anywhere between the 2 parenthesis that you highlighed and try the keys: ci(
As answer of David Norman says,
Place your cursor on the first parenthesis, then press v%y or v%d.
Explanation from http://vimdoc.sourceforge.net/htmldoc/vimindex.html:
tag char note action in Normal mode
------------------------------------------------------------------------------
|v| v start characterwise Visual mode
|%| % 1 find the next (curly/square) bracket on
this line and go to its match, or go to
matching comment bracket, or go to matching
|d| ["x]d{motion} 2 delete Nmove text [into buffer x]
This means it will select everything between and including the two brackets (%) while showing the selection to you visually (v) and then yank/copy y or delete/cut d it. (To the default buffer.)
You can put/paste with p.
Made this answer to "teach myself to fish".