Deprecated: Creation of dynamic property wpdb::$categories is deprecated in /var/www/twodee/blog/wp-includes/wp-db.php on line 668

Deprecated: Creation of dynamic property wpdb::$post2cat is deprecated in /var/www/twodee/blog/wp-includes/wp-db.php on line 668

Deprecated: Creation of dynamic property wpdb::$link2cat is deprecated in /var/www/twodee/blog/wp-includes/wp-db.php on line 668

Deprecated: Return type of WP_Theme::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 554

Deprecated: Return type of WP_Theme::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 595

Deprecated: Return type of WP_Theme::offsetSet($offset, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 535

Deprecated: Return type of WP_Theme::offsetUnset($offset) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 544

Deprecated: Return type of WP_REST_Request::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 960

Deprecated: Return type of WP_REST_Request::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 980

Deprecated: Return type of WP_REST_Request::offsetSet($offset, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 992

Deprecated: Return type of WP_REST_Request::offsetUnset($offset) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 1003

Deprecated: Return type of WP_Block_List::current() should either be compatible with Iterator::current(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 151

Deprecated: Return type of WP_Block_List::next() should either be compatible with Iterator::next(): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 175

Deprecated: Return type of WP_Block_List::key() should either be compatible with Iterator::key(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 164

Deprecated: Return type of WP_Block_List::valid() should either be compatible with Iterator::valid(): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 186

Deprecated: Return type of WP_Block_List::rewind() should either be compatible with Iterator::rewind(): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 138

Deprecated: Return type of WP_Block_List::offsetExists($index) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 75

Deprecated: Return type of WP_Block_List::offsetGet($index) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 89

Deprecated: Return type of WP_Block_List::offsetSet($index, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 110

Deprecated: Return type of WP_Block_List::offsetUnset($index) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 127

Deprecated: Return type of WP_Block_List::count() should either be compatible with Countable::count(): int, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 199

Deprecated: Creation of dynamic property Automattic\Jetpack\Connection\Manager::$error_handler is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/vendor/automattic/jetpack-connection/src/class-manager.php on line 91

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Instagram_Gallery::$is_wpcom is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-instagram-gallery.php on line 23

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Mailchimp::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-mailchimp.php on line 17

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Tweetstorm_Gather::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-tweetstorm-gather.php on line 21

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Tweetstorm_Gather::$is_wpcom is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-tweetstorm-gather.php on line 22

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Gutenberg_Available_Extensions::$wpcom_is_site_specific_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/gutenberg-available-extensions.php on line 20

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Memberships::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/memberships.php on line 23

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Memberships::$wpcom_is_site_specific_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/memberships.php on line 24

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Subscribers::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/subscribers.php on line 15

Deprecated: Creation of dynamic property Automattic\Jetpack\Sync\Queue::$random_int is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/vendor/automattic/jetpack-sync/src/class-queue.php on line 38

Deprecated: Creation of dynamic property Automattic\Jetpack\Sync\Queue::$random_int is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/vendor/automattic/jetpack-sync/src/class-queue.php on line 38

Deprecated: Creation of dynamic property WPCOM_Widget_Goodreads::$shelves is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/modules/widgets/goodreads.php on line 33

Deprecated: DateTime::__construct(): Passing null to parameter #1 ($datetime) of type string is deprecated in /var/www/twodee/blog/wp-includes/script-loader.php on line 348

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$toolbar_classic_block is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 347

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$toolbar_block is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 349

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$toolbar_block_side is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 350

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$panels_block is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 351

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$used_block_buttons is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 354

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: ltrim(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/twodee/blog/wp-includes/wp-db.php on line 3030

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383

Warning: Cannot modify header information - headers already sent by (output started at /var/www/twodee/blog/wp-includes/class-wp-block-list.php:14) in /var/www/twodee/blog/wp-includes/feed-rss2.php on line 8
vim – teaching machines https://twodee.org/blog Fri, 20 May 2016 14:06:07 +0000 en-US hourly 1 https://wordpress.org/?v=5.7.1 Vim Autotemplates https://twodee.org/blog/14881 https://twodee.org/blog/14881#respond Fri, 20 May 2016 13:49:23 +0000
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383
http://www.twodee.org/blog/?p=14881 [...]]]> When I create a brand new file in Vim, I automatically insert template text into it. For Java, the template looks like this:

public class CLASS {
  CURSOR
}

The C template looks like this:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
  CURSOR
  return 0;
}

The HTML template looks like this:

<!DOCTYPE html>
<html>
<head>
  <title>...</title>
</head>
<body>
  CURSOR
</body>
</html>

A student has asked how I do this. I’m sure I picked up the knowledge from somewhere else, but the provenance data has been lost. So, I’ll share my configuration here and pretend like I was its sole author.

First, I put all my template files in some known location. I have a universal configuration repository that I clone on all the machines I use regularly. My templates sit in a directory within this clone named vim/templates. The template files are named according to the extension I use for that file type. For example, the Java template file is named java, the C++ template file is named cpp, and so on.

Second, I added the following autocommand to my .vimrc file, which I explain in more detail below:

autocmd BufNewFile *
\ let templatefile = expand("/PATH/TO/UNIVERSAL/CONFIGURATION/configs/vim/templates/") . expand("%:e")|
\ if filereadable(templatefile)|
\   execute "silent! 0r " . templatefile|
\   execute "normal Gdd/CURSOR\<CR>dw"|
\ endif|
\ startinsert!

Let’s break this down a bit:

  1. The autocommand will run on new file events (BufNewFile) for all files (*).
  2. The %:e grabs the extension of the new file.
  3. Command filereadable checks to see if a template file with this extension exists in the known location.
  4. If the file is readable, I use the r command to read in the template’s contents. The 0r ensures that the contents are placed after line 0—in other words, at the start of the file.
  5. Gdd removes the extra blank that appears at the bottom of the file.
  6. To indicate where I want the cursor to be, I include a CURSOR placeholder in each template. /CURSOR\<CR>dw jumps to the CURSOR placeholder and deletes it. The cursor stays there.
  7. The startinsert command puts us in insert mode. The ! makes this command behave like A, so we start appending text to the line that once held the placeholder.

Adding new templates requires only that I put a new template file in the templates directory.

]]>
https://twodee.org/blog/14881/feed 0
You won’t believe what happens when you type these 19 things into Vim! https://twodee.org/blog/8749 https://twodee.org/blog/8749#respond Tue, 04 Feb 2014 20:55:41 +0000
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383
http://www.twodee.org/blog/?p=8749 [...]]]> A student group at my university asked me to come talk about Vim at their upcoming meeting—which was two days away. I said no. Then they wised up and asked me to speak at a meeting sometime next semester. I said okay. Following are 19 of my favorite Vim editing tricks.

Insert Mode

Complete filenames

Suppose you’re shelling around:

$ ls
utilities.c main.c
$ vi makefile

In the makefile, you go to type the names of the sources files upon which your executable depends. To minimize spelling errors and time spent typing, starting typing just the first few letters of the filename and then hit <Control-x><Control-f>:

main: u<Control-x><Control-f>

This completes the filename under the cursor:

main: utilities.c

If multiple files match the prefix that’s been typed, cycle through them with <Control-f>.

Enter evaluation of an expression

You’re typing in a document and a need to do some math. While in Insert mode, hit <Control-r>=. You’ll be prompted to enter a Vimscript expression. Simple arithmetic is supported. For example:

The number of pixels is <Control-r>=1024 * 768<CR>.

yields

The number of pixels is 786432.

Factor out a variable

Suppose you’ve got a literal in an expression that you’d like to pull out into a variable:

double nsamples = nseconds * 22050;

22050 would be better named SAMPLE_RATE. In very few keystrokes, we can rip out the 22050, replace it with a new name, and insert a declaration on the preceding line. Our method will make use of the following truths:

  1. Normal mode’s cw deletes the word under the cursor and goes into Insert mode so you may type it’s replacement. Think of it as “change word.”
  2. Deleted text may be recalled by accessing the " register.
  3. O in normal mode opens a new line above the current one.
  4. Control-A in insert mode enters the text entered during the last insert mode.

Put your cursor at the beginning of 22050. Then enter cwSAMPLE_RATE<Escape>Oint <Control-a> = <Control-r>";. When the dust settles, you’ve got:

int SAMPLE_RATE = 22050;
int nsamples = nseconds * SAMPLE_RATE;

Shortcut System.out.println

Eclipse offers a shortcut for generating System.out.println. We simply type sysout and then hit <Control-Space> to expand.

We can do something similar in Vim using abbreviations. In Normal mode, enter :iabbr sysout System.out.println. Now, if we type sysout followed by some non-identifier character like (, Vim will correctly expand our abbreviation.

Normal Mode

Increment and decrement numbers

Whether it’s because you’ve got off-by-one errors or because you’re copying and pasting array element processing code, we often need to increment or decrement integer literals. This can be done quickly in Normal mode by placing the cursor anywhere on or before the number to be altered and hitting <Control-a> or <Control-x>. For example, suppose the cursor is on the first line of the following:

states[1] = "Virginia";
states[2] = "Wyoming";

If you hit <Control-x>j<Control-x>, you’ll end up with:

states[0] = "Virginia";
states[1] = "Wyoming";

Repeat the last command

Suppose you’ve got this text:

f(param0);
  ..
  f(param0);
    ..
    f(param0);
f(param0);

Suddenly, the signature for f changes. It gets a new parameter, and at each call site, you’d like to add param1. You could do a find/replace, but sometimes that’s too much overhead. Instead, we can add the text at one call site, and repeat at our action at the remaining with .. With the cursor on the first 0, we enter a, param1/0.n.n. and end up with:

f(param0, param1);
  ..
  f(param0, param1);
    ..
    f(param0, param1);
f(param0, param1);

Open file under cursor

Maybe you’re editing a makefile. Maybe you’re editing a Java source file. It doesn’t matter. At one time or another, you want to open the file associated with the word under the cursor. The word might be a filename, or it might be the name of a class. Hit <Control-w><Control-f> and it opens.

Train yourself away from the cursor keys

“If you can keep your fingers on the home row,” people will tell you, “then you can type much faster.” I don’t find typing speeds an issue, because usually I have to think as much as I type—and thinking is the real bottleneck. However, I don’t want to strain my body unnecessarily. Let’s keep those fingers on the home row.

The cursor keys are far from the home row. Good news. In normal mode, h is the same as <Left>, l is <Right>, j is <Down>, and k is <Up>. However, old habits die hard. You can wean yourself off of the cursor keys by mapping them to do nothing:

nmap <Left> <Nop>
nmap <Right> <Nop>
nmap <Down> <Nop>
nmap <Up> <Nop>

Move cursor quickly to a character

You cursor is sitting at the beginning of the line. It needs to be at the hyphen between those two words really far away. How do you get there? The mouse? Hardly. Use the f command. In particular, f- will advance to the first comma after the cursor. 2f- to the second. 3f- to the third. And so on. But you don’t have to count if you don’t want to. Just hit f- and then ; to jump to the next match. If you overshoot, hit , to jump to the previous match.

If the cursor appears after the target, use F- instead.

f and F will take you right to the match. If you’d like to stop short at the character right next to the target, use t and T. For example, maybe you’re in the open and close of an XML/HTML element and you want to land on the first character after the opening tag. T> will do the trick.

Change, yank, and delete with precision

The commands c, y, and d are used to change, yank, and delete text, respectively. You follow each of these commands with a motion to indicate what text is affected. For example, cw changes a word, dd deletes a line, and y2w yanks two words.

These commands can also be followed by [ fFtT]. To delete from the cursor until the semi-color, hit dt;. To yank through the next closing parenthesis, hit yf). A count can be provided to target the nth character from the cursor.

Vim also supports quick processing of delimited text. To delete everything between parentheses, hit di(. This also works for [], {}, “”, ”. Suppose your delimiters are not single characters, but tags. Use dit. Suppose you want to delete not just the contents of the delimiters, but the delimiters too. Use da(.

Capturing complex edits with macros

Once I needed to create a 50-element array of State objects, each holding its states capital and name. I found a list in this format online:

Madison, Wisconsin
Des Moines, Iowa
Montpelier, Vermont
...

To convert each line into the construction of a State, I first transformed just the first line—but I recorded my keystrokes into register a as I did so using the record macro command q. I entered qaInew State("<Escape>f,i"<Escape>Wi"<Escape>A"),<Escape>j. Then I hit @a to play back the macro I stored in register a on the next line. After seeing that it worked, I hit 48@@ to play back the last register 48 more times.

I ended up with:

new State("Des Moines", "Iowa"),
new State("Madison", "Wisconsin"),
new State("Montpelier", "Vermont"),
...

All that remained was to surround all the states in  {} and assign the result to a State[].

Regular expressions would also have worked.

Visual Mode

Often I find myself needing to edit text that is vertically aligned. Maybe several lines in a row are assigning values to some array elements, and I need to alter the index expression in some uniform way. Maybe I’ve copied some numbers that are formatted in columns, and I need to separate each column with a comma. I could use a macro, or I could use a regular expression and substitution. But there’s also Visual Block mode.

Say I’ve got the numbers problem. I need to turn these numbers into a CSV file:

0.048909 0.524034 0.394847 0.317906
0.693668 0.608016 0.962821 0.887913
0.224440 0.929916 0.536071 0.421397
0.422353 0.911034 0.282418 0.496423

(If the file contained no the other spaces, :%s/ /,/g would do the trick. Let’s assume the file does contain other spaces.)

With the cursor at the beginning, I hit f<Space> to go to the space separating the first two columns, <Control-v> to go into Visual Block mode, 3j to select the next three lines, s to substitute the selected text and go into Insert mode, , to replace the text on the first line, and <Escape> to apply the substitution to the remaining lines. Once satisfied with my edit, I hit ;. to repeat on the next column and then ;. once more.

Ex Mode

Substitution

Because I care, I am constantly renaming things. Next to typing in Insert mode, finding and replacing is probably my most frequent action I take in Vim. At its simplest, I just type:

:%s/oldname/newname/g

I can shorten my work a little bit by placing the cursor on a word I want to replace and hitting # or *. Then, I can leave the search pattern blank:

:%s//newname/g

I can confine the substitution to just the visually selected lines just by being in Visual mode. The range of operation is automatically set to '<,'> when I press ::

:'<,'>s/oldname/newname/g

Usually I qualify the substitution to confirm each replacement, at least until I’m reasonably sure my pattern doesn’t lead to false positives and the substitution is correct:

:%s/oldname/newname/gc

Autocomment

You are coding and want comment out some lines. We can do this in many text editors by selecting some lines and hitting <Control-/>. We can make Vim do this too.

First, let’s do this without a special keybinding. Select some lines by going into visual line mode with V. Move the cursor to expand your selection. Prefix all the selected lines with // by entering :'<,'>normal i//. Remove the comment characters with :'<,'>normal xx. These two Ex commands apply a normal mode command to each line in the visually selected range.

We don’t want to type those Ex commands all the time. We can map <Space>/ to prepend the comment character with vmap <Space>/ :normal i//<CR>. The logic to toggle comments can be wrapped up inside a function to make this solution better.

Operating on multiple files

Suppose you need to change a function name that’s used in many files. What a pain, right? No, substituting in a new name across multiple files is only mildly more difficult than substituting it in one. The argdo command lets us apply a command to each file that we sent to Vim as a command-line argument. For example:

:argdo %s/oldfunc/newfunc/

This command essentially iterates through the argument list and applies the subsequent command. You or your settings may require that the current file be written before advancing to the next. Simply append a second write command:

:argdo %s/oldfunc/newfunc/ | w

Cropping search results for smarter substitution

Imagine you’re editing and need to substitute some text. To match the text that needs updating, you must include some context that you don’t plan on changing. For example, maybe you’ve got an HTML file and you want to replace all the anchor tag links with #, because you’re starting to do things with Javascript now. The file has other links embedded in the text, so you need to be careful that you don’t oversubstitute.

One approach is to capture the surrounding context and explicitly reinsert the unaltered context back in with :%s/\(<a href="\)[^"]\+\(>\)/\1#\2/g. Zero-width assertions, however, would let you match the context without trying to substitute over it:  :%s/\(<a href="\)\@<=[^"]\+\(>\)\@=/#/g. Who thinks this is ugly? I do.

The \zs and \ze commands achieve the same effect much more simply by allowing you to delimit which portion of the matched text gets substituted: :%s/<a href="\zs[^"]\+\ze">/#/g.

Vimrc

Autocommands

Many settings or keybindings depend on the kind of file one is editing. For instance, I like to map <Space>x to execute the script I’m editing without having to go out to the shell. I can do that laboriously with Ex command :!interpreter %, in which  % expands to the path of the current file. Language-specific keybindings make it way better:

autocmd BufEnter *.py
\ map <Space>x :!python %<CR>

autocmd BufEnter *.rb
\ map <Space>x :!ruby %<CR>

autocmd BufEnter *.hs
\ map <Space>x :!runhaskell %<CR>

Restoring cursor position on load

Our edits to a file are often spatially coherent. If we change a line in a file, save it, and reopen it, we’re likely to make more edits near our last edit. On reopening, however, we find that Vim’s cursor is sitting right at the beginning of the file. It’d be really, really nice if our cursor was automatically placed at our last edit.

It turns out that Vim automatically stores the last cursor position as a mark. We can jump to it manually with `" or automatically using an autocommand:

autocmd BufReadPost *
\ if line("'\"") > 0 && line("'\"") <= line("$") |
\   execute "normal! g`\"" |
\ endif

Others

Comparing two files

Say you’ve got a file a.txt. However, this a.txt is on both your hard drive and a USB drive. The modification times are inconclusive. You fear that each may have changes the other does not. How can you compare and possibly merge them? Just use Vimdiff:

vimdiff path/to/one/a.txt path/to/other/a.txt

The two panes will show the two files with differences highlighted and similarities collapsed. Scrolling in one will scroll in the other. [c and ]c will navigate between differences.

]]>
https://twodee.org/blog/8749/feed 0
Quick Commenting in Vim https://twodee.org/blog/7831 https://twodee.org/blog/7831#respond Mon, 13 May 2013 02:46:11 +0000
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383
http://www.twodee.org/blog/?p=7831 [...]]]> Speedy commenting is a major feature of any IDE like Vim. I’m sure there are good plugins that support it, but I don’t like other people’s code. I wrote my own, and here it is, ready for you to not like it.

It works on the premise that for each type of file you have, you register what the comment characters are for that type of file. The catch-all is the pound sign:

autocmd User,BufEnter *
\ let b:commentStart='#'|
\ let b:commentEnd=''

For HTML and XML, we’ve got:

autocmd User,BufEnter *.htm,*.html,*.xml,*.xsl,*.xsd
\ let b:commentStart='<!--'|
\ let b:commentEnd='-->'

Other languages are defined similarly. Only a few, like C, Haskell, and HTML require b:commentEnd to be a non-empty string.

Next I bind <Space>c to comment and -c to uncomment in both normal and visual mode. Hitting 5<Space>c in normal mode comments out the next five lines from the cursor. Or, I can hit V, select my five lines, and hit <Space>c.

These mappings lead to a couple of Vimscript functions, which do the real work.

map <silent> <Space>c :<C-U>call CommentNLines(1, v:count1)<CR>
map <silent> -c :<C-u>call CommentNLines(0, v:count1)<CR>

" Comments or uncomments the specified number of lines, starting from the line
" on which the cursor currently sits.
function! CommentNLines(wantsComment, nLines)
  " There's a companion function that will comment or uncomment a specified
  " range of lines, so our work here is just to determine the range and then
  " call that helper function.

  " We start at the cursor...
  let startAtLine = line(".")

  " And go nLines further, but going no farther than the end of the file.
  let endAtLine = startAtLine + a:nLines - 1
  if endAtLine > line("$")
    let endAtLine = line("$")
  endif

  call CommentLines(a:wantsComment, startAtLine, endAtLine)
endfunction

" --------------------------------------------------------------------------- "

vmap <silent> <Space>c :<C-U>call CommentSelectedLines(1)<CR>gv
vmap <silent> -c :<C-u>call CommentSelectedLines(0)<CR>gv

" Comments or uncomments the visually selected lines.
function! CommentSelectedLines(wantsComment)
  " There's a companion function that will comment or uncomment a specified
  " range of lines, so our work here is just to determine the range. The marks
  " '< and '> tell us the bounds of the visually selected range.
  silent call CommentLines(a:wantsComment, line("'<"), line("'>"))
endfunction

" --------------------------------------------------------------------------- " 

function! CommentLines(wantsComment, startAtLine, endAtLine)
  " Assert that comment characters have been registered for this buffer.
  if !exists("b:commentStart") || !exists("b:commentEnd")
    echo "No comment character registered for this filetype."
    return
  endif

  " We only want to allow a line to be commented once. This is particularly
  " true in C, where /* */ comments cannot legally nest. We also don't want to
  " try to uncomment a line that hasn't been commented. Let's find a pattern
  " that we can use later to ask a line its commented status.
  let commentedPattern = '^\(\s*\)\M' . b:commentStart . '\m \(.\{-}\) \M' . b:commentEnd . '\m\s*\(\\\)\?$'

  " There's one slightly funny thing in this pattern and the ones below. If I
  " have C preprocessor macro split across multiple lines, like this
  "   #define SQUARE(a) \
  "     a \
  "     * \
  "     a
  " I can't legally end the \-suffixed lines with the */ comment character. The
  " comment must be part of the macro, so the end comment character must appear
  " before the closing slash:
  "   #define SQUARE(a) \
  "     /* TODO: parenthesize a someday */\
  "     a \
  "     * \
  "     a
  " The patterns take into account closing backslashes and do not try to wrap
  " them inside the comment. Probably I should only handle this in C and C++,
  " but it's not manifested itself as an issue in other languages.

  " Comment and uncomment are handled with the same algorithm; the only
  " thing that changes is the pattern and substitution that we perform.
  if a:wantsComment
    " For a comment, we place the comment character after all leading
    " whitespace. I like my comments indented coherently, not up against the
    " left margin. \1 holds the leading space, and \2 everything else on
    " the line.
    let pattern = '^\(\s*\)\(.\{-}\)\(\\\)\?$'
    let substitution = '\1' . b:commentStart . ' \2 ' . b:commentEnd . '\3'
  else
    " For decommenting, we can reuse the comment pattern already defined. The
    " leading space is captured in \1, and the text between the comment start
    " and comment end is in \2.
    let pattern = commentedPattern
    let substitution = '\1\2\3'
  endif

  " Now, we're ready to visit each line and either comment or uncomment it.
  let i = a:startAtLine
  while i <= a:endAtLine
    let line = getline(i)

    " Is the line already a comment or a non-comment?
    let isAlreadyComment = line =~ commentedPattern

    " Don't operate on blank lines and make sure that the line isn't
    " already what the caller wants it to be. That is, we don't comment
    " a line twice, nor do we uncomment it twice. 
    if line !~ '^\s*$' && isAlreadyComment != a:wantsComment
      call setline(i, substitute(line, pattern, substitution, ''))
    endif

    let i = i + 1
  endwhile
endfunction

Comments with a wriggle of the nose!

]]>
https://twodee.org/blog/7831/feed 0
Automatic Alias Creation in Mutt/Vim https://twodee.org/blog/7108 https://twodee.org/blog/7108#comments Sun, 17 Mar 2013 05:42:46 +0000
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383
http://www.twodee.org/blog/?p=7108 [...]]]> A friend has got me thinking about using Mutt again. I gave it up years ago after I was forced to use IMAP for one of my mail accounts, and I didn’t think Mutt was up to the task. I switched to Thunderbird, which lets me do certain things faster. However, I’ve really missed a few features from Mutt: textual and portable configuration files, multiple message replies, and full Vim support.

