sponsor Vim development Vim logo Vim Book Ad

intermediate Tip #482: Use VIM as an organizer of Memos, bookmarks, todo, etc.

 tip karma   Rating 59/19, Viewed by 5203 

Read and edit this tip on the Vim tip wiki. The wiki may have a more recent version of this tip.

created:   June 5, 2003 18:55      complexity:   intermediate
author:   hypertext organizer      as of Vim:   5.7

No one has perfect memory. I know this when I saw clever person often key in notes in his computer.
He uses a number of small files with ".txt" extension and "grep" through them. To me this is not good
because you still need to give a different name to different things and as time goes by, you will useup
common words and starts "name1", "name2", ... to enumerate.

Have you ever thought of having one single Memo at hand that can put things down as normal
editor, still very easy to search and navigate through? HTML would be perfect for hypertext
navigation, but it is not as perfect for writting notes. Who knows what <H3> means level 3 headings
when i just want to use to highlight my text, ... A lot inconvenience.

I use VIM! For many years it helps me remember almost everything and still enjoy it. Let me share
the experience with you. Of course I expect you be a VIMMER as me first.

VIM as an organizing tool? The help system of VIM is so well organized that we can think
of reusing the same for our everyday purpose. For example, here is my own Memo (abridged):
<<cut here>>
*memo.txt*      My Memo   - extending my poor memories                |guide|
-------------------------------------------------------------------------------------------------------------
*subjects*                                                                                     *toc*
|cmd|  command tips    |def|   definitions        
|dev|   developments     |ed|    editors              |friends|  friends
|lang|  languages          |misc|    others
|private|  personal info   |sys|   system  
-------------------------------------------------------------------------------------------------------------
Commands                                                               *cmd*
*General
        http://www.cslab.vt.edu/manuals
         ......
|doskey|    DOS key utility
        <F8>: expand history
|man|        Unix manual
                man foo
                nroff -man foo.1 | less
                nroff -man foo.1 | a2ps -m
|unix|
    http://gd.tuwien.ac.at/linuxcommand.org/
|winhelp|
.....
-------------------------------------------------------------------------------------------------------------
Development                                                        *develop*            *dev*
...
-------------------------------------------------------------------------------------------------------------
vim:tw=78:fo=tcq2:isk=!-~,^*,^\|,^\":ts=8:ft=help:norl:
<<cut here>>
Some explainations:
1) The last line instructs VIM with a number of editing settings. The most
important one here is "ft=help", which says file-type is "help"! So the VIM
will highlight thing for us.
2) You can use *foo* to indicate an anchor to the "help" system of VIM.
If you press Ctrl + ] on a word "foo", the cursor will jump to the first *foo*.
You can also see |foo| as a way to highlight it as implicit keywords.
3) This is not magic. The mechanism behind is the tag system. VIM needs
to have the following tag file to go to where you want it to go:
===================================
%userprofile%   memo.txt   /*%userprofile%*
.htaccess   meo.txt   /*.htaccess*
access  memo.txt   /*access*
access.conf memo.txt   /*access.conf*
addressbook memo.txt   /*addressbook*
anchor_keyword  memo.txt   /*anchor_keyword*
apache  memo.txt   /*apache*
as  index.txt   /*as*
at  index.txt   /*at*
awk index.txt   /*awk*
===================================
Each line defines a tag, the first element is the keyword,
the second is the file where the tag belongs (yes, you can use
multiple files as long as you know what they are), and the last
element is the command which as VIM to perform at the keyword (you
can as well do something wield here, but that's your own business).
4) But that's tedious! How to write these tags? God save you and thanks
VIM, you can find this utility to do it:
    cc doctags.c -o doctags
    doctags memo.txt | sort -f | awk -f cases.awk >tags
    uniq -d -2 tags
------------------------------------------------------------------------------
<<cut here>> doctags.c

/* vim:set ts=4 sw=4:
* this program makes a tags file for vim_ref.txt
*
* Usage: doctags vim_ref.txt vim_win.txt ... >tags
*
* A tag in this context is an identifier between stars, e.g. *c_files*
*/

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

#define LINELEN 200

