Monday, December 13, 2010

List File Plugin for Vim

A while back, I had a post about managing lists in vim. Since then, I've found greater and greater use for the script and have invested more time into it. I've decided to put it on

I'm going to reproduce the documentation in the plugin itself with the addition of some in-depth explanation.

Check this post often, as I will keep the documentation up-to-date with the latest features and tweaks.

The plugin helps me manage a plain-text file of nested lists. I use it to manage to-do lists, shopping lists, URLs---all in the same file. It manages priority, status, date, custom folding, among other things. It supports tagging, timestamping and searching with vim's quickfix list. Aside from the shortcuts and commands below, indentation and folding are managed by the standard vim mappings.

First Step

:Lcreate <name> - create new list file in current buffer with <name> (".list" is added automagically)

Creating Items

,n - create new item
<enter> - (insert or normal) create new item
,s - create sub item
<tab> - (insert or normal) create sub-item
,u - create super item

Marking Items

:Lmark <mark> - (normal or visual line) mark item(s) with <mark>
,p - mark item with '=' (in progress)
,x - mark item with 'x' (completed)
,o - mark item with 'o'
,? - mark item with '?'
,- - mark item with '-' (default, incomplete)
,N - set priority as N, where N is 1-5

Tagging Items

:Ltag <tag> [tag ...] - (normal or visual line) add tag(s) to line(s) (has auto complete)
:Ltagr <tag> [tag ...] - (normal or visual line) remove tag(s) from line(s) (has auto complete)

Searching For Items

:Lsearch mark <mark> - find all items with <mark> (e.g.: =, 1, -, etc.) using location list
tag <tag> - find all items with <tag> using location list
due [date] - find all items due on [date]. Today is the default.

Setting Due Dates

:Ldue [date] - (normal or visual line) set due date. Today is the default.
:Lduer - (normal or visual line) remove due date
Due dates are in the format YY-MM-DD or any of: yesterday, today, tomorrow,
N day[s], N week[s] (where N is a number)
N:M day[s], N:M week[s] (where N and M are numbers and N <= M)
E.g.: To see all items due this week or next week: :Lsearch due 0:1 week
To see all items due next week: :Lsearch due 1:1 week
To see all items due last, this, or next weeks: :Lsearch due -1:1 week
To see all items due tomorrow or the next day: :Lsearch due 1:2 day
To make an item due end of next week: :Ldue 1:1 week
To make an item due one week from today: :Ldue 1 week
To see all items due in exactly four days: :Lsearch due 4 days

Sorting Items

,r - (visual line) sort highlighted items
,r - (normal) sort entire file

Et Cetera

,t - add/update last-modified timestamp on item


listFile_timestamp = 0
Should timestamps be added to each item by default? Set to 1 to show a timestamp by default.

listFile_indent = 4
Standard indent for nesting.

listFile_ranks = ['=','1','2','3','4','5','o','-','?','x']
Rank of marks for sorting. Note that your own, custom marks can be added to this list and used with the :Lmark command above.

listFile_mark = '-'
Default mark for new items.

listFile_dateFormat = '%y-%m-%d'
Default format for due dates.

Advanced Configuration

Here's an example of something you may put in your .vimrc file:

" add new "!" mark to ranking
let g:listFile_ranks = ['=','1','2','3','4','5','!','o','-','?','x']

" open local projects list file
nmap <Leader>l :60vsplit ~/projects.list

" add my mappings when a list file is loaded
autocmd BufNewFile,BufRead *.list call MyListFileStuff()
fun! MyListFileStuff()
" add "!" mark for normal and visual modes
nmap <buffer> ,! :Lmark !<CR>
vmap <buffer> ,! :Lmark !<CR>

" tag lines with "quick" tag
nmap <buffer> ,tq :Ltag quick<CR>
vmap <buffer> ,tq :Ltag quick<CR>

" find all lines tagged as "quick"
nmap <buffer> ,sq :Lsearch tag quick<CR>

" set an item as due today
nmap <buffer> ,dt :Ldue today

" find all items due this week
nmap <buffer> ,sw :Lsearch due 0:0 weeks

In this example, I've added a new mark for me to use: "!". I've also added it to the mark ranks so that sorting will put "!" items in their proper order. I created a shortcut ("\l") to open my projects.list file in a narrow sidebar in vim. I added some things to help me manage items that are quick tasks---a mapping to easily tag items as "quick" and another to search for them. I also added a way to set a due date of today and to find all items due this week.

If you'd like this simple tool in your belt, go get it.

Thursday, September 2, 2010

Vim, PHP, TagList, and Ctags

I spent a good bit of time figuring out how to get vim to play nice with the spectacular TagList plugin, Ctags and PHP, so I've decided to sum up everything I did to get it working perfectly for the next person who comes along.

