Posted January 26, 2010
A few days ago I had to create list of email addresses sorted on the
domainname. All addresses with the same name should clump together. Being a
Perl programmer, I quickly wanted to write a Perl script to sort this list of
data. Then I tought, why not use Vim to look at the intermediate steps and do
it with filtering. The following is the result.
:%!perl -pe 'm/\@([-\w]+)\./; $_="$1\#$_";'
:%!sort
:%!cut -d\# -f2
The first line parsed the domain from the data and pastes it in front of the
orignal, seperating it with a '#'. The second line obviously sorts the new
list. The final line removes the domain that I put in front. This leaves a
list of the originals.
:%!perl -pe 'm/\@([-\w]+)\./; $_="$1\#$_";' | sort | cut -d\# -f2
This will do it in one line.
Posted November 9, 2009
On Coding Horror Jeff
wrote about whitespace at the end of lines of code. I hate that as much as the
next guy. It seems irrational, but I think it's not. It has no function and
only creates problems on times when you don't expect them, especially with
source code control tools.
So I wrote a small piece of Vim script code to highlight the spaces at the end
of the line in bright red.
highlight OverLength ctermbg=darkred ctermfg=white guibg=#FFD9D9
function! EndOfLineWhitespace()
3match OverLength /\s\+$/
endfunction
call EndOfLineWhitespace()
This will highlight all the whitespace at the end of a line. If you don't like
to use this for all files, you can use the usual ways to do this in Vim.
UPDATE: Since Vim 7.2 it is possible to use another function instead of the
match functions. It's called matchadd. The solution I gave above can be written
as follows:
highlight OverLength ctermbg=darkred ctermfg=white guibg=#FFD9D9
call matchadd('OverLength', '\s\+$', -1)
See the help documentation for matchadd to see how this works.
Via VimTip810
Posted October 15, 2009
I wrote an article about GTD and
Vimoutliner. This post adds a
few simple things you can do to simplify your edits to the todo.otl file.
In Vim it is easy to autocomplete a word or line. You can complete a word by
typing the first few characters of the word you want to complete. Then type
CTRL-N to complete the word. You can try other words by typing CTRL-N more
often. This will try to complete your word with a word that can be found in the
same file.
Sometimes you need to complete a full line. This can be a person from the
PEOPLE section or a context from the CONTEXT section. To complete a full line,
type the first few characters of the line you want to complete and then type
CTRL-X CTRL-L and then you can try more lines by typing CTRL-N.
Posted August 5, 2009
At last I have found the function that will replace many spaces with one space.
I first wrote a blog post about this in januari of
2007. Then I wrote a blog post about how to enhance this
function to move the cursor one position after the inserted space. With an
update a day after that, which said that it didn't work in some instances.
Today I'm proud to announce the final and working function that works as it should.
I created this function with help from Al on StackOverflow.
Posted July 28, 2009
You would like to add an automatically updated timestamp in your text files.
You can do that by adding 6 lines of code to your .vimrc.
The following command will call the function LastMod() whenever a buffer of
file is written.
autocmd BufWritePre,FileWritePre *.html call LastMod()
The following function will find all files containing 'Last modified:' and
replace them with the current date and time.
fun LastMod()
exe "%g/Last modified: /s/Last modified: .*/Last modified: " . strftime("%Y-%m-%d %T")
endfun
The biggest problem with this function is that using the :substitute function
will move the cursor to the beginning of the line. This will
even happen when nothing gets replaced. This is extremely annoying.
This can be fixed by remembering the current column and setting the cursor back
to that after the command. Remembering the cursor position is easy.
let save_cursor = getpos(".")
And restoring it is not much harder.
call setpos('.', save_cursor)
I added . "/e" to the and of the regex to catch errors. Without the e flag an error
will happen when there is no line matching the regex.
With all these changes the code now looks like this:
fun LastMod()
let save_cursor = getpos(".")
exe "%s/Last modified: .*/Last modified: " . strftime("%Y-%b-%d %X") . "/e"
call setpos('.', save_cursor)
endfun
Posted July 27, 2009
Vim outliner is an outliner tool. As the name implies you can write outlines
with it, but with this particular one you can also create todo lists. A todo list can
be created without much effort.
First open your todo file, todo.otl for example. By using the otl
extension, Vim outliner will be loaded automatically.
Next, type a task you have to do in the future. This could something like
write blog post about Vim outliner. Remember, because this is Vim, you have to
type i to start insert mode.
write blog post about Vim outliner
Then type ,,cb this will insert a checkbox in front the current line. Which
will make the line look like this:
[_] write blog post about Vim outliner
So now you start writing the blog post. When you're done after a few minutes
(about 30min). You can check of the item on the list. Do this by typing ,,cx.
Your file will look like this now:
[X] write blog post about Vim outliner
And this concludes this first How To blog post about Vim
outliner.
Summary
| Add a checkbox | ,,cb |
| Check a checkbox | ,,cx |
Posted May 29, 2009
Not everyone writes drafts for his Twitter posts. It seems silly even to do
this.
But for the people who don't think writing drafts is silly (and use Vim), I
wrote a few lines of Vim script that will help them keep their lines just short
enough.
Put these lines in your .vimrc file and start writing. You should change the
filename to the name of the file that you write your drafts in. As usual, this
code comes without any warranty.
" Call the function that will highlight the lines that are too long.
au BufNewFile,BufRead /home/peter/doc/twitter.txt call TwitterLineLengths()
highlight OverLength ctermbg=darkred ctermfg=white guibg=#FFD9D9
function! TwitterLineLengths()
3match OverLength /\%141v.\+/
endfunction
Code based on code from Stackoverflow.
Posted August 30, 2008
Do you know Ack? It's a grep-like program. That uses perl regular expressions instead of the normal Posix ones. You can find it on the CPAN.
The following Ack call will check your perl code for problem with a space missing behind a controlstatement keyword.
ack --perl '(?\@<!\w)(if|while|elsif|return)('
If you use Vim you can also use the following piece of vimscript in your .vimrc file:
highlight WHITE_ON_RED ctermfg=white ctermbg=red
function! BadNonInvocations ()
2match WHITE_ON_RED /\w\@<!(if\|elsif\|while\|return\|for)(/
endfunction
call BadNonInvocations()
Posted August 18, 2008
I created a small Perl program to convert relative dates to absolute dates in
the format that I use for my calendar. My current calendar file looks like this.
2008
08
2008-08-12
2008-08-13
09
2008-09-10
...
If I want to add a date and I don't know the actual numbers, I can use the
following program to convert the date. It will also respect the whitespace in
front of the text.
#!/usr/bin/perl -w
use v5.10;
use strict;
use warnings;
use Date::Manip;
Date_Init('Language=Dutch');
my $inp = <>;
if (my ($ws, $date) = $inp =~ m/^(\s*)(.+)$/) {
say $ws . UnixDate($date, "%Y-%m-%d");
}
else {
print $inp;
}
I use Date::Manip for parsing the date. It works with human language style
dates like thursday. I added Date_Init so it will parse Dutch days like
donderdag. Also I use Perl 5.10, because I can. It has some nice features.
To use it put this script in the path. I called it refdate.pl. To use it type
a date and type !!refdate.pl<Enter>. In Vim this will call the program on the
current line. The date will be formatted in the YYYY-MM-DD format.
Posted January 24, 2008
At the beginning of last year I wrote a weblog entry about how to write a
function that removes all space but one in Vim.
It didn't work like I wanted, but now it does.
function JustOneSpace()
" replace all whitespace around the cursor with a space
s/\s*\%#\s*/ /e
" search backwards for a space
call search(' ', 'be')
" move to the first character after the space
normal l
endfunction
nmap <space> :call JustOneSpace()<cr>
I added the call to the search() function to move to the space that was
substituted. All this time I wanted to fix this function by using regexes or
special vim variables. I couldn't find these. This is quite obvious, but it
didn't come to mind at first.
Update
I looks like this function doesn't work when it's used on a line with no space.
It will insert a space on the spot it is supposed to, but then moves the cursor
to the first space it finds when searching backwards.
Posted November 4, 2007
I wrote an article about Getting Things Done using Vim outliner, an outliner for Vim.
Posted June 17, 2007
Today I created a page about vim on this website. Vim is a useful
editor, but sometimes it would be nice to have more articles describing the
cool features that it has. The documentation describes every features in vim,
but sometimes it's hard to know where to start looking. I'm building this page
with links to articles that describe features or general vim goodies. So enjoy!
Posted January 25, 2007
I always wondered why vim didn't have the
just-one-space function. It's one of the most useful functions
that is available during coding.
So today I tried to write one myself, the newsgroups and searchengines didn't
come up with something good. First of course it is a good idea to understand
the effect of this operation. The just-one-space function removes all
whitespace around the cursor and replaces it with one space character.
How can this be done in vim. The replacement part isn't that hard. It can be
done with one :s///, something like: :s/\s+/ /. This
will of course remove whitespace from the wrong place, at the start of the
line.
The missing piece in this substitution is of course the place of the cursor. So
I started looking for it. Most help text about the substitution operator can be
found on :s helppage (:help :s). But there is no
mentioning of the first part of the substitution. The description of the
vim regexp engine can be found at the regexp help page (:help regexp).
This contains a description of all the possible meta characters that can be
matched. So I the meta character that will match at the cursor position
(\%#). This solved the second part of the problem.
:s/\s\+\%#\s\+/ /
This will remove the whitespace surrounding the cursor. The only only problem
that still isn't solved is the problem that the cursors moves to the beginning
of the line. It would be better if it stays at the same or a the end of line if
there is not enough room to go to the last position. Probably the best place to
put the cursor is on the first character after the inserted space. I may have to
look into that a little more.
The function is finished by adding the e flag at the end of the
substitution. With the e flags the :s will be silent
when the first part of the substitution doesn't match.
I bound the function to the spacebar in normal mode with the following command:
:nmap <space> :s/\s\+\%#\s\+/ /e
I will try this for some time and look how it works, could be good or better.
Posted December 30, 2006
Today a simple vim plugin is featured on the vim homepage:
toggle_word.vim. I
think the plugin in itself is not that useful, but it seems to be a good
starting point for ruby programmers who want to create their own vim plugin and
don't know where to start.
Posted November 6, 2006
I like using vim. It is simple want it to, but has a lot of possibities when
you need them. Like Perl in vim simple things are easy and hard things are
possible. Like the following piece of code.
I wanted to see a diff of my current version and the version in my svn
repository.
function Svndiff()
let file = system('tempfile')
execute 'silent !svn cat ' expand("%") ' > ' file
execute 'silent vertical diffsplit ' file
endfunction
map <F4> :call Svndiff()<CR>
Of course the <F4> binding is like icing on the already delicious cake. The
only thing that I'm not happy about is the problem with the tempfile, that will
stay open after you've opened the split screen.
Posted November 1, 2006
When you're typing some text in Vim, you will sometimes need a piece of text
that is easy to generate on the command line or with a simple perl script. Maybe
you want to insert the current date, a simple calendar or a list of day names.
Don't you worry there's a simple vim command that will help you with this. Here
are some examples. From simple to complex.
Insert the current date
Type:
date
on a line by itself. Then move the cursor to that line and type !!sh<cr>.
This will filter date through the shell (which is equivalent to :r!date.
The current date will be replaced into the buffer. If the output isn't correct
or different from what you expected, then you can always use u to undo the
change.
Insert a simple calendar
Type:
cal
And type the same command as before !!sh<cr>. The nice thing about using
the !! command this way, is that you can create a command line in Vim.
SQL queries collecting output
Sometimes it's easier to use the command line when conversing with you're MySQL
database instead of using phpmyadmin. This will happen when you need to create
queries based on output of other queries. An example:
SELECT `id`
FROM `entry`
WHERE `post_date`
BETWEEN '2006-10-25' AND '2005-11-05'
This query of a fictitious database will get the id's of the entries in a
datarange. This query can be piped into mysql by using the following command:
mysql -u dbuser -pdbpass databasename
As always prefix the command with !!mysql .... This will send the query to
the database. The output of the query will be replaced into the current
buffer one id on each line.
After this you can use the output together with vim to creates new queries.
Assume we got the following output:
10
11
12
13
These are the id's we got. We can translate the id into new queries by using some
Vim commands.
UPDATE `entry` SET `visible` = 1 WHERE `id` = 10
UPDATE `entry` SET `visible` = 1 WHERE `id` = 11
UPDATE `entry` SET `visible` = 1 WHERE `id` = 12
UPDATE `entry` SET `visible` = 1 WHERE `id` = 13
Now selected these queries by using V visual line mode. When you press !
now, vim will ask for a program to start, just like in the other examples. When
you use mysql, vim will send each query to the database.
A script
To print all the letters of the alphabet you can use the keyboard and type all
the letters one after another. If you are a bit more lazy and want to learn
some nice vim command and perl code, you can use the next command.
print 'a' .. 'z';
This is a line of perl code that will print all the letters of the alphabet
when executed. This line of code can be executed by typing !!perl<cr> on the
line of code. The code will expand into abcdefghijklmnopqrstuvwxyz.