0

I'm using the :!grep "tag1" filename | grep "tag2" filename | grep -n "tag3 or more" filename command in vim to search for my code snippets based on their tags (a simple comment at the top of a snippet) in one big file, similar to firefox's tag functionality. I use snippets to remember tricky things.

This is painful to write out each time. I'd like to make an alias, or function to do something like this:

:!greptag tag1 tag2 ... tag39

And it should search the current doc and return the lines with all the tags on them.

Vim is set to interactive shell mode so that it can parse my bashrc for aliases/functions.

set shellcmdflag=-ic "lets vim use bashrc

How can I construct a function that allows for variable arguments like this in bash?

2 Answers 2

2

You could also use sed:

sed e '/tag1/!d;/tag2/!d;.../tagN/!d' filename

The /tag1/! command is an address prefix to tell sed to only execute the command if the line contains tag1. The command we execute is "d", to delete the line.

A function (in .bashrc) would then be:

greptags () {
    local filename="$1"
    shift
    sed "$filename" -e "$(echo "$@" | sed -e 's,\([^ ]*\) *,/\1/\!d;,g')"
}

Notice that we use another sed command to parse the arguments into the final sed command list. Basically, for every word (no spaces), we remove the spaces that follows it and put it into the /tagN/!d; command form.

And call it:

greptags filename tag1 tag2 tag3 tag4

Hope this helps =)

Sign up to request clarification or add additional context in comments.

4 Comments

The problem is that the original code looks for all tags, not any.
Calling this as $greptags tagname filename from terminal (int the directory with the sample .txt file) prints out sed: -e expression #1, char 20: invalid reference \1 on `s' command's RHS
Sorry... There were a couple of missing things. Fixed it =)
This is great! Thank you! I love sed.
2

How about something like this:

greptags() {
 if [[ -z "$1" ]] ; then
  cat
 else
  local t="$1" ; shift
  greptags "$@" | grep "$t"
 fi
}
greptag() {
 local f="$1" ; shift
 local t="$2" ; shift
 grep "$t" "$f" | greptags "$@"
}

(untested and, probably not exactly what you want, but illustrating the idea).

3 Comments

It didn't throw any errors, but it's also not working as far as I can tell. I tried with :!greptags "example_tag" filename and without the filename and no luck. It doesn't look like I'll be able to avoid learning bash ;p for my reference, which part of your functions allows for multiple args?
vim don't "see" the bash functions, put the code in a script.
Actually the other answer worked fine from vim (the bottom 3 lines in my question explains why) after I pasted it into my bashrc, unless I'm missing something and this is formatted specifically to be in a script file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.