As I return to Mutt, I also miss a few things from Thunderbird. The most prominent of these is autocompletion of my recipients. Mutt will tab-complete aliases that you’ve previously registered in its configuration files, but Thunderbird one-ups Mutt by automatically storing the addresses of people you send messages to. I wanted to make Mutt do that too.

I looked around for hooks, but I didn’t see a way for Mutt to automatically record aliases when I sent a message. However, since I was using Vim to edit my messages, I saw that I could create an autocommand that would strip out the recipients’ addresses from my message and append them to my alias file. So, I first wrote a function to do the heavy-lifting:

" This function, which is to be run only on a Mutt email message,
" finds all the addresses in the To, Cc, and Bcc headers. If
" no aliases exist for these addresses, they are added to the
" alias file.
function! AddMuttAliases()

  " This is where my alias file lives. Change this to something
  " that suits you.
  let aliasfile = $UU . '/configs/mutt/aliases'

  " Why isn't there a match + matchstr? match only gives me the
  " start, which is not enough to extract the substring.
  " matchstr doesn't give me the location, which is not enough
  " information to advance forward.

  " Find all email addresses. My pattern may not be the best yet.
  let addresses = []
  silent vimgrep /^\(To\|Cc\|Bcc\):/j %
  for line in getqflist()
    let pattern = '[-A-z._]\+@[-A-z._]\+'
    let start = match(line.text, pattern)
    let address = matchstr(line.text, pattern, start)
    while address != ""
      call add(addresses, address)
      let start += len(address)
      let address = matchstr(line.text, pattern, start)
    endwhile
  endfor

  " Check to see if each is in aliases file. If not, add it.
  " Mutt's alias registration command has this form:
  "
  "   alias name address
  "
  " Usually the name is something short and mnemonic. I prefer
  " to continually work with people's addresses so that I'm not
  " too crippled when I lose my configuration.  So, my aliases
  " have this form:
  "
  "   alias address address
  "
  " Isn't this overly verbose? Yes. What have I gained? Well,
  " mutt will tab-complete the addresses for me. Verbosity
  " doesn't matter. And that's sweet.
  for address in addresses
    execute 'silent! vimgrep /' . address . '/j ' . aliasfile
    if len(getqflist()) == 0
      let aliasline = 'alias ' . address . ' ' . address
      silent! execute '!echo ' . aliasline . ' >> ' . aliasfile
    endif
  endfor