Installing TagList itself is simple---just follow the instructions, standard to installing any vim plugin. However, getting Exuberant Ctags, which is TagList's workhorse, to work properly with PHP is another matter. Ctags doesn't understand PHP very well. It picks up on variables (which is sorta useless in PHP, anyway) but not functions whose definitions specify access ("public", "protected", etc.), interfaces or abstract classes. How useless!

Creating a useful Ctags file for PHP is not difficult, thanks to the info at these two resources. Just use these flags:

ctags -R --exclude=.svn --tag-relative=yes --PHP-kinds=+cf-v --regex-PHP='/abstract\s+class\s+([^ ]+)/\1/c/' --regex-PHP='/interface\s+([^ ]+)/\1/c/' --regex-PHP='/(public\s+|static\s+|abstract\s+|protected\s+|private\s+)function\s+\&?\s*([^ (]+)/\2/f/' lib/

Notice that I exclude variables via the --PHP-kinds option. This isn't C, tyvm.

What I didn't understand, at first, is that TagList calls Ctags every single time it's opened so that it generates an up-to-date temporary tags file. This makes perfect sense, but when Ctags is called by TagList, it doesn't have all of our required command-line options. Enter the Ctags config file. Put the following in your ~/.ctags file:

--regex-PHP=/abstract\s+class\s+([^ ]+)/\1/c/
--regex-PHP=/interface\s+([^ ]+)/\1/c/
--regex-PHP=/(public\s+|static\s+|abstract\s+|protected\s+|private\s+)function\s+\&?\s*([^ (]+)/\2/f/

And, amazingly, TagList becomes useful for PHP development. The last step is to tweak TagList to work in a way that's most convenient for you. Personally, I like these options:

" set the names of flags
let tlist_php_settings = 'php;c:class;f:function;d:constant'
" close all folds except for current file
let Tlist_File_Fold_Auto_Close = 1
" make tlist pane active when opened
let Tlist_GainFocus_On_ToggleOpen = 1
" width of window
let Tlist_WinWidth = 40
" close tlist when a selection is made
let Tlist_Close_On_Select = 1

TagList has a ton of options, so check them out. You may also be interested in my most up-to-date .ctags and .vimrc.

Friday, July 30, 2010

My Health As a Programmer

People often separate general health into categories--physical, emotional, mental, congenital, hexagonal, Portugal. Although some degree of health in one area or another is possible while ignoring the others, I firmly believe each category is dependent on the others.

Good programmers are proud of their capacity for resolving issues and breaking down problems into their salient parts. Quips about co-workers aside, mental and intellectual health are crucial, and I'll bring that up again later. But that's a very small part of a very large picture.


I had an undiagnosed medical condition for a couple years that affected my energy, motivation and self-image. I didn't have enough energy to keep a routine of physical exercise. On some days, I struggled to stay awake. Focus was hard to come by.

After a successful diagnosis, proper medication helped tremendously. I still felt, though, that my work performance was suffering. I began exercising.

A note about exercise: I hear people say "Oh, I'm not the exercising type." These are always people who have never had an exercise routine before. Anyone I've ever met who has had a routine and fell out of it (for whatever reason) has spoken fondly of the days when they had a routine and of how good they felt--not just physically, but about themselves. So don't give me that "not the exercising type" crap. Unless you have a doctor's note, get out there, even if you have to start small, like, walking-two-blocks small. You will not regret it.

Anyway, so I started exercising. And it was awful. I was exhausted. Panting, tired, and the next day, painfully sore. But after a couple weeks, I started to really look forward to my exercise. Then I started setting goals. Then I started running barefoot. Now I'm six seconds away from beating my best-ever mile time (I ran my best mile in eighth grade).

More importantly, I feel I'm more productive than ever at work. I've started exercising in the morning before I go into the office, which means I'm alert and ready long before I get there. My body is fully awake, my blood is pumping and my brain is active. I walk into the office with a plan, confident and proud of myself for sticking to my routine.


I also try to resolve issues at home. As a married man, I have to occasionally resolve conflicts, of course, with my wife. And bills have to be paid, the car has to be detailed and the trash has to be taken out. I like to keep up with these things, not letting them pile up, go unresolved, or otherwise weigh on my mind. This prevents me from being distracted during the day by stress.

A note about motivations: Of course, I don't do all of these things to be a better programmer. I do them to have a better life in general. I have noted, however, that they have a huge effect on my performance at work and as a programmer.


I've also started caring for my intellectual health. I've had an addiction to certain web sites that waste my time. Considering the GIGO principle, I shouldn't be reading them, anyway.

I've noted how I used to have far more original ideas years ago. In fact, I used to deliberately avoid reading certain things because I thought they'd spoil my creativity by filling my head with other people's ideas. At some point, I started questioning that theory and started reading obsessively. Now I'm finding that a balance between these is best. Say no to Hacker News. Say yes to Schneier on Security and The Old New Thing.


One of the most effective things I've done to be a healthy programmer is made an effort to be more humble:

  • Programming is hard.

  • Neither I nor anyone else is perfect.

  • There exists someone who is smarter than I am.

  • There exists a programmer who could do my project better.

  • I will never be done improving my craft.

I find that, when I remember these things, I am more open to advice, willing to accept constructive criticism, and curious to learn more, and I feel like I get along with my coworkers better. If I'm willing to listen to what others around me have to say, their knowledge is added to my knowledge. Imagine taking the knowledge from five, ten, fifty good programmers and sticking it in your own head. How can that be a bad thing?

I think a lot of this could be applied to any craft or profession. I, however, am only a programmer. I can say, from first-hand experience, that living and thinking this way has made me a better programmer.

Wednesday, May 26, 2010

What Facebook Needs: Respect, Not Settings

Unless you're like the Unibomber and live in a remote cabin, you're probably already bored of the security and privacy news surrounding Facebook.

Since Facebook has realized that they're precariously close to losing millions of users over the bad press, they've made some changes to the privacy settings in an attempt to simplify them and rebuild the trust that has been lost.

What It's Really About

But it's not about settings. I appreciated their efforts to make the settings more granular some time ago. As I see it, there are actually two major hurdles for Facebook, neither related to the current set of privacy settings but to their lack of respect for users and their data:

1) Obviously, settings should not be changed automatically for any reason, as Facebook has done with previous updates. Facebook should also show respect for its users' data by erring on the side of privacy. If an advertiser does not absolutely need a piece of data, it should not be shared, even if Facebook's privacy policy allows it.

