Sunday, January 28, 2007

Javascript tags generator: A MUST have for serious Ajax developers using vim

The following python script could build tags file for your javascript files. It's still version 0.0.1, but it does support extracting most methods and class definitions. Here are a list of the syntax it supports for now. If you find this script misses something, please let me know and I'll add them for you.

Supported Syntax

# - functions
# * function info(msg) {
# * info: function(msg) {
# - classes
# * var logger = {

Usage
#   jstags.py logger.js
# ls *.js | jstags.py
# find ./ -name *.js | jstags.py

Source code

#! /usr/bin/env python
#
# jstags.py
#
# Create a tags file for javascript programs, usable with vi.
#
# Benefit:
# Just in case you haven't used tags in vim, you could jump
# to class/function definition using and jump back
# using . Once you start using tags, you can no longer
# live with it.

import sys, re, os
tags = [] # Modified global variable!

def main():
if sys.stdin: files = [s.strip() for s in sys.stdin.readlines()]
else: files = sys.argv[1:]
for filename in files: parse_file(filename)

fp = open('tags', 'w')
fp.write("!_TAG_FILE_FORMAT\t2\n")
fp.write("!_TAG_FILE_SORTED\t1\n")
fp.write("!_TAG_PROGRAM_AUTHOR\tAlex Dong\n")
fp.write("!_TAG_PROGRAM_VERSION\t0.0.1\n")
fp.write("!_TAG_PROGRAM_URL\thttp://thetruedelight.blogspot.com/2007/01/javascript-tags-generator-must-have-for.html\n")


tags.sort()
for s in tags: fp.write(s)

patterns = { re.compile('\s*var\s*(\w+)\s*=\s*{'):'c',
re.compile('\s*function\s*(\w+)\s*\('):'f',
re.compile('\s*(\w+)\s*\:\s*function\s*\('):'f'
}

def parse_file(filename):
fp = open(filename, 'r')
while 1:
line = fp.readline()
if not line: break

for pattern in patterns.keys():
m = pattern.match(line)
if m:
c = m.group(0)
n = m.group(1)
s = "%s\t%s\t/^%s/;\"\t%s\n" % (n, filename, c, patterns[pattern])
tags.append(s)

fp.close()

if __name__ == '__main__':
main()

1 comment:

cygnl7 said...

Very nice. Thank you!

I took out the reading from stdin since the way it is now will only work to read from stdin (because sys.stdin will always be true when running from the command line).

I also added one more pattern to watch:

re.compile('\s*\w*\.*(\w+)\s*\=\s*function\s*\('):'f'

So it's:

patterns = { re.compile('\s*var\s*(\w+)\s*=\s*{'):'c',
re.compile('\s*function\s*(\w+)\s*\('):'f',
re.compile('\s*(\w+)\s*\:\s*function\s*\('):'f',
re.compile('\s*\w*\.*(\w+)\s*\=\s*function\s*\('):'f'
}

This will catch things like:

Namespace.myfunc = function()...

or

Object.prototype.myfunc = function()...

etc.