endfunction

To call this function when Mutt messages are written, I registered the following autocommand in my .vimrc file:

autocmd BufWritePost ~/.tmp/mutt-* call AddMuttAliases()

This command assumes Mutt messages are temporarily stored in ~/.tmp, which I set in my .muttrc.

Now everytime I write a message to someone new, I get an alias added to my aliases file. The next time, I can simply tab-complete to enter the person’s address!

]]>
https://twodee.org/blog/7108/feed 2
Restoring the Last Known Cursor Position in Vim https://twodee.org/blog/6750 https://twodee.org/blog/6750#respond Wed, 27 Feb 2013 13:44:55 +0000
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383
http://www.twodee.org/blog/?p=6750 [...]]]> In unconfigured Vim, the cursor is placed at the beginning of each file that I open. When I close a file in Vim and open it again later, it’d be really nice if the cursor would automatically move to where I left off editing. And it can, with this handy autocommand:

" When editing a file, always jump to the last known cursor position.
" Don't do it when the position is invalid or when inside an event handler
" (happens when dropping a file on gvim).
autocmd BufReadPost *
\ if line("'\"") > 0 && line("'\"") <= line("$") |
\    execute "normal g'\"" |
\ endif

Autocommands let you write callbacks for certain events that occur in certain files. Here, we are defining some code that we want to execute after we open (BufReadPost) a file of any type (*). The code itself reads the last known cursor position, which Vim kindly stored for us in a special register named ” (that’s a double-quote). (Information like this is stored in ~/.viminfo, but this doesn’t concern us.) Then we

  1. Determine if the line number where the cursor was at still exists in the file. 1 is the first valid line and line(“$”) is the last valid line, so line(“‘\””) must be within this range. We need this check because some other editor may have altered the file and invalidated our bookmark.
  2. If we’re in range, issue a keyboard command: g'”, which means go to the line number stored in register “.