2) In addition, there is currently no easy way to close an account. You can only "deactivate" it--meaning that all of your data is still in Facebook's servers, linked to other users' accounts and ready for your inevitable (ahem) return to their social network, at which time your account can be conveniently reactivated.

These are the ways that Facebook has betrayed the trust of its users. It's not about what settings can be configured. Facebook just needs to show some respect for the users and data that have made the social network successful.

Why Your Data Isn't Safe

Recently, Mark Zuckerburg had a phone call for the press where he explained Facebook's mistakes, its goals, and the changes that are being made. The way I see it, there are only two possibilities here:

1) Mark Zuckerberg is a liar. He doesn't want to really change the way Facebook does things because this will result in a loss of revenue. The revamped user settings are just a red herring.

2) Mark Zuckerberg is a bothersome, idealist figurehead to those who actually run Facebook and must appease him. He may not have made these business decisions for the sake of revenue, but those responsible for increasing revenue convinced him that these offending choices were best for other reasons, e.g., that openness is the way of the future and a way for Facebook to continue changing the world. This would also suggest that Zuckerburg's lofty goals and hubris will be his downfall, like so many ancient Greek protagonists.

Regardless of Zuckerburg's motives, your data is not safe with Facebook.

How to Demonstrate Respect

To turn this situation around, they need to demonstrate an unflagging respect for their users' personal data, even at the loss of revenue. This means not unnecessarily sharing data and not changing the way data is shared, even when settings are added or removed. This will take time. They will not be able to gain their users' trust as quickly as they lost it.

They also need to provide a way to completely close an account without any caveats or persistent data. This would be a huge overhaul; it would require removing photos, updates, comments on other users' walls and posts. It would also require removing other users' actions relating to the cancelling user's account. This is a huge loss of data, but it is the only way to thoroughly remove an account from the system.

Even if someone never cancels his account, he can take comfort in the fact that if, at any time, he is uncomfortable with Facebook's use of his data, it can be quickly and thoroughly wiped. This would not only decrease users' reluctance to share personal data on the site, it would also give the users an effective way to hold Facebook accountable for its decisions, as any bad decision could result in a permanent loss of valuable data.

Tuesday, January 19, 2010

Orlando Perl Workshop (OPW) / Perl Oasis

I had a really great time this weekend with all the guys at OPW! Although I'm obviously not a Perl guy, it was neat to see some of Perl's capabilities and some of the cool things this community is doing to improve web development. Some of these ideas could even be applied to PHP development. I'll have to give that more thought.

I was also graciously invited to speak about roles in PHP (since they were inspired by Perl's Moose::Roles module). I'll throw up another post with more details about the talk later.

There were some great speakers; I really enjoyed the talks and getting to meet fellow programmers. Stevan Little gave a great talk on everything, particularly wiring up a new app with URL routing and Bread::Board. The colorful Matt Trout told an epic poem about database management, and Marty Pauley give an interesting talk on functional programming in Perl, which actually refreshed a lot of the basics I'd forgotten from school. Shawn Moore revealed even more geek than I thought possible in his talk about conquering NetHack with an artificially intelligent bot.

Of course, there were more good things that happened there, but these are the highlights that came to mind. Many thanks to Chris Prather and his very organized and hard-working wife Jamie for their putting this shindig together. Well done! I look forward to next year. Also, I wanted to mention a particular Perl web server named Plack.