int
main(argc, argv)
int argc;
char **argv;
{
char line[LINELEN];
char *p1, *p2;
char *p;
FILE *fd;

if (argc <= 1)
{
fprintf(stderr, "Usage: doctags docfile ... >tags\n");
exit(1);
}
printf("help-tags\ttags\t1\n");
while (--argc > 0)
{
++argv;
fd = fopen(argv[0], "r");
if (fd == NULL)
{
fprintf(stderr, "Unable to open %s for reading\n", argv[0]);
continue;
}
while (fgets(line, LINELEN, fd) != NULL)
{
p1 = strchr(line, '*'); /* find first '*' */
while (p1 != NULL)
{
p2 = strchr(p1 + 1, '*'); /* find second '*' */
if (p2 != NULL && p2 > p1 + 1) /* skip "*" and "**" */
{
for (p = p1 + 1; p < p2; ++p)
if (*p == ' ' || *p == '\t' || *p == '|')
break;
/*
* Only accept a *tag* when it consists of valid
* characters and is followed by a white character or
* end-of-line.
*/
if (p == p2 && (p1 == line || p1[-1] != '-') &&
(strchr(" \t\n\r", p[1]) != NULL || p[1] == '\0'))
{
*p2 = '\0';
++p1;
printf("%s\t%s\t/*", p1, argv[0]);
while (*p1)
{
/* insert backslash before '\' and '/' */
if (*p1 == '\' || *p1 == '/')
putchar('\');
putchar(*p1);
++p1;
}
printf("*\n");
p2 = strchr(p2 + 1, '*'); /* find next '*' */
}
}
p1 = p2;
}
}
fclose(fd);
}
return 0;
}
<<cut here>> cases.awk
{
print tolower($1) "\t" $2 "\t" tolower($3);
}
<<cut here>>

That's it. Good luck VIMMER.

 rate this tip  Life Changing Helpful Unfulfilling 

<< abbreviations only on shortcut | Using GREP for a ‘list occurrences’ and quickfix help command. >>

Additional Notes

maurice, June 6, 2003 4:10
See also :helptags
digitect (at) mindspring • com, June 6, 2003 14:04
Make your own tags file within Vim with:

    :execute "helptags " . expand("%:p:h")

from within the open file.
[email protected] (Rot13ed), June 7, 2003 9:29
There is one downside with :helptags. It opertes only on *.txt files.

Here is another method for generating a tags file for *word* style tags; written in python and based off the ptags.py from the python22 distribution

Usage:
tags.py [file] [file,etc.]
i.e.
tags.py myfile.html myfile.c etc.etc

tags.py:
>>>
#! /usr/bin/env python
#{{{ File header information
"""
/*!
\file        tags.py
\brief        Create a tags file (of *WORDS*), usable with VIM61, possibly earlier.
\note        based on ptags.py from the python22 distribution
            modifed by Feral to find only *word* style tags (for my documtation) output tailored for VIM6.1
\author        Original author unknown, based on ptags.py from the python22 distribution.
            This file modified and maintained by Feral <[email protected]> (Rot13ed)
\version    1.02
\note        $Id$

Changelog:
            1.01: [Feral:240/02@08:36] now warns on a duplicate entry, slow and crude method (checks each addition to tags)
            1.00: [yesterday]
                Initial version, based on ptags.py from the python22 distrobution.
*/
"""
#}}}


import sys, re, os

tags = []     # Modified global variable!

def main():
    args = sys.argv[1:]
    print args
    for file in args:
        treat_file(file)

    # keep in mind that the tags are sorted, this line !should! end up at the top...
    tags.append("!_TAG_FILE_SORTED\t1\n")
#    print tags

    if tags:
        fp = open('tags', 'w')
        tags.sort()
        for s in tags:
            fp.write(s)
#            print s

expr = '.*\*([a-zA-Z0-9_]+)\*.*'
matcher = re.compile(expr)

def treat_file(file):
    print "treating file", file
    dacount = 0
    try:
        fp = open(file, 'r')
    except:
        sys.stderr.write('Cannot open %s\n' % file)
        return
    base = os.path.basename(file)
    while 1:
        line = fp.readline()
#        print "line:",line
        if not line:
            break
        m = matcher.match(line)
        if m:
            content = m.group(1)
            s = content + '\t' + base + '\t/*' + content + '*\n'
# SO: [Feral:240/02@08:32] Hack in a warning if the item exists already.
# Original:
#            tags.append(s)
# THe hack:
            for item in tags:
                if item == s:
                    print "Duplicate entry:", content
            tags.append(s)
# EO: Feral [Feral:240/02@08:32]

#            print "content: ",content
#            print s
            dacount = dacount + 1
    print "\t", dacount, "matches."


if __name__ == '__main__':
    main()

#EOF
<<<
Now hopefully this forum didn't mangle the indent! heh
Anonymous, June 8, 2003 16:39
Also see Thlnk.vim
https://www.vim8.org/scripts/script.php?script_id=293
gpwen, June 11, 2003 18:40
It will be better if combined with the folding. I put this on the modeline:
    vim:fdm=marker:tw=78:isk=!-~,^*,^\|,^\":ts=8:ft=help:norl:

And add folding marks at the end of the section title, like this:
    ==================================================
    Commands                                      {{{1
    ==================================================

"{{{1" is the default folding mark for level one. You can use multiple level
folders as well (:he Folding). Vim will folder the items automatically so you
can get all items at one glance. Really nice feature!
[email protected], July 29, 2003 12:54
Thank you for helping me to simplify the task! I have modified my Memo with the following template:
---------------------------------------
TITLE           *tag*  {{{
  ...content...
}}}
In summary, using "helptags ." can also warn me about any redundant tags.

Another idea, maybe useful, is it possible to use two connected words as the tags automatically? Like
WikiWiki, PikiPiki and MoinMoin (don't need to enter | | and * *, just use a pattern like [A-Z][a-z0-9]*[A-Z][a-z0-9]*.

Furthermore, is it possible to allow Unicode keywords to be automatically found?
davev at ziplip dot com, November 22, 2003 19:25
I just intregrated much of these functions (links, folding, etc.) into one script on Vimscript#828.
If you have questions or remarks about this site, visit the vimonline development pages. Please use this site responsibly.
Questions about Vim should go to the maillist. Help Bram help Uganda.
   
Sponsored by Web Concept Group Inc. SourceForge.net Logo