This autocommand was pulled directly from Vim’s help pages.

]]>
https://twodee.org/blog/6750/feed 0
Swapping first_second to second_first in Vim https://twodee.org/blog/6737 https://twodee.org/blog/6737#respond Tue, 26 Feb 2013 22:21:27 +0000
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383
http://www.twodee.org/blog/?p=6737 [...]]]> When I write C code, I never know how to name functions. In an object-oriented language, my methods are verbs: add, insert, get, swashbuckle, and so on. The subject or indirect object of these verbs is an instance of the containing class, making my code read like English sentences: vector.add, list.insert, image.get, swashbuckler.swashbuckle.

In C, which has one global namespace, functions simply can’t be named generically. Add, insert, and get are out of the question. Usually, I add the name of the data structure to the function: vector_add, list_insert, image_get. However, sometimes I get the order swapped in my head, and type in insert_list or free_stack or some such.

It happens often enough that I wrote a Vim macro to turn free_stack into stack_free:

nmap <Space>_ dt_ea_<ESC>pbx

I hit <Space>_ with the cursor in the offending function identifier and the tokens get switched around. Let me break down this command into its steps:

  1. Delete (d) text starting at cursor right up until underscore (t_). The results are stored in Vim-tracked register variable.
  2. Go to the end of the identifier under the cursor (e).
  3. Go into insert mode after the cursor position (a).
  4. Insert an underscore (_).
  5. Go into command mode (<ESC>).
  6. Paste the contents of the register (p).
  7. Back up to the beginning of the identifier, to the underscore we didn’t delete (b).
  8. Delete the character under the cursor, the underscore (x).
]]>
https://twodee.org/blog/6737/feed 0