24 November 2008

alias or function? and bash 'time'

In a previous post (and a follow-up), I wrote about a number of useful and time-saving aliases that I use in the bash shell. Those posts are pretty old now. In the meantime, I've defined another interesting alias. While nothing special in itself, I've discovered that this is one task that can be done better in another way.

The new alias is this:
pig='pkg_info | grep '

I've found it to be very useful. I often want to know what version of some port is installed, or if I have a port installed at all, and this allows me to find out quickly without paging through the whole list. For example:
mybox$ pig swfdec
swfdec-0.6.8 Flash Rendering Library
swfdec-plugin-0.6.0_1 Flash rendering plugin

It's very much like the alias "psg='ps auxw | grep '" that I'd talked about previously.

But, on a box with a large amount of software installed -- which is pretty well any FreeBSD desktop now that we have modular X -- this new command is pretty slow. Let's use bash's time utility and see just how slow:
mybox$ time pig swfdec
swfdec-0.6.8 Flash Rendering Library
swfdec-plugin-0.6.0_1 Flash rendering plugin

real 0m13.245s
user 0m0.306s
sys 0m0.233s

Thirteen seconds, wow! Immediate, subsequent re-invocations should go much faster since the file information has been cached. See:
mybox$ time pig swfdec
swfdec-0.6.8 Flash Rendering Library
swfdec-plugin-0.6.0_1 Flash rendering plugin

real 0m0.416s
user 0m0.258s
sys 0m0.163s

But, the underlying problem remains: pkg_info spends a lot of processing time going through all the installed ports, and we're only interested in one (or a few). We can do better.

Knowing that the package information is found in the directory '/var/db/pkg/' and how it's structured, we can use filename expansion and a couple of other tricks to dramatically reduce these times. After some fiddling, this is what I've come up with:
pi2 ()
{
RND=$RANDOM;
cd /var/db/pkg/;
cat *${1}*/+COMMENT > /tmp/pig.$RND;
echo *${1}* | sed 's/ /\
/g' | paste - /tmp/pig.$RND;
rm /tmp/pig.$RND;
cd $OLDPWD
}

I call it 'pi2' here for the sake of clarity. Yes, that's a literal newline for the sed replacement string (might cause problems with some versions of sed :/ ).

This function dramatically reduces times. Compare these times with those above:
mybox$ time pi2 swfdec
swfdec-0.6.8 Flash Rendering Library
swfdec-plugin-0.6.0_1 Flash rendering plugin

real 0m0.015s
user 0m0.001s
sys 0m0.023s

And, these fast times stay nearly the same when the file information is not cached. Which takes away that pesky 10 plus second wait when you want to use this utility and the file information doesn't happen to be cached already.

Labels: ,

10 November 2008

"Error detected while processing ../php.vim"

Here's a minor irritation with the vim port (editors/vim-lite, and probably the others). When I go to edit a php file I get this non-fatal error:

"~/somefile.php" 99 lines, 2345 characters
Error detected while processing /usr/local/share/vim/vim72/syntax/php.vim:
line 479:
E10: \ should be followed by /, ? or &
line 482:
E10: \ should be followed by /, ? or &
line 488:
E10: \ should be followed by /, ? or &
line 489:
E10: \ should be followed by /, ? or &
line 490:
E10: \ should be followed by /, ? or &
[etc.,etc.]
Press ENTER or type command to continue

This is with vim-lite-7.2.14, but it was happening on vim-lite-7.1.x too. The fix is pretty easy, we just have to edit the php.vim file and remove the syntax errors. All of the errors reported are the same and look like they were intended to be line continuations for neatness (that vim just does not like). I saved a copy of the original before I did this and here a snippet of the diff:

478,479c478
< syntax keyword phpSpecialFunction containedin=ALLBUT,phpComment,phpStringDouble,phpStringSingle,phpIdentifier
< \ __construct __destruct __call __toString __sleep __wakeup __set __get __unset __isset __clone __set_state
---
> syntax keyword phpSpecialFunction containedin=ALLBUT,phpComment,phpStringDouble,phpStringSingle,phpIdentifier __construct __destruct __call __toString __sleep __wakeup __set __get __unset __isset __clone __set_state


That's probably going to be hard to read. But, the issue is that all the lines beginning with " \ " need to be joined to the line before them and the "\" should be removed. That's it. In the case where there are several of these lines in a row, they should all be joined to the line preceding them, and all of the backslashes removed. (Into one really long line, yes.)

I guess I'll be a good user and submit a patch. :P

UPDATE
See this update, with new information (including a better solution).

Labels: