Browse Source

salamander

windhamdavid 10 years ago
parent
commit
340134ec67

+ 830 - 0
salamander.remote/commands.txt

@@ -0,0 +1,830 @@
+Display all 1658 possibilities? (y or n)
+!                                   make
+./                                  make-ssl-cert
+2to3                                makestrs
+2to3-2.6                            man
+:                                   mandb
+GET                                 manpath
+HEAD                                mapfile
+MAKEDEV                             match
+Magick-config                       mattrib
+MagickCore-config                   mbadblocks
+MagickWand-config                   mcat
+POST                                mcd
+Wand-config                         mcheck
+[                                   mclasserase
+[[                                  mcomp
+]]                                  mcookie
+__rvm_after_cd                      mcopy
+__rvm_ask_to_trust                  md5sum
+__rvm_become                        md5sum.textutils
+__rvm_bin_script                    mdel
+__rvm_bin_scripts                   mdeltree
+__rvm_check_rvmrc_trustworthiness   mdir
+__rvm_clean_path                    mdu
+__rvm_cleanse_variables             memtester
+__rvm_cleanup_tmp                   meryl
+__rvm_conditionally_add_bin_path    meryl@1.0.1
+__rvm_current_gemcache_dir          mesg
+__rvm_current_gemset                mformat
+__rvm_db                            mii-tool
+__rvm_default_flags                 minfo
+__rvm_dump_environment              mk_modmap
+__rvm_ensure_has_environment_files  mkdir
+__rvm_environment_identifier        mkdiskimage
+__rvm_expand_ruby_string            mke2fs
+__rvm_export                        mkfifo
+__rvm_gemset_clear                  mkfontdir
+__rvm_gemset_select                 mkfontscale
+__rvm_gemset_use                    mkfs
+__rvm_initialize                    mkfs.bfs
+__rvm_inspect                       mkfs.cramfs
+__rvm_load_environment              mkfs.ext2
+__rvm_load_rvmrc                    mkfs.ext3
+__rvm_md5_for                       mkfs.ext4
+__rvm_meta                          mkfs.ext4dev
+__rvm_nuke_rvm_variables            mkfs.minix
+__rvm_parse_args                    mkhomedir_helper
+__rvm_project_rvmrc                 mkinitramfs
+__rvm_quote_args                    mkinitramfs-kpkg
+__rvm_quote_args_with_shift         mklost+found
+__rvm_reboot                        mkmanifest
+__rvm_record_install                mknod
+__rvm_recorded_install_command      mkswap
+__rvm_remove_install_record         mktemp
+__rvm_remove_rvm_from_path          mlabel
+__rvm_reset_rvmrc_trust             mlocate
+__rvm_rm_rf                         mlock
+__rvm_ruby_string                   mmd
+__rvm_ruby_string_paths_under       mmount
+__rvm_run                           mmove
+__rvm_run_script                    modinfo
+__rvm_run_with_env                  modprobe
+__rvm_rvmrc_key                     mogrify
+__rvm_rvmrc_stored_trust            montage
+__rvm_rvmrc_tools                   more
+__rvm_select                        mount
+__rvm_set_rvmrc                     mountall
+__rvm_setup                         mountpoint
+__rvm_source_dir                    mpartition
+__rvm_strings                       mrd
+__rvm_strip                         mren
+__rvm_teardown                      msgattrib
+__rvm_trust_rvmrc                   msgcat
+__rvm_unset_exports                 msgcmp
+__rvm_unset_ruby_variables          msgcomm
+__rvm_untrust_rvmrc                 msgconv
+__rvm_usage                         msgen
+__rvm_use                           msgexec
+__rvm_use_system                    msgfilter
+__rvm_using_gemset_globalcache      msgfmt
+__rvm_version                       msggrep
+__rvm_warn_on_rubyopt               msginit
+a2dismod                            msgmerge
+a2dissite                           msgunfmt
+a2enmod                             msguniq
+a2ensite                            mshowfat
+a2p                                 msql2mysql
+ab                                  mt
+accessdb                            mt-gnu
+aclocal                             mtools
+aclocal-1.11                        mtoolstest
+acyclic                             mtrace
+add-shell                           mtype
+addgroup                            mv
+addpart                             mxtar
+addr2line                           my_print_defaults
+adduser                             myisam_ftdump
+alias                               myisamchk
+amuFormat.sh                        myisamlog
+animate                             myisampack
+apache2                             mysql
+apache2ctl                          mysql_client_test
+appres                              mysql_client_test_embedded
+apr-1-config                        mysql_config
+apr-config                          mysql_convert_table_format
+apropos                             mysql_find_rows
+apt-cache                           mysql_fix_extensions
+apt-cdrom                           mysql_fix_privilege_tables
+apt-config                          mysql_install_db
+apt-extracttemplates                mysql_secure_installation
+apt-ftparchive                      mysql_setpermission
+apt-get                             mysql_tzinfo_to_sql
+apt-key                             mysql_upgrade
+apt-mark                            mysql_waitpid
+apt-sortpkgs                        mysql_zap
+aptitude                            mysqlaccess
+aptitude-create-state-bundle        mysqladmin
+aptitude-run-state-bundle           mysqlanalyze
+apu-1-config                        mysqlbinlog
+apu-config                          mysqlbug
+apxs2                               mysqlcheck
+ar                                  mysqld
+arch                                mysqld_multi
+arp                                 mysqld_safe
+arpd                                mysqldump
+arping                              mysqldumpslow
+as                                  mysqlhotcopy
+autoconf                            mysqlimport
+autoheader                          mysqlmanager
+autom4te                            mysqloptimize
+automake                            mysqlrepair
+automake-1.11                       mysqlreport
+autopoint                           mysqlshow
+autoreconf                          mysqlslap
+autoscan                            mysqltest
+autoupdate                          mysqltest_embedded
+awk                                 mzip
+badblocks                           namei
+base64                              nameif
+basename                            nano
+bash                                nawk
+bashbug                             ncal
+bcomps                              ncurses5-config
+bdftopcf                            ncursesw5-config
+bdftops                             neato
+bdftruncate                         neqn
+berkeley_db4.7_svc                  netkit-ftp
+bg                                  netstat
+bind                                newaliases
+blkid                               newgrp
+blockdev                            newusers
+bootlogd                            ngettext
+break                               nginx
+bsd-write                           nice
+builtin                             nisdomainname
+bundle                              nl
+bunzip2                             nm
+bzcat                               node
+bzcmp                               node-waf
+bzdiff                              nohup
+bzegrep                             nologin
+bzexe                               nop
+bzfgrep                             npm
+bzgrep                              npm-get-uid-gid
+bzip2                               npm-get-uid-gid@0.3.18
+bzip2recover                        npm@0.3.18
+bzless                              nroff
+bzmore                              nslookup
+c++                                 nstat
+c++filt                             nsupdate
+c2ph                                ntp-keygen
+c89                                 ntp-wait
+c89-gcc                             ntpd
+c99                                 ntpdate
+c99-gcc                             ntpdate-debian
+c_rehash                            ntpdc
+cake                                ntpq
+cake@1.0.1                          ntpsweep
+cal                                 ntptime
+calendar                            ntptrace
+caller                              objcopy
+captoinfo                           objdump
+case                                ocamlrun
+cat                                 od
+catchsegv                           odbcinst
+catman                              oil-bugreport
+cautious-launcher                   oldfind
+cc                                  omshell
+ccomps                              open
+cd                                  openssl
+cdbs-edit-patch                     openssl-vulnkey
+cfdisk                              openvt
+chage                               pager
+charset                             pam-auth-update
+chattr                              pam_getenv
+chcon                               pam_tally
+check-foreground-console            partx
+check_forensic                      passenger
+checkgid                            passenger-config
+chfn                                passenger-install-apache2-module
+chgpasswd                           passenger-install-nginx-module
+chgrp                               passenger-make-enterprisey
+chkdupexe                           passenger-memory-stats
+chmod                               passenger-status
+chown                               passenger-stress-test
+chpasswd                            passwd
+chroot                              paste
+chrt                                patch
+chsh                                pathchk
+chvt                                pcre-config
+circo                               pcretest
+cksum                               pd
+clear                               pd-gem
+clear_console                       pdb
+cmp                                 pdb2.6
+codepage                            pdf2dsc
+coffee                              pdf2ps
+coffee@1.0.1                        pdfopt
+coffeekup                           pdreceive
+coffeekup@0.2.2                     pdsend
+col                                 pear
+colcrt                              peardev
+colrm                               pecl
+column                              peekfd
+comm                                perl
+command                             perl5.10.1
+compare                             perlbug
+compgen                             perldoc
+compile_et                          perlivp
+complete                            perlthanks
+compopt                             perror
+compose                             pf2afm
+composite                           pfbtopfa
+compress-dummy                      pftp
+config_data                         pg
+conjure                             pg_config
+consolechars                        pgawk
+continue                            pgrep
+convert                             php
+convertquota                        php-config
+coproc                              php-config5
+corelist                            php5
+cp                                  phpize
+cpan                                phpize5
+cpan2dist                           pic
+cpanp                               pico
+cpanp-run-perl                      piconv
+cpgr                                pidof
+cpio                                ping
+cpp                                 ping6
+cpp-4.4                             pinky
+cppw                                pivot_root
+cracklib-check                      pkg-config
+cracklib-format                     pkill
+cracklib-packer                     pl2pm
+cracklib-unpacker                   plipconfig
+create-cracklib-dict                plymouth
+cron                                plymouthd
+crontab                             pma-configure
+csh                                 pma-secure
+csplit                              pmap
+csslint-0.6                         pmap_dump
+ctags                               pmap_set
+ctags-exuberant                     po2debconf
+ctrlaltdel                          pod2html
+ctstat                              pod2latex
+curl                                pod2man
+curl-config                         pod2text
+cut                                 pod2usage
+cytune                              podchecker
+dash                                podebconf-display-po
+date                                podebconf-report-po
+db4.7_archive                       podselect
+db4.7_checkpoint                    popclient
+db4.7_codegen                       popd
+db4.7_deadlock                      portmap
+db4.7_dump                          postalias
+db4.7_hotbackup                     postcat
+db4.7_load                          postconf
+db4.7_printlog                      postdrop
+db4.7_recover                       postfix
+db4.7_stat                          postfix-add-filter
+db4.7_upgrade                       postfix-add-policy
+db4.7_verify                        postkick
+db4.8_archive                       postlock
+db4.8_checkpoint                    postlog
+db4.8_deadlock                      postmap
+db4.8_dump                          postmulti
+db4.8_hotbackup                     postqueue
+db4.8_load                          postsuper
+db4.8_printlog                      poweroff
+db4.8_recover                       ppmtolss16
+db4.8_sql                           pr
+db4.8_stat                          preconv
+db4.8_upgrade                       prename
+db4.8_verify                        print
+db_dump185                          printafm
+dbconfig-generate-include           printenv
+dbconfig-load-include               printerbanner
+dbilogstrip                         printf
+dbiprof                             procinfo
+dbiproxy                            prove
+dbmmanage                           prtstat
+dd                                  prune
+ddate                               ps
+deallocvt                           ps2ascii
+debconf                             ps2epsi
+debconf-apt-progress                ps2pdf
+debconf-communicate                 ps2pdf12
+debconf-copydb                      ps2pdf13
+debconf-escape                      ps2pdf14
+debconf-get-selections              ps2pdfwr
+debconf-getlang                     ps2ps
+debconf-gettextize                  ps2ps2
+debconf-loadtemplate                ps2txt
+debconf-mergetemplate               psbook
+debconf-set-selections              psed
+debconf-show                        psfaddtable
+debconf-updatepo                    psfgettable
+debugfs                             psfstriptable
+declare                             psmerge
+defoma                              psnup
+defoma-app                          psresize
+defoma-font                         psselect
+defoma-hints                        pstops
+defoma-id                           pstree
+defoma-psfont-installer             pstree.x11
+defoma-reconfigure                  pstruct
+defoma-subst                        ptar
+defoma-user                         ptardiff
+delgroup                            ptx
+delpart                             puredata
+deluser                             pushd
+depmod                              pwck
+df                                  pwconv
+dh                                  pwd
+dh-make-pear                        pwdx
+dh-make-pecl                        pwgen
+dh_auto_build                       pwunconv
+dh_auto_clean                       py3_compilefiles
+dh_auto_configure                   py_compilefiles
+dh_auto_install                     pycentral
+dh_auto_test                        pyclean
+dh_bugfiles                         pycompile
+dh_builddeb                         pydoc
+dh_clean                            pydoc2.6
+dh_compress                         pygettext
+dh_desktop                          pygettext2.6
+dh_fixperms                         python
+dh_gconf                            python2
+dh_gencontrol                       python2.6
+dh_icons                            pyversions
+dh_install                          qmqp-sink
+dh_installcatalogs                  qmqp-source
+dh_installchangelogs                qshape
+dh_installcron                      quot
+dh_installdeb                       quota
+dh_installdebconf                   quota_nld
+dh_installdefoma                    quotacheck
+dh_installdirs                      quotaoff
+dh_installdocs                      quotaon
+dh_installemacsen                   quotastats
+dh_installexamples                  rackup
+dh_installifupdown                  rackup1.8
+dh_installinfo                      rails
+dh_installinit                      rake
+dh_installlogcheck                  rake-ruby-1.9.2-p180
+dh_installlogrotate                 rake-ruby-1.9.2-p180@global
+dh_installman                       rake2thor
+dh_installmanpages                  ramsize
+dh_installmenu                      ranlib
+dh_installmime                      rarp
+dh_installmodules                   raw
+dh_installpam                       rbash
+dh_installppp                       rcp
+dh_installudev                      rdev
+dh_installwm                        rdoc
+dh_installxfonts                    rdoc-ruby-1.9.2-p180
+dh_link                             rdoc-ruby-1.9.2-p180@global
+dh_lintian                          rdoc1.8
+dh_listpackages                     read
+dh_makeshlibs                       read-package-json
+dh_md5sums                          read-package-json@0.3.18
+dh_movefiles                        readarray
+dh_perl                             readelf
+dh_prep                             readlink
+dh_pycentral                        readonly
+dh_python                           readprofile
+dh_scrollkeeper                     reboot
+dh_shlibdeps                        recode-sr-latin
+dh_strip                            red
+dh_suidregister                     redcarpet
+dh_testdir                          reload
+dh_testroot                         remove-shell
+dh_testversion                      remsync
+dh_undocumented                     rename
+dh_usrlocal                         rename.ul
+dhclient                            renice
+dhclient-script                     replace
+dhclient3                           repquota
+dhcp6c                              reset
+dhcp6ctl                            resize
+diff                                resize2fs
+diff3                               resolve_stack_dump
+diffimg                             resolveip
+dig                                 restart
+dijkstra                            return
+dir                                 rev
+dircolors                           rgrep
+dirname                             ri
+dirs                                ri-ruby-1.9.2-p180
+disown                              ri-ruby-1.9.2-p180@global
+display                             ri1.8
+dmesg                               rlogin
+dmsetup                             rm
+dnsdomainname                       rmail
+do                                  rmdir
+domainname                          rmmod
+done                                rmt
+dot                                 rmt-tar
+dot2gxl                             rnano
+dotlockfile                         rootflags
+dotty                               rotatelogs
+dovecot                             route
+dovecotpw                           routef
+dpkg                                routel
+dpkg-architecture                   rpc.rquotad
+dpkg-buildpackage                   rpcgen
+dpkg-checkbuilddeps                 rpcinfo
+dpkg-deb                            rsh
+dpkg-distaddfile                    rsync
+dpkg-divert                         rtacct
+dpkg-genchanges                     rtail
+dpkg-gencontrol                     rtcwake
+dpkg-gensymbols                     rtmon
+dpkg-name                           rtstat
+dpkg-parsechangelog                 ruby
+dpkg-preconfigure                   ruby-1.9.2-p180
+dpkg-query                          ruby-1.9.2-p180@global
+dpkg-reconfigure                    ruby1.8
+dpkg-scanpackages                   run-mailcap
+dpkg-scansources                    run-parts
+dpkg-shlibdeps                      runcon
+dpkg-source                         runlevel
+dpkg-split                          rview
+dpkg-statoverride                   rvim
+dpkg-trigger                        rvm
+dpkg-vendor                         rvm-auto-ruby
+dprofpp                             rvm-exec
+drush                               rvm-prompt
+drush.php                           rvm-restart
+dselect                             rvm-shell
+du                                  rvm_debug
+dumpe2fs                            rvm_error
+dumphint                            rvm_log
+dumpkeys                            rvm_warn
+dvipdf                              rvmsudo
+e2freefrag                          rzsh
+e2fsck                              s2p
+e2image                             safe_finger
+e2label                             sasl-sample-client
+e2undo                              sasl-sample-server
+echo                                saslauthd
+ed                                  sasldbconverter2
+edit                                sasldblistusers2
+editor                              saslfinger
+editres                             saslpasswd2
+edquota                             saslpluginviewer
+egrep                               sass
+elif                                sass-convert
+else                                savelog
+enable                              sccmap
+enc2xs                              scp
+enum                                screen
+env                                 screendump
+envsubst                            script
+eps2eps                             scriptreplay
+epsffit                             sdiff
+eqn                                 sed
+erb                                 see
+erb-ruby-1.9.2-p180                 select
+erb-ruby-1.9.2-p180@global          select-editor
+erb1.8                              sendmail
+erubis                              sensible-browser
+esac                                sensible-editor
+etags                               sensible-pager
+eval                                seq
+ex                                  service
+exec                                set
+exit                                setarch
+expand                              setkeycodes
+expiry                              setleds
+export                              setlogcons
+expr                                setmetamode
+extlinux                            setquota
+extractres                          setsid
+factor                              setterm
+faillog                             setvesablank
+faked-sysv                          sfdisk
+faked-tcp                           sftp
+fakeroot                            sg
+fakeroot-sysv                       sh
+fakeroot-tcp                        sh.distrib
+fallocate                           sha1sum
+false                               sha224sum
+fc                                  sha256sum
+fc-cache                            sha384sum
+fc-cat                              sha512sum
+fc-list                             shadowconfig
+fc-match                            shar
+fc-query                            shasum
+fc-scan                             shift
+fdformat                            shopt
+fdisk                               showcfont
+fdp                                 showchar
+fdupes                              showkey
+fetchmail                           shred
+fg                                  shtool
+fgconsole                           shtoolize
+fgrep                               shuf
+fi                                  shutdown
+file                                sieve-test
+filefrag                            sievec
+find                                sieved
+find2perl                           size
+findfs                              skill
+finger                              slabtop
+fix_bs_and_del                      slattach
+fixdlsrps                           sleep
+fixfmps                             slogin
+fixmacps                            smtp-sink
+fixpsditps                          smtp-source
+fixpspps                            snice
+fixscribeps                         socklist
+fixtpps                             soelim
+fixwfwps                            sort
+fixwpps                             source
+fixwwps                             splain
+flock                               split
+fmt                                 split-logfile
+fold                                splitfont
+font2c                              sprof
+font2psf                            sqlite3
+fonttosfnt                          sqlite3_ruby
+for                                 ss
+forever                             ssh
+forever@0.4.2                       ssh-add
+free                                ssh-agent
+freetype-config                     ssh-argv0
+from                                ssh-copy-id
+fromdos                             ssh-keygen
+fsck                                ssh-keyscan
+fsck.cramfs                         ssh-vulnkey
+fsck.ext2                           sshd
+fsck.ext3                           start
+fsck.ext4                           start-stop-daemon
+fsck.ext4dev                        startpar
+fsck.minix                          stat
+fsck.nfs                            status
+fstab-decode                        stop
+ftp                                 strace
+function                            stream
+funzip                              strings
+fuser                               strip
+g++                                 stty
+g++-4.4                             su
+gawk                                sudo
+gc                                  sudoedit
+gcc                                 sulogin
+gcc-4.4                             sum
+gcov                                suspend
+gcov-4.4                            svn
+gdk-pixbuf-query-loaders            svn-populate-node-origins-index
+gem                                 svnadmin
+gem-ruby-1.9.2-p180                 svnauthz-validate
+gem-ruby-1.9.2-p180@global          svndumpfilter
+gem1.8                              svnlook
+gencat                              svnmucc
+geqn                                svnserve
+getafm                              svnsync
+getconf                             svnversion
+getent                              swapoff
+gethostip                           swapon
+getkeycodes                         switch_root
+getopt                              sync
+getopts                             sysctl
+gettext                             syslinux
+gettext.sh                          syslinux2ansi
+gettextize                          syslog-facility
+getty                               syslogd
+ghostscript                         syslogd-listfiles
+ginstall-info                       tabs
+gio-querymodules                    tac
+gist                                tail
+git                                 tailf
+git-receive-pack                    tar
+git-shell                           taskset
+git-upload-archive                  tbl
+git-upload-pack                     tc
+gpasswd                             tclsh
+gpg                                 tclsh8.4
+gpg-zip                             tclsh8.5
+gpgsplit                            tcpd
+gpgv                                tcpdchk
+gpic                                tcpdmatch
+gprof                               tcpdump
+grep                                tcptraceroute
+groff                               tcptraceroute.db
+grog                                tcsh
+grops                               tee
+grotty                              telinit
+groupadd                            telnet
+groupdel                            telnet.netkit
+groupmod                            tempfile
+groups                              test/
+grpck                               testrb
+grpconv                             testrb-ruby-1.9.2-p180
+grpunconv                           testrb-ruby-1.9.2-p180@global
+gs                                  testrb1.8
+gsbj                                testsaslauthd
+gsdj                                tgz
+gsdj500                             then
+gslj                                thor
+gslp                                tic
+gsnd                                tickadj
+gtbl                                tilt
+gtk-query-immodules-2.0             time
+gtk-update-icon-cache               times
+gunzip                              tload
+gvcolor                             todos
+gvimtutor                           toe
+gvpack                              top
+gvpr                                touch
+gxl2dot                             tput
+gzexe                               tr
+gzip                                tracepath
+h2ph                                tracepath6
+h2xs                                traceproto
+halt                                traceproto.db
+haml                                traceroute
+hash                                traceroute-nanog
+hd                                  traceroute-nanog.db
+head                                traceroute.db
+help                                traceroute6
+helpztags                           traceroute6.db
+hexdump                             traceroute6.iputils
+history                             trap
+host                                tred
+hostid                              troff
+hostname                            true
+htcacheclean                        truncate
+htdbm                               try-from
+htdigest                            tset
+html2haml                           tsort
+html2text                           tt
+htpasswd                            tty
+httxt2dbm                           tune2fs
+hwclock                             tunelp
+i386                                turn
+iconv                               twopi
+iconvconfig                         type
+id                                  typeset
+identify                            tzconfig
+if                                  tzselect
+ifconfig                            ucf
+ifdown                              ucfq
+ifnames                             ucfr
+ifquery                             ucs2any
+ifup                                udevadm
+igawk                               udevd
+import                              ul
+in                                  ulimit
+includeres                          umask
+info                                umount
+infobrowser                         unalias
+infocmp                             uname
+infokey                             uncompress
+infotocap                           unexpand
+init                                unflatten
+initctl                             unicode_start
+innochecksum                        unicode_stop
+innotop                             uniq
+insmod                              unix_chkpwd
+insserv                             unix_update
+install                             unlink
+install-info                        unlzma
+install-keymap                      unset
+installkernel                       unshar
+instmodsh                           unshare
+intltool-extract                    until
+intltool-merge                      unxz
+intltool-prepare                    unzip
+intltool-update                     unzipsfx
+intltoolize                         update-alternatives
+invoke-rc.d                         update-bootsystem-insserv
+ionice                              update-ca-certificates
+ip                                  update-cracklib
+ip6tables                           update-fonts-alias
+ip6tables-apply                     update-fonts-dir
+ip6tables-restore                   update-fonts-scale
+ip6tables-save                      update-gdkpixbuf-loaders
+ipcmk                               update-gtk-immodules
+ipcrm                               update-icon-caches
+ipcs                                update-inetd
+ipmaddr                             update-info-dir
+iptables                            update-initramfs
+iptables-apply                      update-locale
+iptables-restore                    update-mime
+iptables-save                       update-mime-database
+iptables-xml                        update-mime-database.real
+iptunnel                            update-pangox-aliases
+irb                                 update-passwd
+irb-ruby-1.9.2-p180                 update-rc.d
+irb-ruby-1.9.2-p180@global          update-rc.d-insserv
+irb1.8                              updatedb
+is_a_function                       updatedb.mlocate
+isosize                             upstart-udev-bridge
+isql                                uptime
+iusql                               useradd
+jobs                                userdel
+join                                usermod
+kbd-config                          users
+kbd_mode                            uudecode
+kbdrate                             uuencode
+kill                                uuidd
+killall                             uuidgen
+killall5                            uxterm
+klogd                               uz
+koi8rxterm                          validlocale
+krb5-config                         vcstime
+ksh                                 vdir
+l                                   vi
+la                                  vidmode
+last                                view
+lastb                               viewres
+lastlog                             vigr
+lcf                                 vim
+ld                                  vim.basic
+ld.bfd                              vim.nox
+ldapadd                             vimdiff
+ldapcompare                         vimtutor
+ldapdelete                          vipw
+ldapexop                            visudo
+ldapmodify                          vmstat
+ldapmodrdn                          vows
+ldappasswd                          vows@0.5.8
+ldapsearch                          vt-is-UTF8
+ldapurl                             w
+ldapwhoami                          w.procps
+ldattach                            wait
+ldconfig                            wall
+ldconfig.real                       warnquota
+ldd                                 watch
+lefty                               wc
+less                                wftopfa
+lessecho                            wget
+lessfile                            whatis
+lesskey                             whereis
+lesspipe                            which
+let                                 while
+lexgrog                             whiptail
+lft                                 who
+lft.db                              whoami
+libgraphviz4-config-update          whois
+libnetcfg                           wipefs
+libpng-config                       wish
+libpng12-config                     wish8.5
+libtool                             write
+libtoolize                          writevt
+libwmf-config                       www-browser
+line                                x-terminal-emulator
+link                                x86_64
+linux32                             x86_64-linux-gnu-cpp
+linux64                             x86_64-linux-gnu-cpp-4.4
+listres                             x86_64-linux-gnu-g++
+ll                                  x86_64-linux-gnu-g++-4.4
+ln                                  x86_64-linux-gnu-gcc
+lneato                              x86_64-linux-gnu-gcc-4.4
+lnstat                              xargs
+loadkeys                            xdpyinfo
+local                               xdriinfo
+locale                              xev
+locale-gen                          xfd
+localedef                           xfontsel
+locate                              xgettext
+lockfile-check                      xkill
+lockfile-create                     xlsatoms
+lockfile-remove                     xlsclients
+lockfile-touch                      xlsfonts
+logger                              xmessage
+login                               xml2-config
+logname                             xmlwf
+logout                              xprop
+logresolve                          xqmstats
+logrotate                           xsubpp
+logsave                             xterm
+look                                xvinfo
+lorder                              xwininfo
+losetup                             xxd
+ls                                  xz
+lsattr                              xzcat
+lsb_release                         xzcmp
+lscpu                               xzdec
+lsdev                               xzdiff
+lsmod                               xzegrep
+lsof                                xzfgrep
+lspgpot                             xzgrep
+lss16toppm                          xzless
+luit                                xzmore
+lwp-download                        yes
+lwp-dump                            ypdomainname
+lwp-mirror                          zcat
+lwp-request                         zcmp
+lwp-rget                            zdiff
+lxterm                              zdump
+lynx                                zegrep
+lynx.cur                            zfgrep
+lz                                  zforce
+lzcat                               zgrep
+lzma                                zic
+lzmadec                             zipgrep
+lzmainfo                            zipinfo
+m4                                  zless
+mail-files                          zmore
+mail-lock                           znew
+mail-touchlock                      zsh
+mail-unlock                         zsh4
+maildirmake.dovecot                 zsoelim
+mailq                               {
+mailshar                            }

+ 2038 - 0
salamander.remote/fugitive.vim

@@ -0,0 +1,2038 @@
+" fugitive.vim - A Git wrapper so awesome, it should be illegal
+" Maintainer:   Tim Pope <vimNOSPAM@tpope.org>
+" Version:      1.2
+" GetLatestVimScripts: 2975 1 :AutoInstall: fugitive.vim
+
+if exists('g:loaded_fugitive') || &cp
+  finish
+endif
+let g:loaded_fugitive = 1
+
+if !exists('g:fugitive_git_executable')
+  let g:fugitive_git_executable = 'git'
+endif
+
+" Utility {{{1
+
+function! s:function(name) abort
+  return function(substitute(a:name,'^s:',matchstr(expand('<sfile>'), '<SNR>\d\+_'),''))
+endfunction
+
+function! s:sub(str,pat,rep) abort
+  return substitute(a:str,'\v\C'.a:pat,a:rep,'')
+endfunction
+
+function! s:gsub(str,pat,rep) abort
+  return substitute(a:str,'\v\C'.a:pat,a:rep,'g')
+endfunction
+
+function! s:shellesc(arg) abort
+  if a:arg =~ '^[A-Za-z0-9_/.-]\+$'
+    return a:arg
+  elseif &shell =~# 'cmd' && a:arg !~# '"'
+    return '"'.a:arg.'"'
+  else
+    return shellescape(a:arg)
+  endif
+endfunction
+
+function! s:fnameescape(file) abort
+  if exists('*fnameescape')
+    return fnameescape(a:file)
+  else
+    return escape(a:file," \t\n*?[{`$\\%#'\"|!<")
+  endif
+endfunction
+
+function! s:throw(string) abort
+  let v:errmsg = 'fugitive: '.a:string
+  throw v:errmsg
+endfunction
+
+function! s:warn(str)
+  echohl WarningMsg
+  echomsg a:str
+  echohl None
+  let v:warningmsg = a:str
+endfunction
+
+function! s:shellslash(path)
+  if exists('+shellslash') && !&shellslash
+    return s:gsub(a:path,'\\','/')
+  else
+    return a:path
+  endif
+endfunction
+
+function! s:add_methods(namespace, method_names) abort
+  for name in a:method_names
+    let s:{a:namespace}_prototype[name] = s:function('s:'.a:namespace.'_'.name)
+  endfor
+endfunction
+
+let s:commands = []
+function! s:command(definition) abort
+  let s:commands += [a:definition]
+endfunction
+
+function! s:define_commands()
+  for command in s:commands
+    exe 'command! -buffer '.command
+  endfor
+endfunction
+
+function! s:compatibility_check()
+  if exists('b:git_dir') && exists('*GitBranchInfoCheckGitDir') && !exists('g:fugitive_did_compatibility_warning')
+    let g:fugitive_did_compatibility_warning = 1
+    call s:warn("See http://github.com/tpope/vim-fugitive/issues#issue/1 for why you should remove git-branch-info.vim")
+  endif
+endfunction
+
+augroup fugitive_utility
+  autocmd!
+  autocmd User Fugitive call s:define_commands()
+  autocmd VimEnter * call s:compatibility_check()
+augroup END
+
+let s:abstract_prototype = {}
+
+" }}}1
+" Initialization {{{1
+
+function! s:ExtractGitDir(path) abort
+  let path = s:shellslash(a:path)
+  if path =~? '^fugitive://.*//'
+    return matchstr(path,'fugitive://\zs.\{-\}\ze//')
+  endif
+  let fn = fnamemodify(path,':s?[\/]$??')
+  let ofn = ""
+  let nfn = fn
+  while fn != ofn
+    if filereadable(fn . '/.git/HEAD')
+      return s:sub(simplify(fnamemodify(fn . '/.git',':p')),'\W$','')
+    elseif fn =~ '\.git$' && filereadable(fn . '/HEAD')
+      return s:sub(simplify(fnamemodify(fn,':p')),'\W$','')
+    endif
+    let ofn = fn
+    let fn = fnamemodify(ofn,':h')
+  endwhile
+  return ''
+endfunction
+
+function! s:Detect(path)
+  if exists('b:git_dir') && b:git_dir ==# ''
+    unlet b:git_dir
+  endif
+  if !exists('b:git_dir')
+    let dir = s:ExtractGitDir(a:path)
+    if dir != ''
+      let b:git_dir = dir
+    endif
+  endif
+  if exists('b:git_dir')
+    silent doautocmd User Fugitive
+    cnoremap <expr> <buffer> <C-R><C-G> fugitive#buffer().rev()
+    let buffer = fugitive#buffer()
+    if expand('%:p') =~# '//'
+      call buffer.setvar('&path',s:sub(buffer.getvar('&path'),'^\.%(,|$)',''))
+    endif
+    if b:git_dir !~# ',' && stridx(buffer.getvar('&tags'),b:git_dir.'/tags') == -1
+      if &filetype != ''
+        call buffer.setvar('&tags',buffer.getvar('&tags').','.b:git_dir.'/'.&filetype.'.tags')
+      endif
+      call buffer.setvar('&tags',buffer.getvar('&tags').','.b:git_dir.'/tags')
+    endif
+  endif
+endfunction
+
+augroup fugitive
+  autocmd!
+  autocmd BufNewFile,BufReadPost * call s:Detect(expand('<amatch>:p'))
+  autocmd FileType           netrw call s:Detect(expand('<afile>:p'))
+  autocmd VimEnter * if expand('<amatch>')==''|call s:Detect(getcwd())|endif
+  autocmd BufWinLeave * execute getwinvar(+winnr(), 'fugitive_restore')
+augroup END
+
+" }}}1
+" Repository {{{1
+
+let s:repo_prototype = {}
+let s:repos = {}
+
+function! s:repo(...) abort
+  let dir = a:0 ? a:1 : (exists('b:git_dir') && b:git_dir !=# '' ? b:git_dir : s:ExtractGitDir(expand('%:p')))
+  if dir !=# ''
+    if has_key(s:repos,dir)
+      let repo = get(s:repos,dir)
+    else
+      let repo = {'git_dir': dir}
+      let s:repos[dir] = repo
+    endif
+    return extend(extend(repo,s:repo_prototype,'keep'),s:abstract_prototype,'keep')
+  endif
+  call s:throw('not a git repository: '.expand('%:p'))
+endfunction
+
+function! s:repo_dir(...) dict abort
+  return join([self.git_dir]+a:000,'/')
+endfunction
+
+function! s:repo_tree(...) dict abort
+  if !self.bare()
+    let dir = fnamemodify(self.git_dir,':h')
+    return join([dir]+a:000,'/')
+  endif
+  call s:throw('no work tree')
+endfunction
+
+function! s:repo_bare() dict abort
+  return self.dir() !~# '/\.git$'
+endfunction
+
+function! s:repo_translate(spec) dict abort
+  if a:spec ==# '.' || a:spec ==# '/.'
+    return self.bare() ? self.dir() : self.tree()
+  elseif a:spec =~# '^/'
+    return fnamemodify(self.dir(),':h').a:spec
+  elseif a:spec =~# '^:[0-3]:'
+    return 'fugitive://'.self.dir().'//'.a:spec[1].'/'.a:spec[3:-1]
+  elseif a:spec ==# ':'
+    if $GIT_INDEX_FILE =~# '/[^/]*index[^/]*\.lock$' && fnamemodify($GIT_INDEX_FILE,':p')[0:strlen(s:repo().dir())] ==# s:repo().dir('') && filereadable($GIT_INDEX_FILE)
+      return fnamemodify($GIT_INDEX_FILE,':p')
+    else
+      return self.dir('index')
+    endif
+  elseif a:spec =~# '^:/'
+    let ref = self.rev_parse(matchstr(a:spec,'.[^:]*'))
+    return 'fugitive://'.self.dir().'//'.ref
+  elseif a:spec =~# '^:'
+    return 'fugitive://'.self.dir().'//0/'.a:spec[1:-1]
+  elseif a:spec =~# 'HEAD\|^refs/' && a:spec !~ ':' && filereadable(self.dir(a:spec))
+    return self.dir(a:spec)
+  elseif filereadable(s:repo().dir('refs/'.a:spec))
+    return self.dir('refs/'.a:spec)
+  elseif filereadable(s:repo().dir('refs/tags/'.a:spec))
+    return self.dir('refs/tags/'.a:spec)
+  elseif filereadable(s:repo().dir('refs/heads/'.a:spec))
+    return self.dir('refs/heads/'.a:spec)
+  elseif filereadable(s:repo().dir('refs/remotes/'.a:spec))
+    return self.dir('refs/remotes/'.a:spec)
+  elseif filereadable(s:repo().dir('refs/remotes/'.a:spec.'/HEAD'))
+    return self.dir('refs/remotes/'.a:spec,'/HEAD')
+  else
+    try
+      let ref = self.rev_parse(matchstr(a:spec,'[^:]*'))
+      let path = s:sub(matchstr(a:spec,':.*'),'^:','/')
+      return 'fugitive://'.self.dir().'//'.ref.path
+    catch /^fugitive:/
+      return self.tree(a:spec)
+    endtry
+  endif
+endfunction
+
+call s:add_methods('repo',['dir','tree','bare','translate'])
+
+function! s:repo_git_command(...) dict abort
+  let git = g:fugitive_git_executable . ' --git-dir='.s:shellesc(self.git_dir)
+  return git.join(map(copy(a:000),'" ".s:shellesc(v:val)'),'')
+endfunction
+
+function! s:repo_git_chomp(...) dict abort
+  return s:sub(system(call(self.git_command,a:000,self)),'\n$','')
+endfunction
+
+function! s:repo_git_chomp_in_tree(...) dict abort
+  let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
+  let dir = getcwd()
+  try
+    execute cd.'`=s:repo().tree()`'
+    return call(s:repo().git_chomp, a:000, s:repo())
+  finally
+    execute cd.'`=dir`'
+  endtry
+endfunction
+
+function! s:repo_rev_parse(rev) dict abort
+  let hash = self.git_chomp('rev-parse','--verify',a:rev)
+  if hash =~ '\<\x\{40\}$'
+    return matchstr(hash,'\<\x\{40\}$')
+  endif
+  call s:throw('rev-parse '.a:rev.': '.hash)
+endfunction
+
+call s:add_methods('repo',['git_command','git_chomp','git_chomp_in_tree','rev_parse'])
+
+function! s:repo_dirglob(base) dict abort
+  let base = s:sub(a:base,'^/','')
+  let matches = split(glob(self.tree(s:gsub(base,'/','*&').'*/')),"\n")
+  call map(matches,'v:val[ strlen(self.tree())+(a:base !~ "^/") : -1 ]')
+  return matches
+endfunction
+
+function! s:repo_superglob(base) dict abort
+  if a:base =~# '^/' || a:base !~# ':'
+    let results = []
+    if a:base !~# '^/'
+      let heads = ["HEAD","ORIG_HEAD","FETCH_HEAD","MERGE_HEAD"]
+      let heads += sort(split(s:repo().git_chomp("rev-parse","--symbolic","--branches","--tags","--remotes"),"\n"))
+      call filter(heads,'v:val[ 0 : strlen(a:base)-1 ] ==# a:base')
+      let results += heads
+    endif
+    if !self.bare()
+      let base = s:sub(a:base,'^/','')
+      let matches = split(glob(self.tree(s:gsub(base,'/','*&').'*')),"\n")
+      call map(matches,'s:shellslash(v:val)')
+      call map(matches,'v:val !~ "/$" && isdirectory(v:val) ? v:val."/" : v:val')
+      call map(matches,'v:val[ strlen(self.tree())+(a:base !~ "^/") : -1 ]')
+      let results += matches
+    endif
+    return results
+
+  elseif a:base =~# '^:'
+    let entries = split(self.git_chomp('ls-files','--stage'),"\n")
+    call map(entries,'s:sub(v:val,".*(\\d)\\t(.*)",":\\1:\\2")')
+    if a:base !~# '^:[0-3]\%(:\|$\)'
+      call filter(entries,'v:val[1] == "0"')
+      call map(entries,'v:val[2:-1]')
+    endif
+    call filter(entries,'v:val[ 0 : strlen(a:base)-1 ] ==# a:base')
+    return entries
+
+  else
+    let tree = matchstr(a:base,'.*[:/]')
+    let entries = split(self.git_chomp('ls-tree',tree),"\n")
+    call map(entries,'s:sub(v:val,"^04.*\\zs$","/")')
+    call map(entries,'tree.s:sub(v:val,".*\t","")')
+    return filter(entries,'v:val[ 0 : strlen(a:base)-1 ] ==# a:base')
+  endif
+endfunction
+
+call s:add_methods('repo',['dirglob','superglob'])
+
+function! s:repo_keywordprg() dict abort
+  let args = ' --git-dir='.escape(self.dir(),"\\\"' ").' show'
+  if has('gui_running') && !has('win32')
+    return g:fugitive_git_executable . ' --no-pager' . args
+  else
+    return g:fugitive_git_executable . args
+  endif
+endfunction
+
+call s:add_methods('repo',['keywordprg'])
+
+" }}}1
+" Buffer {{{1
+
+let s:buffer_prototype = {}
+
+function! s:buffer(...) abort
+  let buffer = {'#': bufnr(a:0 ? a:1 : '%')}
+  call extend(extend(buffer,s:buffer_prototype,'keep'),s:abstract_prototype,'keep')
+  if buffer.getvar('git_dir') !=# ''
+    return buffer
+  endif
+  call s:throw('not a git repository: '.expand('%:p'))
+endfunction
+
+function! fugitive#buffer(...) abort
+  return s:buffer(a:0 ? a:1 : '%')
+endfunction
+
+function! s:buffer_getvar(var) dict abort
+  return getbufvar(self['#'],a:var)
+endfunction
+
+function! s:buffer_setvar(var,value) dict abort
+  return setbufvar(self['#'],a:var,a:value)
+endfunction
+
+function! s:buffer_getline(lnum) dict abort
+  return getbufline(self['#'],a:lnum)[0]
+endfunction
+
+function! s:buffer_repo() dict abort
+  return s:repo(self.getvar('git_dir'))
+endfunction
+
+function! s:buffer_type(...) dict abort
+  if self.getvar('fugitive_type') != ''
+    let type = self.getvar('fugitive_type')
+  elseif fnamemodify(self.spec(),':p') =~# '.\git/refs/\|\.git/\w*HEAD$'
+    let type = 'head'
+  elseif self.getline(1) =~ '^tree \x\{40\}$' && self.getline(2) == ''
+    let type = 'tree'
+  elseif self.getline(1) =~ '^\d\{6\} \w\{4\} \x\{40\}\>\t'
+    let type = 'tree'
+  elseif self.getline(1) =~ '^\d\{6\} \x\{40\}\> \d\t'
+    let type = 'index'
+  elseif isdirectory(self.spec())
+    let type = 'directory'
+  elseif self.spec() == ''
+    let type = 'null'
+  elseif filereadable(self.spec())
+    let type = 'file'
+  else
+    let type = ''
+  endif
+  if a:0
+    return !empty(filter(copy(a:000),'v:val ==# type'))
+  else
+    return type
+  endif
+endfunction
+
+if has('win32')
+
+  function! s:buffer_spec() dict abort
+    let bufname = bufname(self['#'])
+    let retval = ''
+    for i in split(bufname,'[^:]\zs\\')
+      let retval = fnamemodify((retval==''?'':retval.'\').i,':.')
+    endfor
+    return s:shellslash(fnamemodify(retval,':p'))
+  endfunction
+
+else
+
+  function! s:buffer_spec() dict abort
+    let bufname = bufname(self['#'])
+    return s:shellslash(bufname == '' ? '' : fnamemodify(bufname,':p'))
+  endfunction
+
+endif
+
+function! s:buffer_name() dict abort
+  return self.spec()
+endfunction
+
+function! s:buffer_commit() dict abort
+  return matchstr(self.spec(),'^fugitive://.\{-\}//\zs\w*')
+endfunction
+
+function! s:buffer_path(...) dict abort
+  let rev = matchstr(self.spec(),'^fugitive://.\{-\}//\zs.*')
+  if rev != ''
+    let rev = s:sub(rev,'\w*','')
+  else
+    let rev = self.spec()[strlen(self.repo().tree()) : -1]
+  endif
+  return s:sub(s:sub(rev,'.\zs/$',''),'^/',a:0 ? a:1 : '')
+endfunction
+
+function! s:buffer_rev() dict abort
+  let rev = matchstr(self.spec(),'^fugitive://.\{-\}//\zs.*')
+  if rev =~ '^\x/'
+    return ':'.rev[0].':'.rev[2:-1]
+  elseif rev =~ '.'
+    return s:sub(rev,'/',':')
+  elseif self.spec() =~ '\.git/index$'
+    return ':'
+  elseif self.spec() =~ '\.git/refs/\|\.git/.*HEAD$'
+    return self.spec()[strlen(self.repo().dir())+1 : -1]
+  else
+    return self.path()
+  endif
+endfunction
+
+function! s:buffer_sha1() dict abort
+  if self.spec() =~ '^fugitive://' || self.spec() =~ '\.git/refs/\|\.git/.*HEAD$'
+    return self.repo().rev_parse(self.rev())
+  else
+    return ''
+  endif
+endfunction
+
+function! s:buffer_expand(rev) dict abort
+  if a:rev =~# '^:[0-3]$'
+    let file = a:rev.self.path(':')
+  elseif a:rev =~# '^[-:]/$'
+    let file = '/'.self.path()
+  elseif a:rev =~# '^-'
+    let file = 'HEAD^{}'.a:rev[1:-1].self.path(':')
+  elseif a:rev =~# '^@{'
+    let file = 'HEAD'.a:rev.self.path(':')
+  elseif a:rev =~# '^[~^]'
+    let commit = s:sub(self.commit(),'^\d=$','HEAD')
+    let file = commit.a:rev.self.path(':')
+  else
+    let file = a:rev
+  endif
+  return s:sub(s:sub(file,'\%$',self.path()),'\.\@<=/$','')
+endfunction
+
+function! s:buffer_containing_commit() dict abort
+  if self.commit() =~# '^\d$'
+    return ':'
+  elseif self.commit() =~# '.'
+    return self.commit()
+  else
+    return 'HEAD'
+  endif
+endfunction
+
+call s:add_methods('buffer',['getvar','setvar','getline','repo','type','spec','name','commit','path','rev','sha1','expand','containing_commit'])
+
+" }}}1
+" Git {{{1
+
+call s:command("-bang -nargs=? -complete=customlist,s:GitComplete Git :execute s:Git(<bang>0,<q-args>)")
+
+function! s:ExecuteInTree(cmd) abort
+  let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
+  let dir = getcwd()
+  try
+    execute cd.'`=s:repo().tree()`'
+    execute a:cmd
+  finally
+    execute cd.'`=dir`'
+  endtry
+endfunction
+
+function! s:Git(bang,cmd) abort
+  let git = s:repo().git_command()
+  if has('gui_running') && !has('win32')
+    let git .= ' --no-pager'
+  endif
+  let cmd = matchstr(a:cmd,'\v\C.{-}%($|\\@<!%(\\\\)*\|)@=')
+  call s:ExecuteInTree('!'.git.' '.cmd)
+  call fugitive#reload_status()
+  return matchstr(a:cmd,'\v\C\\@<!%(\\\\)*\|\zs.*')
+endfunction
+
+function! s:GitComplete(A,L,P) abort
+  if !exists('s:exec_path')
+    let s:exec_path = s:sub(system(g:fugitive_git_executable.' --exec-path'),'\n$','')
+  endif
+  let cmds = map(split(glob(s:exec_path.'/git-*'),"\n"),'s:sub(v:val[strlen(s:exec_path)+5 : -1],"\\.exe$","")')
+  if a:L =~ ' [[:alnum:]-]\+ '
+    return s:repo().superglob(a:A)
+  elseif a:A == ''
+    return cmds
+  else
+    return filter(cmds,'v:val[0 : strlen(a:A)-1] ==# a:A')
+  endif
+endfunction
+
+" }}}1
+" Gcd, Glcd {{{1
+
+function! s:DirComplete(A,L,P) abort
+  let matches = s:repo().dirglob(a:A)
+  return matches
+endfunction
+
+call s:command("-bar -bang -nargs=? -complete=customlist,s:DirComplete Gcd  :cd<bang>  `=s:repo().bare() ? s:repo().dir(<q-args>) : s:repo().tree(<q-args>)`")
+call s:command("-bar -bang -nargs=? -complete=customlist,s:DirComplete Glcd :lcd<bang> `=s:repo().bare() ? s:repo().dir(<q-args>) : s:repo().tree(<q-args>)`")
+
+" }}}1
+" Gstatus {{{1
+
+call s:command("-bar Gstatus :execute s:Status()")
+
+function! s:Status() abort
+  try
+    Gpedit :
+    wincmd P
+    nnoremap <buffer> <silent> q    :<C-U>bdelete<CR>
+  catch /^fugitive:/
+    return 'echoerr v:errmsg'
+  endtry
+  return ''
+endfunction
+
+function! fugitive#reload_status() abort
+  let mytab = tabpagenr()
+  for tab in [mytab] + range(1,tabpagenr('$'))
+    for winnr in range(1,tabpagewinnr(tab,'$'))
+      if getbufvar(tabpagebuflist(tab)[winnr-1],'fugitive_type') ==# 'index'
+        execute 'tabnext '.tab
+        if winnr != winnr()
+          execute winnr.'wincmd w'
+          let restorewinnr = 1
+        endif
+        try
+          if !&modified
+            call s:BufReadIndex()
+          endif
+        finally
+          if exists('restorewinnr')
+            wincmd p
+          endif
+          execute 'tabnext '.mytab
+        endtry
+      endif
+    endfor
+  endfor
+endfunction
+
+function! s:StageDiff(...) abort
+  let cmd = a:0 ? a:1 : 'Gdiff'
+  let section = getline(search('^# .*:$','bnW'))
+  let line = getline('.')
+  let filename = matchstr(line,'^#\t\%([[:alpha:] ]\+: *\)\=\zs.\{-\}\ze\%( (new commits)\)\=$')
+  if filename ==# '' && section == '# Changes to be committed:'
+    return 'Git diff --cached'
+  elseif filename ==# ''
+    return 'Git diff'
+  elseif line =~# '^#\trenamed:' && filename =~ ' -> '
+    let [old, new] = split(filename,' -> ')
+    execute 'Gedit '.s:fnameescape(':0:'.new)
+    return cmd.' HEAD:'.s:fnameescape(old)
+  elseif section == '# Changes to be committed:'
+    execute 'Gedit '.s:fnameescape(':0:'.filename)
+    return cmd.' -'
+  else
+    execute 'Gedit '.s:fnameescape('/'.filename)
+    return cmd
+  endif
+endfunction
+
+function! s:StageToggle(lnum1,lnum2) abort
+  try
+    let output = ''
+    for lnum in range(a:lnum1,a:lnum2)
+      let line = getline(lnum)
+      let repo = s:repo()
+      if line ==# '# Changes to be committed:'
+        call repo.git_chomp_in_tree('reset','-q')
+        silent! edit!
+        1
+        if !search('^# Untracked files:$','W')
+          call search('^# Change','W')
+        endif
+        return ''
+      elseif line =~# '^# Change\%(d but not updated\|s not staged for commit\):$'
+        call repo.git_chomp_in_tree('add','-u')
+        silent! edit!
+        1
+        if !search('^# Untracked files:$','W')
+          call search('^# Change','W')
+        endif
+        return ''
+      elseif line ==# '# Untracked files:'
+        " Work around Vim parser idiosyncrasy
+        call repo.git_chomp_in_tree('add','-N','.')
+        silent! edit!
+        1
+        if !search('^# Change\%(d but not updated\|s not staged for commit\):$','W')
+          call search('^# Change','W')
+        endif
+        return ''
+      endif
+      let filename = matchstr(line,'^#\t\%([[:alpha:] ]\+: *\)\=\zs.\{-\}\ze\%( (\a\+ [[:alpha:], ]\+)\)\=$')
+      if filename ==# ''
+        continue
+      endif
+      if !exists('first_filename')
+        let first_filename = filename
+      endif
+      execute lnum
+      let section = getline(search('^# .*:$','bnW'))
+      if line =~# '^#\trenamed:' && filename =~ ' -> '
+        let cmd = ['mv','--'] + reverse(split(filename,' -> '))
+        let filename = cmd[-1]
+      elseif section =~? ' to be '
+        let cmd = ['reset','-q','--',filename]
+      elseif line =~# '^#\tdeleted:'
+        let cmd = ['rm','--',filename]
+      else
+        let cmd = ['add','--',filename]
+      endif
+      let output .= call(repo.git_chomp_in_tree,cmd,s:repo())."\n"
+    endfor
+    if exists('first_filename')
+      let jump = first_filename
+      let f = matchstr(getline(a:lnum1-1),'^#\t\%([[:alpha:] ]\+: *\)\=\zs.*')
+      if f !=# '' | let jump = f | endif
+      let f = matchstr(getline(a:lnum2+1),'^#\t\%([[:alpha:] ]\+: *\)\=\zs.*')
+      if f !=# '' | let jump = f | endif
+      silent! edit!
+      1
+      redraw
+      call search('^#\t\%([[:alpha:] ]\+: *\)\=\V'.jump.'\%( (new commits)\)\=\$','W')
+    endif
+    echo s:sub(s:gsub(output,'\n+','\n'),'\n$','')
+  catch /^fugitive:/
+    return 'echoerr v:errmsg'
+  endtry
+  return 'checktime'
+endfunction
+
+function! s:StagePatch(lnum1,lnum2) abort
+  let add = []
+  let reset = []
+
+  for lnum in range(a:lnum1,a:lnum2)
+    let line = getline(lnum)
+    if line ==# '# Changes to be committed:'
+      return 'Git reset --patch'
+    elseif line =~# '^# Change\%(d but not updated\|s not staged for commit\):$'
+      return 'Git add --patch'
+    endif
+    let filename = matchstr(line,'^#\t\%([[:alpha:] ]\+: *\)\=\zs.\{-\}\ze\%( (new commits)\)\=$')
+    if filename ==# ''
+      continue
+    endif
+    if !exists('first_filename')
+      let first_filename = filename
+    endif
+    execute lnum
+    let section = getline(search('^# .*:$','bnW'))
+    if line =~# '^#\trenamed:' && filename =~ ' -> '
+      let reset += [split(filename,' -> ')[1]]
+    elseif section =~? ' to be '
+      let reset += [filename]
+    elseif line !~# '^#\tdeleted:'
+      let add += [filename]
+    endif
+  endfor
+  try
+    if !empty(add)
+      execute "Git add --patch -- ".join(map(add,'s:shellesc(v:val)'))
+    endif
+    if !empty(reset)
+      execute "Git reset --patch -- ".join(map(add,'s:shellesc(v:val)'))
+    endif
+    if exists('first_filename')
+      silent! edit!
+      1
+      redraw
+      call search('^#\t\%([[:alpha:] ]\+: *\)\=\V'.first_filename.'\%( (new commits)\)\=\$','W')
+    endif
+  catch /^fugitive:/
+    return 'echoerr v:errmsg'
+  endtry
+  return 'checktime'
+endfunction
+
+" }}}1
+" Gcommit {{{1
+
+call s:command("-nargs=? -complete=customlist,s:CommitComplete Gcommit :execute s:Commit(<q-args>)")
+
+function! s:Commit(args) abort
+  let old_type = s:buffer().type()
+  let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
+  let dir = getcwd()
+  let msgfile = s:repo().dir('COMMIT_EDITMSG')
+  let outfile = tempname()
+  let errorfile = tempname()
+  try
+    execute cd.'`=s:repo().tree()`'
+    if &shell =~# 'cmd'
+      let command = ''
+      let old_editor = $GIT_EDITOR
+      let $GIT_EDITOR = 'false'
+    else
+      let command = 'env GIT_EDITOR=false '
+    endif
+    let command .= s:repo().git_command('commit').' '.a:args
+    if &shell =~# 'csh'
+      call system('('.command.' > '.outfile.') >& '.errorfile)
+    elseif a:args =~# '\%(^\| \)--interactive\>'
+      call system(command.' 2> '.errorfile)
+    else
+      call system(command.' > '.outfile.' 2> '.errorfile)
+    endif
+    if !v:shell_error
+      if filereadable(outfile)
+        for line in readfile(outfile)
+          echo line
+        endfor
+      endif
+      return ''
+    else
+      let errors = readfile(errorfile)
+      let error = get(errors,-2,get(errors,-1,'!'))
+      if error =~# '\<false''\=\.$'
+        let args = a:args
+        let args = s:gsub(args,'%(%(^| )-- )@<!%(^| )@<=%(-[se]|--edit|--interactive)%($| )','')
+        let args = s:gsub(args,'%(%(^| )-- )@<!%(^| )@<=%(-F|--file|-m|--message)%(\s+|\=)%(''[^'']*''|"%(\\.|[^"])*"|\\.|\S)*','')
+        let args = s:gsub(args,'%(^| )@<=[%#]%(:\w)*','\=expand(submatch(0))')
+        let args = '-F '.s:shellesc(msgfile).' '.args
+        if args !~# '\%(^\| \)--cleanup\>'
+          let args = '--cleanup=strip '.args
+        endif
+        let old_nr = bufnr('')
+        if bufname('%') == '' && line('$') == 1 && getline(1) == '' && !&mod
+          edit `=msgfile`
+        else
+          keepalt split `=msgfile`
+        endif
+        if old_type ==# 'index'
+          execute 'bdelete '.old_nr
+        endif
+        let b:fugitive_commit_arguments = args
+        setlocal bufhidden=delete filetype=gitcommit
+        return '1'
+      elseif error ==# '!'
+        return s:Status()
+      else
+        call s:throw(error)
+      endif
+    endif
+  catch /^fugitive:/
+    return 'echoerr v:errmsg'
+  finally
+    if exists('old_editor')
+      let $GIT_EDITOR = old_editor
+    endif
+    call delete(outfile)
+    call delete(errorfile)
+    execute cd.'`=dir`'
+    call fugitive#reload_status()
+  endtry
+endfunction
+
+function! s:CommitComplete(A,L,P) abort
+  if a:A =~ '^-' || type(a:A) == type(0) " a:A is 0 on :Gcommit -<Tab>
+    let args = ['-C', '-F', '-a', '-c', '-e', '-i', '-m', '-n', '-o', '-q', '-s', '-t', '-u', '-v', '--all', '--allow-empty', '--amend', '--author=', '--cleanup=', '--dry-run', '--edit', '--file=', '--include', '--interactive', '--message=', '--no-verify', '--only', '--quiet', '--reedit-message=', '--reuse-message=', '--signoff', '--template=', '--untracked-files', '--verbose']
+    return filter(args,'v:val[0 : strlen(a:A)-1] ==# a:A')
+  else
+    return s:repo().superglob(a:A)
+  endif
+endfunction
+
+function! s:FinishCommit()
+  let args = getbufvar(+expand('<abuf>'),'fugitive_commit_arguments')
+  if !empty(args)
+    call setbufvar(+expand('<abuf>'),'fugitive_commit_arguments','')
+    return s:Commit(args)
+  endif
+  return ''
+endfunction
+
+augroup fugitive_commit
+  autocmd!
+  autocmd VimLeavePre,BufDelete *.git/COMMIT_EDITMSG execute s:sub(s:FinishCommit(), '^echoerr (.*)', 'echohl ErrorMsg|echo \1|echohl NONE')
+augroup END
+
+" }}}1
+" Ggrep, Glog {{{1
+
+if !exists('g:fugitive_summary_format')
+  let g:fugitive_summary_format = '%s'
+endif
+
+call s:command("-bang -nargs=? -complete=customlist,s:EditComplete Ggrep :execute s:Grep(<bang>0,<q-args>)")
+call s:command("-bar -bang -nargs=* -complete=customlist,s:EditComplete Glog :execute s:Log('grep<bang>',<f-args>)")
+
+function! s:Grep(bang,arg) abort
+  let grepprg = &grepprg
+  let grepformat = &grepformat
+  let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
+  let dir = getcwd()
+  try
+    execute cd.'`=s:repo().tree()`'
+    let &grepprg = s:repo().git_command('--no-pager', 'grep', '-n')
+    let &grepformat = '%f:%l:%m'
+    exe 'grep! '.escape(matchstr(a:arg,'\v\C.{-}%($|[''" ]\@=\|)@='),'|')
+    let list = getqflist()
+    for entry in list
+      if bufname(entry.bufnr) =~ ':'
+        let entry.filename = s:repo().translate(bufname(entry.bufnr))
+        unlet! entry.bufnr
+      elseif a:arg =~# '\%(^\| \)--cached\>'
+        let entry.filename = s:repo().translate(':0:'.bufname(entry.bufnr))
+        unlet! entry.bufnr
+      endif
+    endfor
+    call setqflist(list,'r')
+    if !a:bang && !empty(list)
+      return 'cfirst'.matchstr(a:arg,'\v\C[''" ]\zs\|.*')
+    else
+      return matchstr(a:arg,'\v\C[''" ]\|\zs.*')
+    endif
+  finally
+    let &grepprg = grepprg
+    let &grepformat = grepformat
+    execute cd.'`=dir`'
+  endtry
+endfunction
+
+function! s:Log(cmd,...)
+  let path = s:buffer().path('/')
+  if path =~# '^/\.git\%(/\|$\)' || index(a:000,'--') != -1
+    let path = ''
+  endif
+  let cmd = ['--no-pager', 'log', '--no-color']
+  let cmd += [escape('--pretty=format:fugitive://'.s:repo().dir().'//%H'.path.'::'.g:fugitive_summary_format,'%')]
+  if empty(filter(a:000[0 : index(a:000,'--')],'v:val !~# "^-"'))
+    if s:buffer().commit() =~# '\x\{40\}'
+      let cmd += [s:buffer().commit()]
+    elseif s:buffer().path() =~# '^\.git/refs/\|^\.git/.*HEAD$'
+      let cmd += [s:buffer().path()[5:-1]]
+    endif
+  end
+  let cmd += map(copy(a:000),'s:sub(v:val,"^\\%(%(:\\w)*)","\\=fnamemodify(s:buffer().path(),submatch(1))")')
+  if path =~# '/.'
+    let cmd += ['--',path[1:-1]]
+  endif
+  let grepformat = &grepformat
+  let grepprg = &grepprg
+  let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
+  let dir = getcwd()
+  try
+    execute cd.'`=s:repo().tree()`'
+    let &grepprg = call(s:repo().git_command,cmd,s:repo())
+    let &grepformat = '%f::%m'
+    exe a:cmd
+  finally
+    let &grepformat = grepformat
+    let &grepprg = grepprg
+    execute cd.'`=dir`'
+  endtry
+endfunction
+
+" }}}1
+" Gedit, Gpedit, Gsplit, Gvsplit, Gtabedit, Gread {{{1
+
+function! s:Edit(cmd,...) abort
+  if a:0 && a:1 == ''
+    return ''
+  elseif a:0
+    let file = s:buffer().expand(a:1)
+  elseif s:buffer().commit() ==# '' && s:buffer().path('/') !~# '^/.git\>'
+    let file = s:buffer().path(':')
+  else
+    let file = s:buffer().path('/')
+  endif
+  try
+    let file = s:repo().translate(file)
+  catch /^fugitive:/
+    return 'echoerr v:errmsg'
+  endtry
+  if a:cmd ==# 'read'
+    return 'silent %delete_|read '.s:fnameescape(file).'|silent 1delete_|diffupdate|'.line('.')
+  else
+    if &previewwindow && getbufvar('','fugitive_type') ==# 'index'
+      wincmd p
+    endif
+    return a:cmd.' '.s:fnameescape(file)
+  endif
+endfunction
+
+function! s:EditComplete(A,L,P) abort
+  return s:repo().superglob(a:A)
+endfunction
+
+call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Ge       :execute s:Edit('edit<bang>',<f-args>)")
+call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gedit    :execute s:Edit('edit<bang>',<f-args>)")
+call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gpedit   :execute s:Edit('pedit<bang>',<f-args>)")
+call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gsplit   :execute s:Edit('split<bang>',<f-args>)")
+call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gvsplit  :execute s:Edit('vsplit<bang>',<f-args>)")
+call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gtabedit :execute s:Edit('tabedit<bang>',<f-args>)")
+call s:command("-bar -bang -nargs=? -count -complete=customlist,s:EditComplete Gread :execute s:Edit((!<count> && <line1> ? '' : <count>).'read<bang>',<f-args>)")
+
+" }}}1
+" Gwrite, Gwq {{{1
+
+call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gwrite :execute s:Write(<bang>0,<f-args>)")
+call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gw :execute s:Write(<bang>0,<f-args>)")
+call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gwq :execute s:Wq(<bang>0,<f-args>)")
+
+function! s:Write(force,...) abort
+  if exists('b:fugitive_commit_arguments')
+    return 'write|bdelete'
+  elseif expand('%:t') == 'COMMIT_EDITMSG' && $GIT_INDEX_FILE != ''
+    return 'wq'
+  elseif s:buffer().type() == 'index'
+    return 'Gcommit'
+  endif
+  let mytab = tabpagenr()
+  let mybufnr = bufnr('')
+  let path = a:0 ? a:1 : s:buffer().path()
+  if path =~# '^:\d\>'
+    return 'write'.(a:force ? '! ' : ' ').s:fnameescape(s:repo().translate(s:buffer().expand(path)))
+  endif
+  let always_permitted = (s:buffer().path() ==# path && s:buffer().commit() =~# '^0\=$')
+  if !always_permitted && !a:force && s:repo().git_chomp_in_tree('diff','--name-status','HEAD','--',path) . s:repo().git_chomp_in_tree('ls-files','--others','--',path) !=# ''
+    let v:errmsg = 'fugitive: file has uncommitted changes (use ! to override)'
+    return 'echoerr v:errmsg'
+  endif
+  let file = s:repo().translate(path)
+  let treebufnr = 0
+  for nr in range(1,bufnr('$'))
+    if fnamemodify(bufname(nr),':p') ==# file
+      let treebufnr = nr
+    endif
+  endfor
+
+  if treebufnr > 0 && treebufnr != bufnr('')
+    let temp = tempname()
+    silent execute '%write '.temp
+    for tab in [mytab] + range(1,tabpagenr('$'))
+      for winnr in range(1,tabpagewinnr(tab,'$'))
+        if tabpagebuflist(tab)[winnr-1] == treebufnr
+          execute 'tabnext '.tab
+          if winnr != winnr()
+            execute winnr.'wincmd w'
+            let restorewinnr = 1
+          endif
+          try
+            let lnum = line('.')
+            let last = line('$')
+            silent execute '$read '.temp
+            silent execute '1,'.last.'delete_'
+            silent write!
+            silent execute lnum
+            let did = 1
+          finally
+            if exists('restorewinnr')
+              wincmd p
+            endif
+            execute 'tabnext '.mytab
+          endtry
+        endif
+      endfor
+    endfor
+    if !exists('did')
+      call writefile(readfile(temp,'b'),file,'b')
+    endif
+  else
+    execute 'write! '.s:fnameescape(s:repo().translate(path))
+  endif
+
+  if a:force
+    let error = s:repo().git_chomp_in_tree('add', '--force', file)
+  else
+    let error = s:repo().git_chomp_in_tree('add', file)
+  endif
+  if v:shell_error
+    let v:errmsg = 'fugitive: '.error
+    return 'echoerr v:errmsg'
+  endif
+  if s:buffer().path() ==# path && s:buffer().commit() =~# '^\d$'
+    set nomodified
+  endif
+
+  let one = s:repo().translate(':1:'.path)
+  let two = s:repo().translate(':2:'.path)
+  let three = s:repo().translate(':3:'.path)
+  for nr in range(1,bufnr('$'))
+    if bufloaded(nr) && !getbufvar(nr,'&modified') && (bufname(nr) == one || bufname(nr) == two || bufname(nr) == three)
+      execute nr.'bdelete'
+    endif
+  endfor
+
+  unlet! restorewinnr
+  let zero = s:repo().translate(':0:'.path)
+  for tab in range(1,tabpagenr('$'))
+    for winnr in range(1,tabpagewinnr(tab,'$'))
+      let bufnr = tabpagebuflist(tab)[winnr-1]
+      let bufname = bufname(bufnr)
+      if bufname ==# zero && bufnr != mybufnr
+        execute 'tabnext '.tab
+        if winnr != winnr()
+          execute winnr.'wincmd w'
+          let restorewinnr = 1
+        endif
+        try
+          let lnum = line('.')
+          let last = line('$')
+          silent $read `=file`
+          silent execute '1,'.last.'delete_'
+          silent execute lnum
+          set nomodified
+          diffupdate
+        finally
+          if exists('restorewinnr')
+            wincmd p
+          endif
+          execute 'tabnext '.mytab
+        endtry
+        break
+      endif
+    endfor
+  endfor
+  call fugitive#reload_status()
+  return 'checktime'
+endfunction
+
+function! s:Wq(force,...) abort
+  let bang = a:force ? '!' : ''
+  if exists('b:fugitive_commit_arguments')
+    return 'wq'.bang
+  endif
+  let result = call(s:function('s:Write'),[a:force]+a:000)
+  if result =~# '^\%(write\|wq\|echoerr\)'
+    return s:sub(result,'^write','wq')
+  else
+    return result.'|quit'.bang
+  endif
+endfunction
+
+" }}}1
+" Gdiff {{{1
+
+call s:command("-bang -bar -nargs=? -complete=customlist,s:EditComplete Gdiff :execute s:Diff(<bang>0,<f-args>)")
+call s:command("-bar -nargs=? -complete=customlist,s:EditComplete Gvdiff :execute s:Diff(0,<f-args>)")
+call s:command("-bar -nargs=? -complete=customlist,s:EditComplete Gsdiff :execute s:Diff(1,<f-args>)")
+
+augroup fugitive_diff
+  autocmd!
+  autocmd BufWinLeave * if s:diff_window_count() == 2 && &diff && getbufvar(+expand('<abuf>'), 'git_dir') !=# '' | call s:diff_off_all(getbufvar(+expand('<abuf>'), 'git_dir')) | endif
+  autocmd BufWinEnter * if s:diff_window_count() == 1 && &diff && getbufvar(+expand('<abuf>'), 'git_dir') !=# '' | diffoff | endif
+augroup END
+
+function! s:diff_window_count()
+  let c = 0
+  for nr in range(1,winnr('$'))
+    let c += getwinvar(nr,'&diff')
+  endfor
+  return c
+endfunction
+
+function! s:diff_off_all(dir)
+  for nr in range(1,winnr('$'))
+    if getwinvar(nr,'&diff')
+      if nr != winnr()
+        execute nr.'wincmd w'
+        let restorewinnr = 1
+      endif
+      if exists('b:git_dir') && b:git_dir ==# a:dir
+        diffoff
+      endif
+      if exists('restorewinnr')
+        wincmd p
+      endif
+    endif
+  endfor
+endfunction
+
+function! s:buffer_compare_age(commit) dict abort
+  let scores = {':0': 1, ':1': 2, ':2': 3, ':': 4, ':3': 5}
+  let my_score    = get(scores,':'.self.commit(),0)
+  let their_score = get(scores,':'.a:commit,0)
+  if my_score || their_score
+    return my_score < their_score ? -1 : my_score != their_score
+  elseif self.commit() ==# a:commit
+    return 0
+  endif
+  let base = self.repo().git_chomp('merge-base',self.commit(),a:commit)
+  if base ==# self.commit()
+    return -1
+  elseif base ==# a:commit
+    return 1
+  endif
+  let my_time    = +self.repo().git_chomp('log','--max-count=1','--pretty=format:%at',self.commit())
+  let their_time = +self.repo().git_chomp('log','--max-count=1','--pretty=format:%at',a:commit)
+  return my_time < their_time ? -1 : my_time != their_time
+endfunction
+
+call s:add_methods('buffer',['compare_age'])
+
+function! s:Diff(bang,...) abort
+  let split = a:bang ? 'split' : 'vsplit'
+  if exists(':DiffGitCached')
+    return 'DiffGitCached'
+  elseif (!a:0 || a:1 == ':') && s:buffer().commit() =~# '^[0-1]\=$' && s:repo().git_chomp_in_tree('ls-files', '--unmerged', '--', s:buffer().path()) !=# ''
+    let nr = bufnr('')
+    execute 'leftabove '.split.' `=fugitive#buffer().repo().translate(s:buffer().expand('':2''))`'
+    execute 'nnoremap <buffer> <silent> dp :diffput '.nr.'<Bar>diffupdate<CR>'
+    diffthis
+    wincmd p
+    execute 'rightbelow '.split.' `=fugitive#buffer().repo().translate(s:buffer().expand('':3''))`'
+    execute 'nnoremap <buffer> <silent> dp :diffput '.nr.'<Bar>diffupdate<CR>'
+    diffthis
+    wincmd p
+    diffthis
+    return ''
+  elseif a:0
+    if a:1 ==# ''
+      return ''
+    elseif a:1 ==# '/'
+      let file = s:buffer().path('/')
+    elseif a:1 ==# ':'
+      let file = s:buffer().path(':0:')
+    elseif a:1 =~# '^:/.'
+      try
+        let file = s:repo().rev_parse(a:1).s:buffer().path(':')
+      catch /^fugitive:/
+        return 'echoerr v:errmsg'
+      endtry
+    else
+      let file = s:buffer().expand(a:1)
+    endif
+    if file !~# ':' && file !~# '^/' && s:repo().git_chomp('cat-file','-t',file) =~# '^\%(tag\|commit\)$'
+      let file = file.s:buffer().path(':')
+    endif
+  else
+    let file = s:buffer().path(s:buffer().commit() == '' ? ':0:' : '/')
+  endif
+  try
+    let spec = s:repo().translate(file)
+    let commit = matchstr(spec,'\C[^:/]//\zs\x\+')
+    if s:buffer().compare_age(commit) < 0
+      execute 'rightbelow '.split.' `=spec`'
+    else
+      execute 'leftabove '.split.' `=spec`'
+    endif
+    diffthis
+    wincmd p
+    diffthis
+    return ''
+  catch /^fugitive:/
+    return 'echoerr v:errmsg'
+  endtry
+endfunction
+
+" }}}1
+" Gmove, Gremove {{{1
+
+function! s:Move(force,destination)
+  if a:destination =~# '^/'
+    let destination = a:destination[1:-1]
+  else
+    let destination = fnamemodify(s:sub(a:destination,'[%#]%(:\w)*','\=expand(submatch(0))'),':p')
+    if destination[0:strlen(s:repo().tree())] ==# s:repo().tree('')
+      let destination = destination[strlen(s:repo().tree('')):-1]
+    endif
+  endif
+  if isdirectory(s:buffer().name())
+    " Work around Vim parser idiosyncrasy
+    let discarded = s:buffer().setvar('&swapfile',0)
+  endif
+  let message = call(s:repo().git_chomp_in_tree,['mv']+(a:force ? ['-f'] : [])+['--', s:buffer().path(), destination], s:repo())
+  if v:shell_error
+    let v:errmsg = 'fugitive: '.message
+    return 'echoerr v:errmsg'
+  endif
+  let destination = s:repo().tree(destination)
+  if isdirectory(destination)
+    let destination = fnamemodify(s:sub(destination,'/$','').'/'.expand('%:t'),':.')
+  endif
+  call fugitive#reload_status()
+  if s:buffer().commit() == ''
+    if isdirectory(destination)
+      return 'edit '.s:fnameescape(destination)
+    else
+      return 'saveas! '.s:fnameescape(destination)
+    endif
+  else
+    return 'file '.s:fnameescape(s:repo().translate(':0:'.destination)
+  endif
+endfunction
+
+function! s:MoveComplete(A,L,P)
+  if a:A =~ '^/'
+    return s:repo().superglob(a:A)
+  else
+    let matches = split(glob(a:A.'*'),"\n")
+    call map(matches,'v:val !~ "/$" && isdirectory(v:val) ? v:val."/" : v:val')
+    return matches
+  endif
+endfunction
+
+function! s:Remove(force)
+  if s:buffer().commit() ==# ''
+    let cmd = ['rm']
+  elseif s:buffer().commit() ==# '0'
+    let cmd = ['rm','--cached']
+  else
+    let v:errmsg = 'fugitive: rm not supported here'
+    return 'echoerr v:errmsg'
+  endif
+  if a:force
+    let cmd += ['--force']
+  endif
+  let message = call(s:repo().git_chomp_in_tree,cmd+['--',s:buffer().path()],s:repo())
+  if v:shell_error
+    let v:errmsg = 'fugitive: '.s:sub(message,'error:.*\zs\n\(.*-f.*',' (add ! to force)')
+    return 'echoerr '.string(v:errmsg)
+  else
+    call fugitive#reload_status()
+    return 'bdelete'.(a:force ? '!' : '')
+  endif
+endfunction
+
+augroup fugitive_remove
+  autocmd!
+  autocmd User Fugitive if s:buffer().commit() =~# '^0\=$' |
+        \ exe "command! -buffer -bar -bang -nargs=1 -complete=customlist,s:MoveComplete Gmove :execute s:Move(<bang>0,<q-args>)" |
+        \ exe "command! -buffer -bar -bang Gremove :execute s:Remove(<bang>0)" |
+        \ endif
+augroup END
+
+" }}}1
+" Gblame {{{1
+
+augroup fugitive_blame
+  autocmd!
+  autocmd BufReadPost *.fugitiveblame setfiletype fugitiveblame
+  autocmd FileType fugitiveblame setlocal nomodeline | if exists('b:git_dir') | let &l:keywordprg = s:repo().keywordprg() | endif
+  autocmd Syntax fugitiveblame call s:BlameSyntax()
+  autocmd User Fugitive if s:buffer().type('file', 'blob') | exe "command! -buffer -bar -bang -range=0 -nargs=* Gblame :execute s:Blame(<bang>0,<line1>,<line2>,<count>,[<f-args>])" | endif
+augroup END
+
+function! s:Blame(bang,line1,line2,count,args) abort
+  try
+    if s:buffer().path() == ''
+      call s:throw('file or blob required')
+    endif
+    if filter(copy(a:args),'v:val !~# "^\\%(--root\|--show-name\\|-\\=\\%([ltwfs]\\|[MC]\\d*\\)\\+\\)$"') != []
+      call s:throw('unsupported option')
+    endif
+    call map(a:args,'s:sub(v:val,"^\\ze[^-]","-")')
+    let git_dir = s:repo().dir()
+    let cmd = ['--no-pager', 'blame', '--show-number'] + a:args
+    if s:buffer().commit() =~# '\D\|..'
+      let cmd += [s:buffer().commit()]
+    else
+      let cmd += ['--contents', '-']
+    endif
+    let basecmd = call(s:repo().git_command,cmd+['--',s:buffer().path()],s:repo())
+    try
+      let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
+      if !s:repo().bare()
+        let dir = getcwd()
+        execute cd.'`=s:repo().tree()`'
+      endif
+      if a:count
+        execute 'write !'.substitute(basecmd,' blame ',' blame -L '.a:line1.','.a:line2.' ','g')
+      else
+        let error = tempname()
+        let temp = error.'.fugitiveblame'
+        if &shell =~# 'csh'
+          silent! execute '%write !('.basecmd.' > '.temp.') >& '.error
+        else
+          silent! execute '%write !'.basecmd.' > '.temp.' 2> '.error
+        endif
+        if exists('l:dir')
+          execute cd.'`=dir`'
+          unlet dir
+        endif
+        if v:shell_error
+          call s:throw(join(readfile(error),"\n"))
+        endif
+        let bufnr = bufnr('')
+        let restore = 'call setwinvar(bufwinnr('.bufnr.'),"&scrollbind",0)'
+        if &l:wrap
+          let restore .= '|call setwinvar(bufwinnr('.bufnr.'),"&wrap",1)'
+        endif
+        if &l:foldenable
+          let restore .= '|call setwinvar(bufwinnr('.bufnr.'),"&foldenable",1)'
+        endif
+        let winnr = winnr()
+        windo set noscrollbind
+        exe winnr.'wincmd w'
+        setlocal scrollbind nowrap nofoldenable
+        let top = line('w0') + &scrolloff
+        let current = line('.')
+        exe 'leftabove vsplit '.temp
+        let b:git_dir = git_dir
+        let b:fugitive_type = 'blame'
+        let b:fugitive_blamed_bufnr = bufnr
+        let w:fugitive_restore = restore
+        let b:fugitive_blame_arguments = join(a:args,' ')
+        call s:Detect(expand('%:p'))
+        execute top
+        normal! zt
+        execute current
+        execute "vertical resize ".(match(getline('.'),'\s\+\d\+)')+1)
+        setlocal nomodified nomodifiable bufhidden=delete nonumber scrollbind nowrap foldcolumn=0 nofoldenable filetype=fugitiveblame
+        nnoremap <buffer> <silent> q    :<C-U>bdelete<CR>
+        nnoremap <buffer> <silent> <CR> :<C-U>exe <SID>BlameJump('')<CR>
+        nnoremap <buffer> <silent> P    :<C-U>exe <SID>BlameJump('^'.v:count1)<CR>
+        nnoremap <buffer> <silent> ~    :<C-U>exe <SID>BlameJump('~'.v:count1)<CR>
+        nnoremap <buffer> <silent> o    :<C-U>exe <SID>Edit((&splitbelow ? "botright" : "topleft")." split", matchstr(getline('.'),'\x\+'))<CR>
+        nnoremap <buffer> <silent> O    :<C-U>exe <SID>Edit("tabedit", matchstr(getline('.'),'\x\+'))<CR>
+        syncbind
+      endif
+    finally
+      if exists('l:dir')
+        execute cd.'`=dir`'
+      endif
+    endtry
+    return ''
+  catch /^fugitive:/
+    return 'echoerr v:errmsg'
+  endtry
+endfunction
+
+function! s:BlameJump(suffix) abort
+  let commit = matchstr(getline('.'),'^\^\=\zs\x\+')
+  if commit =~# '^0\+$'
+    let commit = ':0'
+  endif
+  let lnum = matchstr(getline('.'),'\d\+\ze\s\+[([:digit:]]')
+  let path = matchstr(getline('.'),'^\^\=\zs\x\+\s\+\zs.\{-\}\ze\s*\d\+ ')
+  if path ==# ''
+    let path = s:buffer(b:fugitive_blamed_bufnr).path()
+  endif
+  let args = b:fugitive_blame_arguments
+  let offset = line('.') - line('w0')
+  let bufnr = bufnr('%')
+  let winnr = bufwinnr(b:fugitive_blamed_bufnr)
+  if winnr > 0
+    exe winnr.'wincmd w'
+  endif
+  execute s:Edit('edit',commit.a:suffix.':'.path)
+  if winnr > 0
+    exe bufnr.'bdelete'
+  endif
+  execute 'Gblame '.args
+  execute lnum
+  let delta = line('.') - line('w0') - offset
+  if delta > 0
+    execute 'norm! 'delta."\<C-E>"
+  elseif delta < 0
+    execute 'norm! '(-delta)."\<C-Y>"
+  endif
+  syncbind
+  return ''
+endfunction
+
+function! s:BlameSyntax() abort
+  let b:current_syntax = 'fugitiveblame'
+  syn match FugitiveblameBoundary "^\^"
+  syn match FugitiveblameBlank                      "^\s\+\s\@=" nextgroup=FugitiveblameAnnotation,fugitiveblameOriginalFile,FugitiveblameOriginalLineNumber skipwhite
+  syn match FugitiveblameHash       "\%(^\^\=\)\@<=\x\{7,40\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite
+  syn match FugitiveblameUncommitted "\%(^\^\=\)\@<=0\{7,40\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite
+  syn region FugitiveblameAnnotation matchgroup=FugitiveblameDelimiter start="(" end="\%( \d\+\)\@<=)" contained keepend oneline
+  syn match FugitiveblameTime "[0-9:/+-][0-9:/+ -]*[0-9:/+-]\%( \+\d\+)\)\@=" contained containedin=FugitiveblameAnnotation
+  syn match FugitiveblameLineNumber         " \@<=\d\+)\@=" contained containedin=FugitiveblameAnnotation
+  syn match FugitiveblameOriginalFile       " \%(\f\+\D\@<=\|\D\@=\f\+\)\%(\%(\s\+\d\+\)\=\s\%((\|\s*\d\+)\)\)\@=" contained nextgroup=FugitiveblameOriginalLineNumber,FugitiveblameAnnotation skipwhite
+  syn match FugitiveblameOriginalLineNumber " \@<=\d\+\%(\s(\)\@=" contained nextgroup=FugitiveblameAnnotation skipwhite
+  syn match FugitiveblameOriginalLineNumber " \@<=\d\+\%(\s\+\d\+)\)\@=" contained nextgroup=FugitiveblameShort skipwhite
+  syn match FugitiveblameShort              "\d\+)" contained contains=FugitiveblameLineNumber
+  syn match FugitiveblameNotCommittedYet "(\@<=Not Committed Yet\>" contained containedin=FugitiveblameAnnotation
+  hi def link FugitiveblameBoundary           Keyword
+  hi def link FugitiveblameHash               Identifier
+  hi def link FugitiveblameUncommitted        Function
+  hi def link FugitiveblameTime               PreProc
+  hi def link FugitiveblameLineNumber         Number
+  hi def link FugitiveblameOriginalFile       String
+  hi def link FugitiveblameOriginalLineNumber Float
+  hi def link FugitiveblameShort              FugitiveblameDelimiter
+  hi def link FugitiveblameDelimiter          Delimiter
+  hi def link FugitiveblameNotCommittedYet    Comment
+endfunction
+
+" }}}1
+" Gbrowse {{{1
+
+call s:command("-bar -bang -count=0 -nargs=? -complete=customlist,s:EditComplete Gbrowse :execute s:Browse(<bang>0,<line1>,<count>,<f-args>)")
+
+function! s:Browse(bang,line1,count,...) abort
+  try
+    let rev = a:0 ? substitute(a:1,'@[[:alnum:]_-]*\%(://.\{-\}\)\=$','','') : ''
+    if rev ==# ''
+      let expanded = s:buffer().rev()
+    elseif rev ==# ':'
+      let expanded = s:buffer().path('/')
+    else
+      let expanded = s:buffer().expand(rev)
+    endif
+    let full = s:repo().translate(expanded)
+    let commit = ''
+    if full =~# '^fugitive://'
+      let commit = matchstr(full,'://.*//\zs\w\+')
+      let path = matchstr(full,'://.*//\w\+\zs/.*')
+      if commit =~ '..'
+        let type = s:repo().git_chomp('cat-file','-t',commit.s:sub(path,'^/',':'))
+      else
+        let type = 'blob'
+      endif
+      let path = path[1:-1]
+    elseif s:repo().bare()
+      let path = '.git/' . full[strlen(s:repo().dir())+1:-1]
+      let type = ''
+    else
+      let path = full[strlen(s:repo().tree())+1:-1]
+      if path =~# '^\.git/'
+        let type = ''
+      elseif isdirectory(full)
+        let type = 'tree'
+      else
+        let type = 'blob'
+      endif
+    endif
+    if path =~# '^\.git/.*HEAD' && filereadable(s:repo().dir(path[5:-1]))
+      let body = readfile(s:repo().dir(path[5:-1]))[0]
+      if body =~# '^\x\{40\}$'
+        let commit = body
+        let type = 'commit'
+        let path = ''
+      elseif body =~# '^ref: refs/'
+        let path = '.git/' . matchstr(body,'ref: \zs.*')
+      endif
+    endif
+
+    if a:0 && a:1 =~# '@[[:alnum:]_-]*\%(://.\{-\}\)\=$'
+      let remote = matchstr(a:1,'@\zs[[:alnum:]_-]\+\%(://.\{-\}\)\=$')
+    elseif path =~# '^\.git/refs/remotes/.'
+      let remote = matchstr(path,'^\.git/refs/remotes/\zs[^/]\+')
+    else
+      let remote = 'origin'
+      let branch = matchstr(rev,'^[[:alnum:]/._-]\+\ze[:^~@]')
+      if branch ==# '' && path =~# '^\.git/refs/\w\+/'
+        let branch = s:sub(path,'^\.git/refs/\w+/','')
+      endif
+      if filereadable(s:repo().dir('refs/remotes/'.branch))
+        let remote = matchstr(branch,'[^/]\+')
+        let rev = rev[strlen(remote)+1:-1]
+      else
+        if branch ==# ''
+          let branch = matchstr(s:repo().head_ref(),'\<refs/heads/\zs.*')
+        endif
+        if branch != ''
+          let remote = s:repo().git_chomp('config','branch.'.branch.'.remote')
+          if remote ==# ''
+            let remote = 'origin'
+          elseif rev[0:strlen(branch)-1] ==# branch && rev[strlen(branch)] =~# '[:^~@]'
+            let rev = s:repo().git_chomp('config','branch.'.branch.'.merge')[11:-1] . rev[strlen(branch):-1]
+          endif
+        endif
+      endif
+    endif
+
+    let raw = s:repo().git_chomp('config','remote.'.remote.'.url')
+    if raw ==# ''
+      let raw = remote
+    endif
+
+    let url = s:github_url(s:repo(),raw,rev,commit,path,type,a:line1,a:count)
+    if url == ''
+      let url = s:instaweb_url(s:repo(),rev,commit,path,type,a:count ? a:line1 : 0)
+    endif
+
+    if url == ''
+      call s:throw("Instaweb failed to start and '".remote."' is not a GitHub remote")
+    endif
+
+    if a:bang
+      let @* = url
+      return 'echomsg '.string(url)
+    else
+      return 'echomsg '.string(url).'|silent Git web--browse '.shellescape(url,1)
+    endif
+  catch /^fugitive:/
+    return 'echoerr v:errmsg'
+  endtry
+endfunction
+
+function! s:github_url(repo,url,rev,commit,path,type,line1,line2) abort
+  let path = a:path
+  let repo_path = matchstr(a:url,'^\%(https\=://\|git://\|git@\)github\.com[/:]\zs.\{-\}\ze\%(\.git\)\=$')
+  if repo_path ==# ''
+    return ''
+  endif
+  let root = 'https://github.com/' . repo_path
+  if path =~# '^\.git/refs/heads/'
+    let branch = a:repo.git_chomp('config','branch.'.path[16:-1].'.merge')[11:-1]
+    if branch ==# ''
+      return root . '/commits/' . path[16:-1]
+    else
+      return root . '/commits/' . branch
+    endif
+  elseif path =~# '^\.git/refs/.'
+    return root . '/commits/' . matchstr(path,'[^/]\+$')
+  elseif path =~# '.git/\%(config$\|hooks\>\)'
+    return root . '/admin'
+  elseif path =~# '^\.git\>'
+    return root
+  endif
+  if a:rev =~# '^[[:alnum:]._-]\+:'
+    let commit = matchstr(a:rev,'^[^:]*')
+  elseif a:commit =~# '^\d\=$'
+    let local = matchstr(a:repo.head_ref(),'\<refs/heads/\zs.*')
+    let commit = a:repo.git_chomp('config','branch.'.local.'.merge')[11:-1]
+    if commit ==# ''
+      let commit = local
+    endif
+  else
+    let commit = a:commit
+  endif
+  if a:type == 'tree'
+    let url = s:sub(root . '/tree/' . commit . '/' . path,'/$','')
+  elseif a:type == 'blob'
+    let url = root . '/blob/' . commit . '/' . path
+    if a:line2 && a:line1 == a:line2
+      let url .= '#L' . a:line1
+    elseif a:line2
+      let url .= '#L' . a:line1 . '-' . a:line2
+    endif
+  elseif a:type == 'tag'
+    let commit = matchstr(getline(3),'^tag \zs.*')
+    let url = root . '/tree/' . commit
+  else
+    let url = root . '/commit/' . commit
+  endif
+  return url
+endfunction
+
+function! s:instaweb_url(repo,rev,commit,path,type,...) abort
+  let output = a:repo.git_chomp('instaweb','-b','unknown')
+  if output =~# 'http://'
+    let root = matchstr(output,'http://.*').'/?p='.fnamemodify(a:repo.dir(),':t')
+  else
+    return ''
+  endif
+  if a:path =~# '^\.git/refs/.'
+    return root . ';a=shortlog;h=' . matchstr(a:path,'^\.git/\zs.*')
+  elseif a:path =~# '^\.git\>'
+    return root
+  endif
+  let url = root
+  if a:commit =~# '^\x\{40\}$'
+    if a:type ==# 'commit'
+      let url .= ';a=commit'
+    endif
+    let url .= ';h=' . a:repo.rev_parse(a:commit . (a:path == '' ? '' : ':' . a:path))
+  else
+    if a:type ==# 'blob'
+      let tmp = tempname()
+      silent execute 'write !'.a:repo.git_command('hash-object','-w','--stdin').' > '.tmp
+      let url .= ';h=' . readfile(tmp)[0]
+    else
+      try
+        let url .= ';h=' . a:repo.rev_parse((a:commit == '' ? 'HEAD' : ':' . a:commit) . ':' . a:path)
+      catch /^fugitive:/
+        call s:throw('fugitive: cannot browse uncommitted file')
+      endtry
+    endif
+    let root .= ';hb=' . matchstr(a:repo.head_ref(),'[^ ]\+$')
+  endif
+  if a:path !=# ''
+    let url .= ';f=' . a:path
+  endif
+  if a:0 && a:1
+    let url .= '#l' . a:1
+  endif
+  return url
+endfunction
+
+" }}}1
+" File access {{{1
+
+function! s:ReplaceCmd(cmd,...) abort
+  let fn = bufname('')
+  let tmp = tempname()
+  let prefix = ''
+  try
+    if a:0 && a:1 != ''
+      if &shell =~# 'cmd'
+        let old_index = $GIT_INDEX_FILE
+        let $GIT_INDEX_FILE = a:1
+      else
+        let prefix = 'env GIT_INDEX_FILE='.s:shellesc(a:1).' '
+      endif
+    endif
+    call writefile(split(system(prefix.a:cmd), "\n", 1), tmp)
+  finally
+    if exists('old_index')
+      let $GIT_INDEX_FILE = old_index
+    endif
+  endtry
+  silent exe 'keepalt file '.tmp
+  silent edit!
+  silent exe 'keepalt file '.s:fnameescape(fn)
+  call delete(tmp)
+  silent exe 'doau BufReadPost '.s:fnameescape(fn)
+endfunction
+
+function! s:BufReadIndex()
+  if !exists('b:fugitive_display_format')
+    let b:fugitive_display_format = filereadable(expand('%').'.lock')
+  endif
+  let b:fugitive_display_format = b:fugitive_display_format % 2
+  let b:fugitive_type = 'index'
+  try
+    let b:git_dir = s:repo().dir()
+    setlocal noro ma
+    if fnamemodify($GIT_INDEX_FILE !=# '' ? $GIT_INDEX_FILE : b:git_dir . '/index', ':p') ==# expand('%:p')
+      let index = ''
+    else
+      let index = expand('%:p')
+    endif
+    if b:fugitive_display_format
+      call s:ReplaceCmd(s:repo().git_command('ls-files','--stage'),index)
+      set ft=git nospell
+    else
+      let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
+      let dir = getcwd()
+      try
+        execute cd.'`=s:repo().tree()`'
+        call s:ReplaceCmd(s:repo().git_command('status'),index)
+      finally
+        execute cd.'`=dir`'
+      endtry
+      set ft=gitcommit
+    endif
+    setlocal ro noma nomod nomodeline bufhidden=delete
+    nnoremap <buffer> <silent> a :<C-U>let b:fugitive_display_format += 1<Bar>exe <SID>BufReadIndex()<CR>
+    nnoremap <buffer> <silent> i :<C-U>let b:fugitive_display_format -= 1<Bar>exe <SID>BufReadIndex()<CR>
+    nnoremap <buffer> <silent> D :<C-U>execute <SID>StageDiff()<CR>
+    nnoremap <buffer> <silent> dd :<C-U>execute <SID>StageDiff()<CR>
+    nnoremap <buffer> <silent> dh :<C-U>execute <SID>StageDiff('Gsdiff')<CR>
+    nnoremap <buffer> <silent> ds :<C-U>execute <SID>StageDiff('Gsdiff')<CR>
+    nnoremap <buffer> <silent> dv :<C-U>execute <SID>StageDiff()<CR>
+    nnoremap <buffer> <silent> - :<C-U>execute <SID>StageToggle(line('.'),line('.')+v:count1-1)<CR>
+    xnoremap <buffer> <silent> - :<C-U>execute <SID>StageToggle(line("'<"),line("'>"))<CR>
+    nnoremap <buffer> <silent> p :<C-U>execute <SID>StagePatch(line('.'),line('.')+v:count1-1)<CR>
+    xnoremap <buffer> <silent> p :<C-U>execute <SID>StagePatch(line("'<"),line("'>"))<CR>
+    nnoremap <buffer> <silent> <C-N> :call search('^#\t.*','W')<Bar>.<CR>
+    nnoremap <buffer> <silent> <C-P> :call search('^#\t.*','Wbe')<Bar>.<CR>
+    call s:JumpInit()
+    nunmap   <buffer>          P
+    nunmap   <buffer>          ~
+    nnoremap <buffer> <silent> C :<C-U>Gcommit<CR>
+  catch /^fugitive:/
+    return 'echoerr v:errmsg'
+  endtry
+endfunction
+
+function! s:FileRead()
+  try
+    let repo = s:repo(s:ExtractGitDir(expand('<amatch>')))
+    let path = s:sub(s:sub(matchstr(expand('<amatch>'),'fugitive://.\{-\}//\zs.*'),'/',':'),'^\d:',':&')
+    let hash = repo.rev_parse(path)
+    if path =~ '^:'
+      let type = 'blob'
+    else
+      let type = repo.git_chomp('cat-file','-t',hash)
+    endif
+    " TODO: use count, if possible
+    return "read !".escape(repo.git_command('cat-file',type,hash),'%#\')
+  catch /^fugitive:/
+    return 'echoerr v:errmsg'
+  endtry
+endfunction
+
+function! s:BufReadIndexFile()
+  try
+    let b:fugitive_type = 'blob'
+    let b:git_dir = s:repo().dir()
+    call s:ReplaceCmd(s:repo().git_command('cat-file','blob',s:buffer().sha1()))
+    return ''
+  catch /^fugitive: rev-parse/
+    silent exe 'doau BufNewFile '.s:fnameescape(bufname(''))
+    return ''
+  catch /^fugitive:/
+    return 'echoerr v:errmsg'
+  endtry
+endfunction
+
+function! s:BufWriteIndexFile()
+  let tmp = tempname()
+  try
+    let path = matchstr(expand('<amatch>'),'//\d/\zs.*')
+    let stage = matchstr(expand('<amatch>'),'//\zs\d')
+    silent execute 'write !'.s:repo().git_command('hash-object','-w','--stdin').' > '.tmp
+    let sha1 = readfile(tmp)[0]
+    let old_mode = matchstr(s:repo().git_chomp('ls-files','--stage',path),'^\d\+')
+    if old_mode == ''
+      let old_mode = executable(s:repo().tree(path)) ? '100755' : '100644'
+    endif
+    let info = old_mode.' '.sha1.' '.stage."\t".path
+    call writefile([info],tmp)
+    if has('win32')
+      let error = system('type '.tmp.'|'.s:repo().git_command('update-index','--index-info'))
+    else
+      let error = system(s:repo().git_command('update-index','--index-info').' < '.tmp)
+    endif
+    if v:shell_error == 0
+      setlocal nomodified
+      silent execute 'doautocmd BufWritePost '.s:fnameescape(expand('%:p'))
+      call fugitive#reload_status()
+      return ''
+    else
+      return 'echoerr '.string('fugitive: '.error)
+    endif
+  finally
+    call delete(tmp)
+  endtry
+endfunction
+
+function! s:BufReadObject()
+  try
+    setlocal noro ma
+    let b:git_dir = s:repo().dir()
+    let hash = s:buffer().sha1()
+    if !exists("b:fugitive_type")
+      let b:fugitive_type = s:repo().git_chomp('cat-file','-t',hash)
+    endif
+    if b:fugitive_type !~# '^\%(tag\|commit\|tree\|blob\)$'
+      return "echoerr 'fugitive: unrecognized git type'"
+    endif
+    let firstline = getline('.')
+    if !exists('b:fugitive_display_format') && b:fugitive_type != 'blob'
+      let b:fugitive_display_format = +getbufvar('#','fugitive_display_format')
+    endif
+
+    let pos = getpos('.')
+    silent %delete
+    setlocal endofline
+
+    if b:fugitive_type == 'tree'
+      let b:fugitive_display_format = b:fugitive_display_format % 2
+      if b:fugitive_display_format
+        call s:ReplaceCmd(s:repo().git_command('ls-tree',hash))
+      else
+        call s:ReplaceCmd(s:repo().git_command('show',hash))
+      endif
+    elseif b:fugitive_type == 'tag'
+      let b:fugitive_display_format = b:fugitive_display_format % 2
+      if b:fugitive_display_format
+        call s:ReplaceCmd(s:repo().git_command('cat-file',b:fugitive_type,hash))
+      else
+        call s:ReplaceCmd(s:repo().git_command('cat-file','-p',hash))
+      endif
+    elseif b:fugitive_type == 'commit'
+      let b:fugitive_display_format = b:fugitive_display_format % 2
+      if b:fugitive_display_format
+        call s:ReplaceCmd(s:repo().git_command('cat-file',b:fugitive_type,hash))
+      else
+        call s:ReplaceCmd(s:repo().git_command('show','--pretty=format:tree %T%nparent %P%nauthor %an <%ae> %ad%ncommitter %cn <%ce> %cd%nencoding %e%n%n%s%n%n%b',hash))
+        call search('^parent ')
+        if getline('.') ==# 'parent '
+          silent delete_
+        else
+          silent s/\%(^parent\)\@<! /\rparent /ge
+        endif
+        if search('^encoding \%(<unknown>\)\=$','W',line('.')+3)
+          silent delete_
+        end
+        1
+      endif
+    elseif b:fugitive_type ==# 'blob'
+      call s:ReplaceCmd(s:repo().git_command('cat-file',b:fugitive_type,hash))
+    endif
+    call setpos('.',pos)
+    setlocal ro noma nomod nomodeline
+    if b:fugitive_type !=# 'blob'
+      set filetype=git
+      nnoremap <buffer> <silent> a :<C-U>let b:fugitive_display_format += v:count1<Bar>exe <SID>BufReadObject()<CR>
+      nnoremap <buffer> <silent> i :<C-U>let b:fugitive_display_format -= v:count1<Bar>exe <SID>BufReadObject()<CR>
+    else
+      call s:JumpInit()
+    endif
+
+    return ''
+  catch /^fugitive:/
+    return 'echoerr v:errmsg'
+  endtry
+endfunction
+
+augroup fugitive_files
+  autocmd!
+  autocmd BufReadCmd  *.git/index                      exe s:BufReadIndex()
+  autocmd BufReadCmd  *.git/*index*.lock               exe s:BufReadIndex()
+  autocmd FileReadCmd fugitive://**//[0-3]/**          exe s:FileRead()
+  autocmd BufReadCmd  fugitive://**//[0-3]/**          exe s:BufReadIndexFile()
+  autocmd BufWriteCmd fugitive://**//[0-3]/**          exe s:BufWriteIndexFile()
+  autocmd BufReadCmd  fugitive://**//[0-9a-f][0-9a-f]* exe s:BufReadObject()
+  autocmd FileReadCmd fugitive://**//[0-9a-f][0-9a-f]* exe s:FileRead()
+  autocmd FileType git       call s:JumpInit()
+augroup END
+
+" }}}1
+" Go to file {{{1
+
+function! s:JumpInit() abort
+  nnoremap <buffer> <silent> <CR>    :<C-U>exe <SID>GF("edit")<CR>
+  if !&modifiable
+    nnoremap <buffer> <silent> o     :<C-U>exe <SID>GF("split")<CR>
+    nnoremap <buffer> <silent> O     :<C-U>exe <SID>GF("tabedit")<CR>
+    nnoremap <buffer> <silent> P     :<C-U>exe <SID>Edit('edit',<SID>buffer().commit().'^'.v:count1.<SID>buffer().path(':'))<CR>
+    nnoremap <buffer> <silent> ~     :<C-U>exe <SID>Edit('edit',<SID>buffer().commit().'~'.v:count1.<SID>buffer().path(':'))<CR>
+    nnoremap <buffer> <silent> C     :<C-U>exe <SID>Edit('edit',<SID>buffer().containing_commit())<CR>
+    nnoremap <buffer> <silent> cc    :<C-U>exe <SID>Edit('edit',<SID>buffer().containing_commit())<CR>
+    nnoremap <buffer> <silent> co    :<C-U>exe <SID>Edit('split',<SID>buffer().containing_commit())<CR>
+    nnoremap <buffer> <silent> cO    :<C-U>exe <SID>Edit('tabedit',<SID>buffer().containing_commit())<CR>
+    nnoremap <buffer> <silent> cp    :<C-U>exe <SID>Edit('pedit',<SID>buffer().containing_commit())<CR>
+  endif
+endfunction
+
+function! s:GF(mode) abort
+  try
+    let buffer = s:buffer()
+    let myhash = buffer.sha1()
+
+    if buffer.type('tree')
+      let showtree = (getline(1) =~# '^tree ' && getline(2) == "")
+      if showtree && line('.') == 1
+        return ""
+      elseif showtree && line('.') > 2
+        return s:Edit(a:mode,buffer.commit().':'.s:buffer().path().(buffer.path() =~# '^$\|/$' ? '' : '/').s:sub(getline('.'),'/$',''))
+      elseif getline('.') =~# '^\d\{6\} \l\{3,8\} \x\{40\}\t'
+        return s:Edit(a:mode,buffer.commit().':'.s:buffer().path().(buffer.path() =~# '^$\|/$' ? '' : '/').s:sub(matchstr(getline('.'),'\t\zs.*'),'/$',''))
+      endif
+
+    elseif buffer.type('blob')
+      let ref = expand("<cfile>")
+      try
+        let sha1 = buffer.repo().rev_parse(ref)
+      catch /^fugitive:/
+      endtry
+      if exists('sha1')
+        return s:Edit(a:mode,ref)
+      endif
+
+    else
+
+      " Index
+      if getline('.') =~# '^\d\{6\} \x\{40\} \d\t'
+        let ref = matchstr(getline('.'),'\x\{40\}')
+        let file = ':'.s:sub(matchstr(getline('.'),'\d\t.*'),'\t',':')
+        return s:Edit(a:mode,file)
+
+      elseif getline('.') =~# '^#\trenamed:.* -> '
+        let file = '/'.matchstr(getline('.'),' -> \zs.*')
+        return s:Edit(a:mode,file)
+      elseif getline('.') =~# '^#\t[[:alpha:] ]\+: *.'
+        let file = '/'.matchstr(getline('.'),': *\zs.\{-\}\ze\%( (new commits)\)\=$')
+        return s:Edit(a:mode,file)
+      elseif getline('.') =~# '^#\t.'
+        let file = '/'.matchstr(getline('.'),'#\t\zs.*')
+        return s:Edit(a:mode,file)
+      elseif getline('.') =~# ': needs merge$'
+        let file = '/'.matchstr(getline('.'),'.*\ze: needs merge$')
+        return s:Edit(a:mode,file).'|Gdiff'
+
+      elseif getline('.') ==# '# Not currently on any branch.'
+        return s:Edit(a:mode,'HEAD')
+      elseif getline('.') =~# '^# On branch '
+        let file = 'refs/heads/'.getline('.')[12:]
+        return s:Edit(a:mode,file)
+      elseif getline('.') =~# "^# Your branch .*'"
+        let file = matchstr(getline('.'),"'\\zs\\S\\+\\ze'")
+        return s:Edit(a:mode,file)
+      endif
+
+      let showtree = (getline(1) =~# '^tree ' && getline(2) == "")
+
+      if getline('.') =~# '^ref: '
+        let ref = strpart(getline('.'),5)
+
+      elseif getline('.') =~# '^parent \x\{40\}\>'
+        let ref = matchstr(getline('.'),'\x\{40\}')
+        let line = line('.')
+        let parent = 0
+        while getline(line) =~# '^parent '
+          let parent += 1
+          let line -= 1
+        endwhile
+        return s:Edit(a:mode,ref)
+
+      elseif getline('.') =~ '^tree \x\{40\}$'
+        let ref = matchstr(getline('.'),'\x\{40\}')
+        if s:repo().rev_parse(myhash.':') == ref
+          let ref = myhash.':'
+        endif
+        return s:Edit(a:mode,ref)
+
+      elseif getline('.') =~# '^object \x\{40\}$' && getline(line('.')+1) =~ '^type \%(commit\|tree\|blob\)$'
+        let ref = matchstr(getline('.'),'\x\{40\}')
+        let type = matchstr(getline(line('.')+1),'type \zs.*')
+
+      elseif getline('.') =~# '^\l\{3,8\} '.myhash.'$'
+        return ''
+
+      elseif getline('.') =~# '^\l\{3,8\} \x\{40\}\>'
+        let ref = matchstr(getline('.'),'\x\{40\}')
+        echoerr "warning: unknown context ".matchstr(getline('.'),'^\l*')
+
+      elseif getline('.') =~# '^[+-]\{3\} [ab/]'
+        let ref = getline('.')[4:]
+
+      elseif getline('.') =~# '^rename from '
+        let ref = 'a/'.getline('.')[12:]
+      elseif getline('.') =~# '^rename to '
+        let ref = 'b/'.getline('.')[10:]
+
+      elseif getline('.') =~# '^diff --git \%(a/.*\|/dev/null\) \%(b/.*\|/dev/null\)'
+        let dref = matchstr(getline('.'),'\Cdiff --git \zs\%(a/.*\|/dev/null\)\ze \%(b/.*\|/dev/null\)')
+        let ref = matchstr(getline('.'),'\Cdiff --git \%(a/.*\|/dev/null\) \zs\%(b/.*\|/dev/null\)')
+        let dcmd = 'Gdiff'
+
+      elseif getline('.') =~# '^index ' && getline(line('.')-1) =~# '^diff --git \%(a/.*\|/dev/null\) \%(b/.*\|/dev/null\)'
+        let line = getline(line('.')-1)
+        let dref = matchstr(line,'\Cdiff --git \zs\%(a/.*\|/dev/null\)\ze \%(b/.*\|/dev/null\)')
+        let ref = matchstr(line,'\Cdiff --git \%(a/.*\|/dev/null\) \zs\%(b/.*\|/dev/null\)')
+        let dcmd = 'Gdiff!'
+
+      elseif line('$') == 1 && getline('.') =~ '^\x\{40\}$'
+        let ref = getline('.')
+      else
+        let ref = ''
+      endif
+
+      if myhash ==# ''
+        let ref = s:sub(ref,'^a/','HEAD:')
+        let ref = s:sub(ref,'^b/',':0:')
+        if exists('dref')
+          let dref = s:sub(dref,'^a/','HEAD:')
+        endif
+      else
+        let ref = s:sub(ref,'^a/',myhash.'^:')
+        let ref = s:sub(ref,'^b/',myhash.':')
+        if exists('dref')
+          let dref = s:sub(dref,'^a/',myhash.'^:')
+        endif
+      endif
+
+      if ref ==# '/dev/null'
+        " Empty blob
+        let ref = 'e69de29bb2d1d6434b8b29ae775ad8c2e48c5391'
+      endif
+
+      if exists('dref')
+        return s:Edit(a:mode,ref) . '|'.dcmd.' '.s:fnameescape(dref)
+      elseif ref != ""
+        return s:Edit(a:mode,ref)
+      endif
+
+    endif
+    return ''
+  catch /^fugitive:/
+    return 'echoerr v:errmsg'
+  endtry
+endfunction
+
+" }}}1
+" Statusline {{{1
+
+function! s:repo_head_ref() dict abort
+  return readfile(s:repo().dir('HEAD'))[0]
+endfunction
+
+call s:add_methods('repo',['head_ref'])
+
+function! fugitive#statusline(...)
+  if !exists('b:git_dir')
+    return ''
+  endif
+  let status = ''
+  if s:buffer().commit() != ''
+    let status .= ':' . s:buffer().commit()[0:7]
+  endif
+  let head = s:repo().head_ref()
+  if head =~# '^ref: '
+    let status .= s:sub(head,'^ref: %(refs/%(heads/|remotes/|tags/)=)=','(').')'
+  elseif head =~# '^\x\{40\}$'
+    let status .= '('.head[0:7].')'
+  endif
+  if &statusline =~# '%[MRHWY]' && &statusline !~# '%[mrhwy]'
+    return ',GIT'.status
+  else
+    return '[Git'.status.']'
+  endif
+endfunction
+
+function! s:repo_config(conf) dict abort
+  return matchstr(system(s:repo().git_command('config').' '.a:conf),"[^\r\n]*")
+endfun
+
+function! s:repo_user() dict abort
+  let username = s:repo().config('user.name')
+  let useremail = s:repo().config('user.email')
+  return username.' <'.useremail.'>'
+endfun
+
+call s:add_methods('repo',['config', 'user'])
+
+" }}}1
+
+" vim:set ft=vim ts=8 sw=2 sts=2:

+ 823 - 0
salamander.remote/gist.vim

@@ -0,0 +1,823 @@
+"=============================================================================
+" File: gist.vim
+" Author: Yasuhiro Matsumoto <mattn.jp@gmail.com>
+" Last Change: 18-Apr-2011.
+" Version: 4.9
+" WebPage: http://github.com/mattn/gist-vim
+" License: BSD
+" Usage:
+"
+"   :Gist
+"     post current buffer to gist, using default privicy option
+"     (see g:gist_private)
+"
+"   :'<,'>Gist
+"     post selected text to gist., using default privicy option
+"     This applies to all permutations listed below (except multi)
+"     (see g:gist_private)
+"
+"   :Gist -p
+"     create a private gist
+"
+"   :Gist -P
+"     create a public gist
+"     (only relevant if you've set gists to be private by default)
+"
+"   :Gist -P
+"     post whole text to gist as public
+"     This is only relevant if you've set gists to be private by default
+"   :Gist -a
+"     create a gist anonymously
+"
+"   :Gist -m
+"     create a gist with all open buffers
+"
+"   :Gist -e
+"     edit the gist. (you need to have opend the gist buffer first)
+"     you can update the gist with :w command on gist buffer
+"
+"   :Gist -d
+"     delete the gist. (you need to have opend the gist buffer first)
+"     password authentication is needed
+"
+"   :Gist -f
+"     fork the gist. (you need to have opend the gist buffer first)
+"     password authentication is needed
+"
+"   :Gist -e foo.js
+"     edit the gist with name 'foo.js'. (you need to have opend the gist buffer first)
+"
+"   :Gist XXXXX
+"     get gist XXXXX
+"
+"   :Gist -c XXXXX
+"     get gist XXXXX and add to clipboard
+"
+"   :Gist -l
+"     list your public gists
+"
+"   :Gist -l mattn
+"     list gists from mattn
+"
+"   :Gist -la
+"     list all your (public and private) gists
+"
+" Tips:
+"   * if set g:gist_clip_command, gist.vim will copy the gist code
+"       with option '-c'.
+"
+"     # mac
+"     let g:gist_clip_command = 'pbcopy'
+"
+"     # linux
+"     let g:gist_clip_command = 'xclip -selection clipboard'
+"
+"     # others(cygwin?)
+"     let g:gist_clip_command = 'putclip'
+"
+"   * if you want to detect filetype from gist's filename...
+"
+"     # detect filetype if vim failed auto-detection.
+"     let g:gist_detect_filetype = 1
+"
+"     # detect filetype always.
+"     let g:gist_detect_filetype = 2
+"
+"   * if you want to open browser after the post...
+"
+"     let g:gist_open_browser_after_post = 1
+"
+"   * if you want to change the browser...
+"
+"     let g:gist_browser_command = 'w3m %URL%'
+"
+"       or
+"
+"     let g:gist_browser_command = 'opera %URL% &'
+"
+"     on windows, should work with original setting.
+"
+"   * if you want to show your private gists with ':Gist -l'
+"
+"     let g:gist_show_privates = 1
+"
+"   * if don't you want to copy URL of the post...
+"
+"     let g:gist_put_url_to_clipboard_after_post = 0
+"
+"     or if you want to copy URL and add linefeed at the last of URL,
+"
+"     let g:gist_put_url_to_clipboard_after_post = 2
+"
+"     default value is 1.
+"
+" Thanks:
+"   MATSUU Takuto:
+"     removed carriage return
+"     gist_browser_command enhancement
+"     edit support
+"
+" GetLatestVimScripts: 2423 1 :AutoInstall: gist.vim
+" script type: plugin
+
+if &cp || (exists('g:loaded_gist_vim') && g:loaded_gist_vim)
+  finish
+endif
+let g:loaded_gist_vim = 1
+
+if (!exists('g:github_user') || !exists('g:github_token')) && !executable('git')
+  echoerr "Gist: require 'git' command"
+  finish
+endif
+
+if !executable('curl')
+  echoerr "Gist: require 'curl' command"
+  finish
+endif
+
+if !exists('g:gist_open_browser_after_post')
+  let g:gist_open_browser_after_post = 0
+endif
+
+if !exists('g:gist_put_url_to_clipboard_after_post')
+  let g:gist_put_url_to_clipboard_after_post = 1
+endif
+
+if !exists('g:gist_curl_options')
+  let g:gist_curl_options = ""
+endif
+
+if !exists('g:gist_browser_command')
+  if has('win32')
+    let g:gist_browser_command = "!start rundll32 url.dll,FileProtocolHandler %URL%"
+  elseif has('mac')
+    let g:gist_browser_command = "open %URL%"
+  elseif executable('xdg-open')
+    let g:gist_browser_command = "xdg-open %URL%"
+  else
+    let g:gist_browser_command = "firefox %URL% &"
+  endif
+endif
+
+if !exists('g:gist_detect_filetype')
+  let g:gist_detect_filetype = 0
+endif
+
+if !exists('g:gist_private')
+  let g:gist_private = 0
+endif
+
+if !exists('g:gist_show_privates')
+  let g:gist_show_privates = 0
+endif
+
+if !exists('g:gist_cookie_dir')
+  let g:gist_cookie_dir = substitute(expand('<sfile>:p:h'), '[/\\]plugin$', '', '').'/cookies'
+endif
+
+function! s:nr2hex(nr)
+  let n = a:nr
+  let r = ""
+  while n
+    let r = '0123456789ABCDEF'[n % 16] . r
+    let n = n / 16
+  endwhile
+  return r
+endfunction
+
+function! s:encodeURIComponent(instr)
+  let instr = iconv(a:instr, &enc, "utf-8")
+  let len = strlen(instr)
+  let i = 0
+  let outstr = ''
+  while i < len
+    let ch = instr[i]
+    if ch =~# '[0-9A-Za-z-._~!''()*]'
+      let outstr = outstr . ch
+    elseif ch == ' '
+      let outstr = outstr . '+'
+    else
+      let outstr = outstr . '%' . substitute('0' . s:nr2hex(char2nr(ch)), '^.*\(..\)$', '\1', '')
+    endif
+    let i = i + 1
+  endwhile
+  return outstr
+endfunction
+
+" Note: A colon in the file name has side effects on Windows due to NTFS Alternate Data Streams; avoid it. 
+let s:bufprefix = 'gist' . (has('unix') ? ':' : '_')
+function! s:GistList(user, token, gistls, page)
+  if a:gistls == '-all'
+    let url = 'https://gist.github.com/gists'
+  elseif g:gist_show_privates && a:gistls == a:user
+    let url = 'https://gist.github.com/mine'
+  else
+    let url = 'https://gist.github.com/'.a:gistls
+  endif
+  let winnum = bufwinnr(bufnr(s:bufprefix.a:gistls))
+  if winnum != -1
+    if winnum != bufwinnr('%')
+      exe "normal \<c-w>".winnum."w"
+    endif
+    setlocal modifiable
+  else
+    exec 'silent split' s:bufprefix.a:gistls
+  endif
+  if a:page > 1
+    let oldlines = getline(0, line('$'))
+    let url = url . '?page=' . a:page
+  endif
+
+  setlocal foldmethod=manual
+  let oldlines = []
+  if g:gist_show_privates
+    echon 'Login to gist... '
+    silent %d _
+    let res = s:GistGetPage(url, a:user, '', '-L')
+    silent put =res.content
+  else
+    silent %d _
+    exec 'silent r! curl -s '.g:gist_curl_options.' '.url
+  endif
+
+  silent normal! ggdd
+  silent! %s/>/>\r/g
+  silent! %s/</\r</g
+  silent! %g/<pre/,/<\/pre/join!
+  silent! %g/<span class="date"/,/<\/span/join
+  silent! %g/^<span class="date"/s/> */>/g
+  silent! %v/^\(gist:\|<pre>\|<span class="date">\)/d _
+  silent! %s/<div[^>]*>/\r  /g
+  silent! %s/<\/pre>/\r/g
+  silent! %g/^gist:/,/<span class="date"/join
+  silent! %s/<[^>]\+>//g
+  silent! %s/\r//g
+  silent! %s/&nbsp;/ /g
+  silent! %s/&quot;/"/g
+  silent! %s/&amp;/\&/g
+  silent! %s/&gt;/>/g
+  silent! %s/&lt;/</g
+  silent! %s/&#\(\d\d\);/\=nr2char(submatch(1))/g
+  silent! %g/^gist: /s/ //g
+
+  call append(0, oldlines)
+  normal! Gomore...
+
+  let b:user = a:user
+  let b:token = a:token
+  let b:gistls = a:gistls
+  let b:page = a:page
+  setlocal buftype=nofile bufhidden=hide noswapfile
+  setlocal nomodified
+  syntax match SpecialKey /^gist:/he=e-1
+  exec 'nnoremap <silent> <buffer> <cr> :call <SID>GistListAction()<cr>'
+
+  cal cursor(1+len(oldlines),1)
+  setlocal foldmethod=expr
+  setlocal foldexpr=getline(v:lnum)=~'^\\(gist:\\\|more\\)'?'>1':'='
+  setlocal foldtext=getline(v:foldstart)
+endfunction
+
+function! s:GistGetFileName(gistid)
+  let url = 'https://gist.github.com/'.a:gistid
+  let res = system('curl -s '.g:gist_curl_options.' '.url)
+  let res = substitute(res, '^.*<a href="/raw/[^"]\+/\([^"]\+\)".*$', '\1', '')
+  if res =~ '/'
+    return ''
+  else
+    return res
+  endif
+endfunction
+
+function! s:GistDetectFiletype(gistid)
+  let url = 'https://gist.github.com/'.a:gistid
+  let mx = '^.*<div class=".\{-}type-\([^"]\+\)">.*$'
+  let res = system('curl -s '.g:gist_curl_options.' '.url)
+  let res = substitute(matchstr(res, mx), mx, '\1', '')
+  let res = substitute(res, '.*\(\.[^\.]\+\)$', '\1', '')
+  let res = substitute(res, '-', '', 'g')
+  " TODO: more filetype detection that is specified in html.
+  if res == 'bat' | let res = 'dosbatch' | endif
+  if res == 'as' | let res = 'actionscript' | endif
+  if res == 'bash' | let res = 'sh' | endif
+  if res == 'cl' | let res = 'lisp' | endif
+  if res == 'rb' | let res = 'ruby' | endif
+  if res == 'viml' | let res = 'vim' | endif
+  if res == 'plain' || res == 'text' | let res = '' | endif
+
+  if res =~ '^\.'
+    silent! exec "doau BufRead *".res
+  else
+    silent! exec "setlocal ft=".tolower(res)
+  endif
+endfunction
+
+function! s:GistWrite(fname)
+  if substitute(a:fname, '\\', '/', 'g') == expand("%:p:gs@\\@/@")
+    Gist -e
+  else
+    exe "w".(v:cmdbang ? "!" : "")." ".fnameescape(v:cmdarg)." ".fnameescape(a:fname)
+  endif
+endfunction
+
+function! s:GistGet(user, token, gistid, clipboard)
+  let url = 'https://gist.github.com/'.a:gistid.'.txt'
+  let winnum = bufwinnr(bufnr(s:bufprefix.a:gistid))
+  if winnum != -1
+    if winnum != bufwinnr('%')
+      exe "normal \<c-w>".winnum."w"
+    endif
+    setlocal modifiable
+  else
+    exec 'silent split' s:bufprefix.a:gistid
+  endif
+  filetype detect
+  silent %d _
+  exec 'silent 0r! curl -s '.g:gist_curl_options.' '.url
+  normal! Gd_
+  setlocal buftype=acwrite bufhidden=delete noswapfile
+  setlocal nomodified
+  doau StdinReadPost <buffer>
+  if (&ft == '' && g:gist_detect_filetype == 1) || g:gist_detect_filetype == 2
+    call s:GistDetectFiletype(a:gistid)
+  endif
+  if a:clipboard
+    if exists('g:gist_clip_command')
+      exec 'silent w !'.g:gist_clip_command
+    else
+      normal! gg"+yG
+    endif
+  endif
+  normal! gg
+  au! BufWriteCmd <buffer> call s:GistWrite(expand("<amatch>"))
+endfunction
+
+function! s:GistListAction()
+  let line = getline('.')
+  let mx = '^gist:\(\w\+\).*'
+  if line =~# mx
+    let gistid = substitute(line, mx, '\1', '')
+    call s:GistGet(g:github_user, g:github_token, gistid, 0)
+    return
+  endif
+  if line =~# '^more\.\.\.$'
+    normal! dd
+    call s:GistList(b:user, b:token, b:gistls, b:page+1)
+    return
+  endif
+endfunction
+
+function! s:GistUpdate(user, token, content, gistid, gistnm)
+  if len(a:gistnm) == 0
+    let name = s:GistGetFileName(a:gistid)
+  else
+    let name = a:gistnm
+  endif
+  let namemx = '^[^.]\+\(.\+\)$'
+  let ext = ''
+  if name =~ namemx
+    let ext = substitute(name, namemx, '\1', '')
+  endif
+  let query = [
+    \ '_method=put',
+    \ 'file_ext[gistfile1%s]=%s',
+    \ 'file_name[gistfile1%s]=%s',
+    \ 'file_contents[gistfile1%s]=%s',
+    \ 'login=%s',
+    \ 'token=%s',
+    \ ]
+  let squery = printf(join(query, '&'),
+    \ s:encodeURIComponent(ext), s:encodeURIComponent(ext),
+    \ s:encodeURIComponent(ext), s:encodeURIComponent(name),
+    \ s:encodeURIComponent(ext), s:encodeURIComponent(a:content),
+    \ s:encodeURIComponent(a:user),
+    \ s:encodeURIComponent(a:token))
+  unlet query
+
+  let file = tempname()
+  call writefile([squery], file)
+  echon 'Updating it to gist... '
+  let quote = &shellxquote == '"' ?  "'" : '"'
+  let url = 'https://gist.github.com/gists/'.a:gistid
+  let res = system('curl -i '.g:gist_curl_options.' -d @'.quote.file.quote.' '.url)
+  call delete(file)
+  let headers = split(res, '\(\r\?\n\|\r\n\?\)')
+  let location = matchstr(headers, '^Location: ')
+  let location = substitute(location, '^[^:]\+: ', '', '')
+  if len(location) > 0 && location =~ '^\(http\|https\):\/\/gist\.github\.com\/'
+    setlocal nomodified
+    redraw
+    echo 'Done: '.location
+  else
+    let message = matchstr(headers, '^Status: ')
+    let message = substitute(message, '^[^:]\+: [0-9]\+ ', '', '')
+    echoerr 'Edit failed: '.message
+  endif
+  return location
+endfunction
+
+function! s:GistGetPage(url, user, param, opt)
+  if !isdirectory(g:gist_cookie_dir)
+    call mkdir(g:gist_cookie_dir, 'p')
+  endif
+  let cookie_file = g:gist_cookie_dir.'/github'
+
+  if len(a:url) == 0
+    call delete(cookie_file)
+    return
+  endif
+
+  let quote = &shellxquote == '"' ?  "'" : '"'
+  if !filereadable(cookie_file)
+    let password = inputsecret('Password:')
+    if len(password) == 0
+      echo 'Canceled'
+      return
+    endif
+    let url = 'https://gist.github.com/login?return_to=gist'
+    let res = system('curl -L -s '.g:gist_curl_options.' -c '.quote.cookie_file.quote.' '.quote.url.quote)
+    let token = substitute(res, '^.* name="authenticity_token" type="hidden" value="\([^"]\+\)".*$', '\1', '')
+
+    let query = [
+      \ 'authenticity_token=%s',
+      \ 'login=%s',
+      \ 'password=%s',
+      \ 'return_to=gist',
+      \ 'commit=Log+in',
+      \ ]
+    let squery = printf(join(query, '&'),
+      \ s:encodeURIComponent(token),
+      \ s:encodeURIComponent(a:user),
+      \ s:encodeURIComponent(password))
+    unlet query
+
+    let file = tempname()
+    let command = 'curl -s '.g:gist_curl_options.' -i'
+    let command .= ' -b '.quote.cookie_file.quote
+    let command .= ' -c '.quote.cookie_file.quote
+    let command .= ' '.quote.'https://gist.github.com/session'.quote
+    let command .= ' -d @' . quote.file.quote
+    call writefile([squery], file)
+    let res = system(command)
+    call delete(file)
+    let res = matchstr(split(res, '\(\r\?\n\|\r\n\?\)'), '^Location: ')
+    let res = substitute(res, '^[^:]\+: ', '', '')
+    if len(res) == 0
+      call delete(cookie_file)
+      return ''
+    endif
+  endif
+  let command = 'curl -s '.g:gist_curl_options.' -i '.a:opt
+  if len(a:param)
+    let command .= ' -d '.quote.a:param.quote
+  endif
+  let command .= ' -b '.quote.cookie_file.quote
+  let command .= ' '.quote.a:url.quote
+  let res = iconv(system(command), "utf-8", &encoding)
+  let pos = stridx(res, "\r\n\r\n")
+  if pos != -1
+    let content = res[pos+4:]
+  else
+    let pos = stridx(res, "\n\n")
+    let content = res[pos+2:]
+  endif
+  return {
+  \ "header" : split(res[0:pos], '\r\?\n'),
+  \ "content" : content
+  \}
+endfunction
+
+function! s:GistDelete(user, token, gistid)
+  echon 'Deleting gist... '
+  let res = s:GistGetPage('https://gist.github.com/'.a:gistid, a:user, '', '')
+  if (!len(res)) 
+      echoerr 'Wrong password? no response received from github trying to delete ' . a:gistid
+      return
+  endif
+  let mx = '^.* name="authenticity_token" type="hidden" value="\([^"]\+\)".*$'
+  let token = substitute(matchstr(res.content, mx), mx, '\1', '')
+  if len(token) > 0
+    let res = s:GistGetPage('https://gist.github.com/delete/'.a:gistid, a:user, '_method=delete&authenticity_token='.token, '')
+    if len(res.content) > 0
+      redraw
+      echo 'Done: '
+    else
+      let message = matchstr(res.header, '^Status: ')
+      let message = substitute(message, '^[^:]\+: [0-9]\+ ', '', '')
+      echoerr 'Delete failed: '.message
+    endif
+  else
+    echoerr 'Delete failed'
+  endif
+endfunction
+
+
+" GistPost function:
+"   Post new gist to github
+"
+"   if there is an embedded gist url or gist id in your file,
+"   it will just update it.
+"                                                   -- by c9s
+"
+"   embedded gist url format:
+"
+"       Gist: https://gist.github.com/123123
+"
+"   embedded gist id format:
+"
+"       GistID: 123123
+"
+function! s:GistPost(user, token, content, private)
+
+  " find GistID: in content, then we should just update
+  for l in split(a:content, "\n")
+    if l =~ '\<GistID:'
+      let gistid = matchstr(l, 'GistID:\s*[0-9a-z]\+')
+
+      if strlen(gistid) == 0
+        echohl WarningMsg | echo "GistID error" | echohl None
+        return
+      endif
+      echo "Found GistID: " . gistid
+
+      cal s:GistUpdate(a:user, a:token,  a:content, gistid, '')
+      return
+    elseif l =~ '\<Gist:'
+      let gistid = matchstr(l, 'Gist:\s*https://gist.github.com/[0-9a-z]\+')
+
+      if strlen(gistid) == 0
+        echohl WarningMsg | echo "GistID error" | echohl None
+        return
+      endif
+      echo "Found GistID: " . gistid
+
+      cal s:GistUpdate(a:user, a:token,  a:content, gistid, '')
+      return
+    endif
+  endfor
+
+  let ext = expand('%:e')
+  let ext = len(ext) ? '.'.ext : ''
+  let name = expand('%:t')
+
+  let query = [
+    \ 'file_ext[gistfile1]=%s',
+    \ 'file_name[gistfile1]=%s',
+    \ 'file_contents[gistfile1]=%s',
+    \ ]
+
+  if len(a:user) > 0 && len(a:token) > 0
+    call add(query, 'login=%s')
+    call add(query, 'token=%s')
+  else
+    call add(query, '%.0s%.0s')
+  endif
+
+  if a:private
+    call add(query, 'action_button=private')
+  endif
+  let squery = printf(join(query, '&'),
+    \ s:encodeURIComponent(ext),
+    \ s:encodeURIComponent(name),
+    \ s:encodeURIComponent(a:content),
+    \ s:encodeURIComponent(a:user),
+    \ s:encodeURIComponent(a:token))
+  unlet query
+
+  let file = tempname()
+  call writefile([squery], file)
+  echon 'Posting it to gist... '
+  let quote = &shellxquote == '"' ?  "'" : '"'
+  let url = 'https://gist.github.com/gists'
+  let res = system('curl -i '.g:gist_curl_options.' -d @'.quote.file.quote.' '.url)
+  call delete(file)
+  let headers = split(res, '\(\r\?\n\|\r\n\?\)')
+  let location = matchstr(headers, '^Location: ')
+  let location = substitute(location, '^[^:]\+: ', '', '')
+  if len(location) > 0 && location =~ '^\(http\|https\):\/\/gist\.github\.com\/'
+    redraw
+    echo 'Done: '.location
+  else
+    let message = matchstr(headers, '^Status: ')
+    let message = substitute(message, '^[^:]\+: [0-9]\+ ', '', '')
+    echoerr 'Post failed: '.message
+  endif
+  return location
+endfunction
+
+function! s:GistPostBuffers(user, token, private)
+  let bufnrs = range(1, bufnr("$"))
+  let bn = bufnr('%')
+  let query = []
+  if len(a:user) > 0 && len(a:token) > 0
+    call add(query, 'login=%s')
+    call add(query, 'token=%s')
+  else
+    call add(query, '%.0s%.0s')
+  endif
+  if a:private
+    call add(query, 'action_button=private')
+  endif
+  let squery = printf(join(query, "&"),
+    \ s:encodeURIComponent(a:user),
+    \ s:encodeURIComponent(a:token)) . '&'
+
+  let query = [
+    \ 'file_ext[gistfile]=%s',
+    \ 'file_name[gistfile]=%s',
+    \ 'file_contents[gistfile]=%s',
+    \ ]
+  let format = join(query, "&") . '&'
+
+  let index = 1
+  for bufnr in bufnrs
+    if !bufexists(bufnr) || buflisted(bufnr) == 0
+      continue
+    endif
+    echo "Creating gist content".index."... "
+    silent! exec "buffer! ".bufnr
+    let content = join(getline(1, line('$')), "\n")
+    let ext = expand('%:e')
+    let ext = len(ext) ? '.'.ext : ''
+    let name = expand('%:t')
+    let squery .= printf(substitute(format, 'gistfile', 'gistfile'.index, 'g'),
+      \ s:encodeURIComponent(ext),
+      \ s:encodeURIComponent(name),
+      \ s:encodeURIComponent(content))
+    let index = index + 1
+  endfor
+  silent! exec "buffer! ".bn
+
+  let file = tempname()
+  call writefile([squery], file)
+  echo "Posting it to gist... "
+  let quote = &shellxquote == '"' ?  "'" : '"'
+  let url = 'https://gist.github.com/gists'
+  let res = system('curl -i '.g:gist_curl_options.' -d @'.quote.file.quote.' '.url)
+  call delete(file)
+  let res = matchstr(split(res, '\(\r\?\n\|\r\n\?\)'), '^Location: ')
+  let res = substitute(res, '^.*: ', '', '')
+  if len(res) > 0 && res =~ '^\(http\|https\):\/\/gist\.github\.com\/'
+    redraw
+    echo 'Done: '.res
+  else
+    echoerr 'Post failed'
+  endif
+  return res
+endfunction
+
+function! Gist(line1, line2, ...)
+  if !exists('g:github_user')
+    let g:github_user = substitute(system('git config --global github.user'), "\n", '', '')
+    if strlen(g:github_user) == 0
+      let g:github_user = $GITHUB_USER
+    end
+  endif
+  if !exists('g:github_token')
+    let g:github_token = substitute(system('git config --global github.token'), "\n", '', '')
+    if strlen(g:github_token) == 0
+      let g:github_token = $GITHUB_TOKEN
+    end
+  endif
+  if strlen(g:github_user) == 0 || strlen(g:github_token) == 0
+    echoerr "You have no setting for github."
+    echohl WarningMsg
+    echo "git config --global github.user  your-name"
+    echo "git config --global github.token your-token"
+    echo "or set g:github_user and g:github_token in your vimrc"
+    echo "or set shell env vars GITHUB_USER and GITHUB_TOKEN"
+    echohl None
+    return 0
+  end
+
+  let bufname = bufname("%")
+  let user = g:github_user
+  let token = g:github_token
+  let gistid = ''
+  let gistls = ''
+  let gistnm = ''
+  let private = g:gist_private
+  let multibuffer = 0
+  let clipboard = 0
+  let deletepost = 0
+  let editpost = 0
+  let listmx = '^\(-l\|--list\)\s*\([^\s]\+\)\?$'
+  let bufnamemx = '^' . s:bufprefix .'\([0-9a-f]\+\)$'
+
+  let args = (a:0 > 0) ? split(a:1, ' ') : []
+  for arg in args
+    if arg =~ '^\(-la\|--listall\)$\C'
+      let gistls = '-all'
+    elseif arg =~ '^\(-l\|--list\)$\C'
+      if g:gist_show_privates
+        let gistls = 'mine'
+      else
+        let gistls = g:github_user
+      endif
+    elseif arg == '--abandon\C'
+      call s:GistGetPage('', '', '', '')
+      return
+    elseif arg =~ '^\(-m\|--multibuffer\)$\C'
+      let multibuffer = 1
+    elseif arg =~ '^\(-p\|--private\)$\C'
+      let private = 1
+    elseif arg =~ '^\(-P\|--public\)$\C'
+      let private = 0
+    elseif arg =~ '^\(-a\|--anonymous\)$\C'
+      let user = ''
+      let token = ''
+    elseif arg =~ '^\(-c\|--clipboard\)$\C'
+      let clipboard = 1
+    elseif arg =~ '^\(-d\|--delete\)$\C' && bufname =~ bufnamemx
+      let deletepost = 1
+      let gistid = substitute(bufname, bufnamemx, '\1', '')
+    elseif arg =~ '^\(-e\|--edit\)$\C' && bufname =~ bufnamemx
+      let editpost = 1
+      let gistid = substitute(bufname, bufnamemx, '\1', '')
+    elseif arg =~ '^\(-f\|--fork\)$\C' && bufname =~ bufnamemx
+      let gistid = substitute(bufname, bufnamemx, '\1', '')
+      let res = s:GistGetPage("https://gist.github.com/fork/".gistid, g:github_user, '', '')
+      let loc = filter(res.header, 'v:val =~ "^Location:"')[0]
+      let loc = substitute(loc, '^[^:]\+: ', '', '')
+      let mx = '^https://gist.github.com/\([0-9a-z]\+\)$'
+      if loc =~ mx
+        let gistid = substitute(loc, mx, '\1', '')
+      else
+        echoerr 'Fork failed'
+        return
+      endif
+    elseif arg !~ '^-' && len(gistnm) == 0
+      if editpost == 1 || deletepost == 1
+        let gistnm = arg
+      elseif len(gistls) > 0 && arg != '^\w\+$\C'
+        let gistls = arg
+      elseif arg =~ '^[0-9a-z]\+$\C'
+        let gistid = arg
+      else
+        echoerr 'Invalid arguments'
+        unlet args
+        return 0
+      endif
+    elseif len(arg) > 0
+      echoerr 'Invalid arguments'
+      unlet args
+      return 0
+    endif
+  endfor
+  unlet args
+  "echo "gistid=".gistid
+  "echo "gistls=".gistls
+  "echo "gistnm=".gistnm
+  "echo "private=".private
+  "echo "clipboard=".clipboard
+  "echo "editpost=".editpost
+  "echo "deletepost=".deletepost
+
+  if len(gistls) > 0
+    call s:GistList(user, token, gistls, 1)
+  elseif len(gistid) > 0 && editpost == 0 && deletepost == 0
+    call s:GistGet(user, token, gistid, clipboard)
+  else
+    let url = ''
+    if multibuffer == 1
+      let url = s:GistPostBuffers(user, token, private)
+    else
+      let content = join(getline(a:line1, a:line2), "\n")
+      if editpost == 1
+        let url = s:GistUpdate(user, token, content, gistid, gistnm)
+      elseif deletepost == 1
+        call s:GistDelete(user, token, gistid)
+      else
+        let url = s:GistPost(user, token, content, private)
+      endif
+    endif
+    if len(url) > 0
+      if g:gist_open_browser_after_post
+        let cmd = substitute(g:gist_browser_command, '%URL%', url, 'g')
+        if cmd =~ '^!'
+          silent! exec cmd
+        elseif cmd =~ '^:[A-Z]'
+          exec cmd
+        else
+          call system(cmd)
+        endif
+      endif
+      if g:gist_put_url_to_clipboard_after_post > 0
+        if g:gist_put_url_to_clipboard_after_post == 2
+          let url = url . "\n"
+        endif
+        if exists('g:gist_clip_command')
+          call system(g:gist_clip_command, url)
+        elseif has('unix') && !has('xterm_clipboard')
+          let @" = url
+        else
+          let @+ = url
+        endif
+      endif
+    endif
+  endif
+  return 1
+endfunction
+
+command! -nargs=? -range=% Gist :call Gist(<line1>, <line2>, <f-args>)
+" vim:set et:

+ 38 - 0
salamander.remote/hammer.vim

@@ -0,0 +1,38 @@
+if has('ruby')
+  let g:HammerLocation = fnamemodify(expand("<sfile>"), ":p:h")
+
+  ruby $LOAD_PATH.unshift Vim.evaluate('g:HammerLocation')
+  ruby require 'rubygems'
+  ruby require 'github/markup'
+  ruby require 'lib/hammer'
+  ruby require 'lib/hammer/env'
+  ruby require 'lib/vim/improvedbuffer'
+  ruby require 'erb'
+
+  function! Hammer()
+  ruby << RUBY
+    buffer = Vim::Buffer.current.extend Vim::ImprovedBuffer
+
+    if GitHub::Markup.can_render? buffer.basename
+      File.open File.join(Hammer::ENV.directory, "#{buffer.basename}.html"), 'w' do |f|
+        f.write Hammer.render { GitHub::Markup.render(buffer.basename, buffer[1..-1]) }
+      end
+
+      Vim.command "silent ! #{Hammer::ENV.browser} #{File.join Hammer::ENV.directory, buffer.basename}.html"
+      Vim.command "redraw!"
+    elsif buffer.extname =~ /^\.(xhtml|html)$/
+      Vim.command "silent ! #{Hammer::ENV.browser} #{buffer.name}"
+      Vim.command "redraw!"
+    else
+      Vim.message "It is not possible to render #{buffer.extname} files. Missing dependency?" 
+    end
+RUBY
+  endfunction
+
+else
+  function! Hammer()
+    echo "Sorry, hammer.vim requires vim to be built with Ruby support"
+  endfunction
+end
+
+:command! Hammer :call Hammer()

+ 4546 - 0
salamander.remote/taglist.vim

@@ -0,0 +1,4546 @@
+" File: taglist.vim
+" Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
+" Version: 4.5
+" Last Modified: September 21, 2007
+" Copyright: Copyright (C) 2002-2007 Yegappan Lakshmanan
+"            Permission is hereby granted to use and distribute this code,
+"            with or without modifications, provided that this copyright
+"            notice is copied with it. Like anything else that's free,
+"            taglist.vim is provided *as is* and comes with no warranty of any
+"            kind, either expressed or implied. In no event will the copyright
+"            holder be liable for any damamges resulting from the use of this
+"            software.
+"
+" The "Tag List" plugin is a source code browser plugin for Vim and provides
+" an overview of the structure of the programming language files and allows
+" you to efficiently browse through source code files for different
+" programming languages.  You can visit the taglist plugin home page for more
+" information:
+"
+"       http://vim-taglist.sourceforge.net
+"
+" You can subscribe to the taglist mailing list to post your questions
+" or suggestions for improvement or to report bugs. Visit the following
+" page for subscribing to the mailing list:
+"
+"       http://groups.yahoo.com/group/taglist/
+"
+" For more information about using this plugin, after installing the
+" taglist plugin, use the ":help taglist" command.
+"
+" Installation
+" ------------
+" 1. Download the taglist.zip file and unzip the files to the $HOME/.vim
+"    or the $HOME/vimfiles or the $VIM/vimfiles directory. This should
+"    unzip the following two files (the directory structure should be
+"    preserved):
+"
+"       plugin/taglist.vim - main taglist plugin file
+"       doc/taglist.txt    - documentation (help) file
+"
+"    Refer to the 'add-plugin', 'add-global-plugin' and 'runtimepath'
+"    Vim help pages for more details about installing Vim plugins.
+" 2. Change to the $HOME/.vim/doc or $HOME/vimfiles/doc or
+"    $VIM/vimfiles/doc directory, start Vim and run the ":helptags ."
+"    command to process the taglist help file.
+" 3. If the exuberant ctags utility is not present in your PATH, then set the
+"    Tlist_Ctags_Cmd variable to point to the location of the exuberant ctags
+"    utility (not to the directory) in the .vimrc file.
+" 4. If you are running a terminal/console version of Vim and the
+"    terminal doesn't support changing the window width then set the
+"    'Tlist_Inc_Winwidth' variable to 0 in the .vimrc file.
+" 5. Restart Vim.
+" 6. You can now use the ":TlistToggle" command to open/close the taglist
+"    window. You can use the ":help taglist" command to get more
+"    information about using the taglist plugin.
+"
+" ****************** Do not modify after this line ************************
+
+" Line continuation used here
+let s:cpo_save = &cpo
+set cpo&vim
+
+if !exists('loaded_taglist')
+    " First time loading the taglist plugin
+    "
+    " To speed up the loading of Vim, the taglist plugin uses autoload
+    " mechanism to load the taglist functions.
+    " Only define the configuration variables, user commands and some
+    " auto-commands and finish sourcing the file
+
+    " The taglist plugin requires the built-in Vim system() function. If this
+    " function is not available, then don't load the plugin.
+    if !exists('*system')
+        echomsg 'Taglist: Vim system() built-in function is not available. ' .
+                    \ 'Plugin is not loaded.'
+        let loaded_taglist = 'no'
+        let &cpo = s:cpo_save
+        finish
+    endif
+
+    " Location of the exuberant ctags tool
+    if !exists('Tlist_Ctags_Cmd')
+        if executable('exuberant-ctags')
+            " On Debian Linux, exuberant ctags is installed
+            " as exuberant-ctags
+            let Tlist_Ctags_Cmd = 'exuberant-ctags'
+        elseif executable('exctags')
+            " On Free-BSD, exuberant ctags is installed as exctags
+            let Tlist_Ctags_Cmd = 'exctags'
+        elseif executable('ctags')
+            let Tlist_Ctags_Cmd = 'ctags'
+        elseif executable('ctags.exe')
+            let Tlist_Ctags_Cmd = 'ctags.exe'
+        elseif executable('tags')
+            let Tlist_Ctags_Cmd = 'tags'
+        else
+            echomsg 'Taglist: Exuberant ctags (http://ctags.sf.net) ' .
+                        \ 'not found in PATH. Plugin is not loaded.'
+            " Skip loading the plugin
+            let loaded_taglist = 'no'
+            let &cpo = s:cpo_save
+            finish
+        endif
+    endif
+
+
+    " Automatically open the taglist window on Vim startup
+    if !exists('Tlist_Auto_Open')
+        let Tlist_Auto_Open = 0
+    endif
+
+    " When the taglist window is toggle opened, move the cursor to the
+    " taglist window
+    if !exists('Tlist_GainFocus_On_ToggleOpen')
+        let Tlist_GainFocus_On_ToggleOpen = 0
+    endif
+
+    " Process files even when the taglist window is not open
+    if !exists('Tlist_Process_File_Always')
+        let Tlist_Process_File_Always = 0
+    endif
+
+    if !exists('Tlist_Show_Menu')
+        let Tlist_Show_Menu = 0
+    endif
+
+    " Tag listing sort type - 'name' or 'order'
+    if !exists('Tlist_Sort_Type')
+        let Tlist_Sort_Type = 'order'
+    endif
+
+    " Tag listing window split (horizontal/vertical) control
+    if !exists('Tlist_Use_Horiz_Window')
+        let Tlist_Use_Horiz_Window = 0
+    endif
+
+    " Open the vertically split taglist window on the left or on the right
+    " side.  This setting is relevant only if Tlist_Use_Horiz_Window is set to
+    " zero (i.e.  only for vertically split windows)
+    if !exists('Tlist_Use_Right_Window')
+        let Tlist_Use_Right_Window = 0
+    endif
+
+    " Increase Vim window width to display vertically split taglist window.
+    " For MS-Windows version of Vim running in a MS-DOS window, this must be
+    " set to 0 otherwise the system may hang due to a Vim limitation.
+    if !exists('Tlist_Inc_Winwidth')
+        if (has('win16') || has('win95')) && !has('gui_running')
+            let Tlist_Inc_Winwidth = 0
+        else
+            let Tlist_Inc_Winwidth = 1
+        endif
+    endif
+
+    " Vertically split taglist window width setting
+    if !exists('Tlist_WinWidth')
+        let Tlist_WinWidth = 30
+    endif
+
+    " Horizontally split taglist window height setting
+    if !exists('Tlist_WinHeight')
+        let Tlist_WinHeight = 10
+    endif
+
+    " Display tag prototypes or tag names in the taglist window
+    if !exists('Tlist_Display_Prototype')
+        let Tlist_Display_Prototype = 0
+    endif
+
+    " Display tag scopes in the taglist window
+    if !exists('Tlist_Display_Tag_Scope')
+        let Tlist_Display_Tag_Scope = 1
+    endif
+
+    " Use single left mouse click to jump to a tag. By default this is disabled.
+    " Only double click using the mouse will be processed.
+    if !exists('Tlist_Use_SingleClick')
+        let Tlist_Use_SingleClick = 0
+    endif
+
+    " Control whether additional help is displayed as part of the taglist or
+    " not.  Also, controls whether empty lines are used to separate the tag
+    " tree.
+    if !exists('Tlist_Compact_Format')
+        let Tlist_Compact_Format = 0
+    endif
+
+    " Exit Vim if only the taglist window is currently open. By default, this is
+    " set to zero.
+    if !exists('Tlist_Exit_OnlyWindow')
+        let Tlist_Exit_OnlyWindow = 0
+    endif
+
+    " Automatically close the folds for the non-active files in the taglist
+    " window
+    if !exists('Tlist_File_Fold_Auto_Close')
+        let Tlist_File_Fold_Auto_Close = 0
+    endif
+
+    " Close the taglist window when a tag is selected
+    if !exists('Tlist_Close_On_Select')
+        let Tlist_Close_On_Select = 0
+    endif
+
+    " Automatically update the taglist window to display tags for newly
+    " edited files
+    if !exists('Tlist_Auto_Update')
+        let Tlist_Auto_Update = 1
+    endif
+
+    " Automatically highlight the current tag
+    if !exists('Tlist_Auto_Highlight_Tag')
+        let Tlist_Auto_Highlight_Tag = 1
+    endif
+    
+    " Automatically highlight the current tag on entering a buffer
+    if !exists('Tlist_Highlight_Tag_On_BufEnter')
+        let Tlist_Highlight_Tag_On_BufEnter = 1
+    endif
+
+    " Enable fold column to display the folding for the tag tree
+    if !exists('Tlist_Enable_Fold_Column')
+        let Tlist_Enable_Fold_Column = 1
+    endif
+
+    " Display the tags for only one file in the taglist window
+    if !exists('Tlist_Show_One_File')
+        let Tlist_Show_One_File = 0
+    endif
+
+    if !exists('Tlist_Max_Submenu_Items')
+        let Tlist_Max_Submenu_Items = 20
+    endif
+
+    if !exists('Tlist_Max_Tag_Length')
+        let Tlist_Max_Tag_Length = 10
+    endif
+
+    " Do not change the name of the taglist title variable. The winmanager
+    " plugin relies on this name to determine the title for the taglist
+    " plugin.
+    let TagList_title = "__Tag_List__"
+
+    " Taglist debug messages
+    let s:tlist_msg = ''
+
+    " Define the taglist autocommand to automatically open the taglist window
+    " on Vim startup
+    if g:Tlist_Auto_Open
+        autocmd VimEnter * nested call s:Tlist_Window_Check_Auto_Open()
+    endif
+
+    " Refresh the taglist
+    if g:Tlist_Process_File_Always
+        autocmd BufEnter * call s:Tlist_Refresh()
+    endif
+
+    if g:Tlist_Show_Menu
+        autocmd GUIEnter * call s:Tlist_Menu_Init()
+    endif
+
+    " When the taglist buffer is created when loading a Vim session file,
+    " the taglist buffer needs to be initialized. The BufFilePost event
+    " is used to handle this case.
+    autocmd BufFilePost __Tag_List__ call s:Tlist_Vim_Session_Load()
+
+    " Define the user commands to manage the taglist window
+    command! -nargs=0 -bar TlistToggle call s:Tlist_Window_Toggle()
+    command! -nargs=0 -bar TlistOpen call s:Tlist_Window_Open()
+    " For backwards compatiblity define the Tlist command
+    command! -nargs=0 -bar Tlist TlistToggle
+    command! -nargs=+ -complete=file TlistAddFiles
+                \  call s:Tlist_Add_Files(<f-args>)
+    command! -nargs=+ -complete=dir TlistAddFilesRecursive
+                \ call s:Tlist_Add_Files_Recursive(<f-args>)
+    command! -nargs=0 -bar TlistClose call s:Tlist_Window_Close()
+    command! -nargs=0 -bar TlistUpdate call s:Tlist_Update_Current_File()
+    command! -nargs=0 -bar TlistHighlightTag call s:Tlist_Window_Highlight_Tag(
+                        \ fnamemodify(bufname('%'), ':p'), line('.'), 2, 1)
+    " For backwards compatiblity define the TlistSync command
+    command! -nargs=0 -bar TlistSync TlistHighlightTag
+    command! -nargs=* -complete=buffer TlistShowPrototype
+                \ echo Tlist_Get_Tag_Prototype_By_Line(<f-args>)
+    command! -nargs=* -complete=buffer TlistShowTag
+                \ echo Tlist_Get_Tagname_By_Line(<f-args>)
+    command! -nargs=* -complete=file TlistSessionLoad
+                \ call s:Tlist_Session_Load(<q-args>)
+    command! -nargs=* -complete=file TlistSessionSave
+                \ call s:Tlist_Session_Save(<q-args>)
+    command! -bar TlistLock let Tlist_Auto_Update=0
+    command! -bar TlistUnlock let Tlist_Auto_Update=1
+
+    " Commands for enabling/disabling debug and to display debug messages
+    command! -nargs=? -complete=file -bar TlistDebug
+                \ call s:Tlist_Debug_Enable(<q-args>)
+    command! -nargs=0 -bar TlistUndebug  call s:Tlist_Debug_Disable()
+    command! -nargs=0 -bar TlistMessages call s:Tlist_Debug_Show()
+
+    " Define autocommands to autoload the taglist plugin when needed.
+
+    " Trick to get the current script ID
+    map <SID>xx <SID>xx
+    let s:tlist_sid = substitute(maparg('<SID>xx'), '<SNR>\(\d\+_\)xx$',
+                                \ '\1', '')
+    unmap <SID>xx
+
+    exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_* source ' .
+                \ escape(expand('<sfile>'), ' ')
+    exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_Window_* source ' .
+                \ escape(expand('<sfile>'), ' ')
+    exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_Menu_* source ' .
+                \ escape(expand('<sfile>'), ' ')
+    exe 'autocmd FuncUndefined Tlist_* source ' .
+                \ escape(expand('<sfile>'), ' ')
+    exe 'autocmd FuncUndefined TagList_* source ' .
+                \ escape(expand('<sfile>'), ' ')
+
+    let loaded_taglist = 'fast_load_done'
+
+    if g:Tlist_Show_Menu && has('gui_running')
+        call s:Tlist_Menu_Init()
+    endif
+
+    " restore 'cpo'
+    let &cpo = s:cpo_save
+    finish
+endif
+
+if !exists('s:tlist_sid')
+    " Two or more versions of taglist plugin are installed. Don't
+    " load this version of the plugin.
+    finish
+endif
+
+unlet! s:tlist_sid
+
+if loaded_taglist != 'fast_load_done'
+    " restore 'cpo'
+    let &cpo = s:cpo_save
+    finish
+endif
+
+" Taglist plugin functionality is available
+let loaded_taglist = 'available'
+
+"------------------- end of user configurable options --------------------
+
+" Default language specific settings for supported file types and tag types
+"
+" Variable name format:
+"
+"       s:tlist_def_{vim_ftype}_settings
+" 
+" vim_ftype - Filetype detected by Vim
+"
+" Value format:
+"
+"       <ctags_ftype>;<flag>:<name>;<flag>:<name>;...
+"
+" ctags_ftype - File type supported by exuberant ctags
+" flag        - Flag supported by exuberant ctags to generate a tag type
+" name        - Name of the tag type used in the taglist window to display the
+"               tags of this type
+"
+
+" assembly language
+let s:tlist_def_asm_settings = 'asm;d:define;l:label;m:macro;t:type'
+
+" aspperl language
+let s:tlist_def_aspperl_settings = 'asp;f:function;s:sub;v:variable'
+
+" aspvbs language
+let s:tlist_def_aspvbs_settings = 'asp;f:function;s:sub;v:variable'
+
+" awk language
+let s:tlist_def_awk_settings = 'awk;f:function'
+
+" beta language
+let s:tlist_def_beta_settings = 'beta;f:fragment;s:slot;v:pattern'
+
+" c language
+let s:tlist_def_c_settings = 'c;d:macro;g:enum;s:struct;u:union;t:typedef;' .
+                           \ 'v:variable;f:function'
+
+" c++ language
+let s:tlist_def_cpp_settings = 'c++;n:namespace;v:variable;d:macro;t:typedef;' .
+                             \ 'c:class;g:enum;s:struct;u:union;f:function'
+
+" c# language
+let s:tlist_def_cs_settings = 'c#;d:macro;t:typedef;n:namespace;c:class;' .
+                             \ 'E:event;g:enum;s:struct;i:interface;' .
+                             \ 'p:properties;m:method'
+
+" cobol language
+let s:tlist_def_cobol_settings = 'cobol;d:data;f:file;g:group;p:paragraph;' .
+                               \ 'P:program;s:section'
+
+" eiffel language
+let s:tlist_def_eiffel_settings = 'eiffel;c:class;f:feature'
+
+" erlang language
+let s:tlist_def_erlang_settings = 'erlang;d:macro;r:record;m:module;f:function'
+
+" expect (same as tcl) language
+let s:tlist_def_expect_settings = 'tcl;c:class;f:method;p:procedure'
+
+" fortran language
+let s:tlist_def_fortran_settings = 'fortran;p:program;b:block data;' .
+                    \ 'c:common;e:entry;i:interface;k:type;l:label;m:module;' .
+                    \ 'n:namelist;t:derived;v:variable;f:function;s:subroutine'
+
+" HTML language
+let s:tlist_def_html_settings = 'html;a:anchor;f:javascript function'
+
+" java language
+let s:tlist_def_java_settings = 'java;p:package;c:class;i:interface;' .
+                              \ 'f:field;m:method'
+
+" javascript language
+let s:tlist_def_javascript_settings = 'javascript;f:function'
+
+" lisp language
+let s:tlist_def_lisp_settings = 'lisp;f:function'
+
+" lua language
+let s:tlist_def_lua_settings = 'lua;f:function'
+
+" makefiles
+let s:tlist_def_make_settings = 'make;m:macro'
+
+" pascal language
+let s:tlist_def_pascal_settings = 'pascal;f:function;p:procedure'
+
+" perl language
+let s:tlist_def_perl_settings = 'perl;c:constant;l:label;p:package;s:subroutine'
+
+" php language
+let s:tlist_def_php_settings = 'php;c:class;d:constant;v:variable;f:function'
+
+" python language
+let s:tlist_def_python_settings = 'python;c:class;m:member;f:function'
+
+" rexx language
+let s:tlist_def_rexx_settings = 'rexx;s:subroutine'
+
+" ruby language
+let s:tlist_def_ruby_settings = 'ruby;c:class;f:method;F:function;' .
+                              \ 'm:singleton method'
+
+" scheme language
+let s:tlist_def_scheme_settings = 'scheme;s:set;f:function'
+
+" shell language
+let s:tlist_def_sh_settings = 'sh;f:function'
+
+" C shell language
+let s:tlist_def_csh_settings = 'sh;f:function'
+
+" Z shell language
+let s:tlist_def_zsh_settings = 'sh;f:function'
+
+" slang language
+let s:tlist_def_slang_settings = 'slang;n:namespace;f:function'
+
+" sml language
+let s:tlist_def_sml_settings = 'sml;e:exception;c:functor;s:signature;' .
+                             \ 'r:structure;t:type;v:value;f:function'
+
+" sql language
+let s:tlist_def_sql_settings = 'sql;c:cursor;F:field;P:package;r:record;' .
+            \ 's:subtype;t:table;T:trigger;v:variable;f:function;p:procedure'
+
+" tcl language
+let s:tlist_def_tcl_settings = 'tcl;c:class;f:method;m:method;p:procedure'
+
+" vera language
+let s:tlist_def_vera_settings = 'vera;c:class;d:macro;e:enumerator;' .
+                                \ 'f:function;g:enum;m:member;p:program;' .
+                                \ 'P:prototype;t:task;T:typedef;v:variable;' .
+                                \ 'x:externvar'
+
+"verilog language
+let s:tlist_def_verilog_settings = 'verilog;m:module;c:constant;P:parameter;' .
+            \ 'e:event;r:register;t:task;w:write;p:port;v:variable;f:function'
+
+" vim language
+let s:tlist_def_vim_settings = 'vim;a:autocmds;v:variable;f:function'
+
+" yacc language
+let s:tlist_def_yacc_settings = 'yacc;l:label'
+
+"------------------- end of language specific options --------------------
+
+" Vim window size is changed by the taglist plugin or not
+let s:tlist_winsize_chgd = -1
+" Taglist window is maximized or not
+let s:tlist_win_maximized = 0
+" Name of files in the taglist
+let s:tlist_file_names=''
+" Number of files in the taglist
+let s:tlist_file_count = 0
+" Number of filetypes supported by taglist
+let s:tlist_ftype_count = 0
+" Is taglist part of other plugins like winmanager or cream?
+let s:tlist_app_name = "none"
+" Are we displaying brief help text
+let s:tlist_brief_help = 1
+" List of files removed on user request
+let s:tlist_removed_flist = ""
+" Index of current file displayed in the taglist window
+let s:tlist_cur_file_idx = -1
+" Taglist menu is empty or not
+let s:tlist_menu_empty = 1
+
+" An autocommand is used to refresh the taglist window when entering any
+" buffer. We don't want to refresh the taglist window if we are entering the
+" file window from one of the taglist functions. The 'Tlist_Skip_Refresh'
+" variable is used to skip the refresh of the taglist window and is set
+" and cleared appropriately.
+let s:Tlist_Skip_Refresh = 0
+
+" Tlist_Window_Display_Help()
+function! s:Tlist_Window_Display_Help()
+    if s:tlist_app_name == "winmanager"
+        " To handle a bug in the winmanager plugin, add a space at the
+        " last line
+        call setline('$', ' ')
+    endif
+
+    if s:tlist_brief_help
+        " Add the brief help
+        call append(0, '" Press <F1> to display help text')
+    else
+        " Add the extensive help
+        call append(0, '" <enter> : Jump to tag definition')
+        call append(1, '" o : Jump to tag definition in new window')
+        call append(2, '" p : Preview the tag definition')
+        call append(3, '" <space> : Display tag prototype')
+        call append(4, '" u : Update tag list')
+        call append(5, '" s : Select sort field')
+        call append(6, '" d : Remove file from taglist')
+        call append(7, '" x : Zoom-out/Zoom-in taglist window')
+        call append(8, '" + : Open a fold')
+        call append(9, '" - : Close a fold')
+        call append(10, '" * : Open all folds')
+        call append(11, '" = : Close all folds')
+        call append(12, '" [[ : Move to the start of previous file')
+        call append(13, '" ]] : Move to the start of next file')
+        call append(14, '" q : Close the taglist window')
+        call append(15, '" <F1> : Remove help text')
+    endif
+endfunction
+
+" Tlist_Window_Toggle_Help_Text()
+" Toggle taglist plugin help text between the full version and the brief
+" version
+function! s:Tlist_Window_Toggle_Help_Text()
+    if g:Tlist_Compact_Format
+        " In compact display mode, do not display help
+        return
+    endif
+
+    " Include the empty line displayed after the help text
+    let brief_help_size = 1
+    let full_help_size = 16
+
+    setlocal modifiable
+
+    " Set report option to a huge value to prevent informational messages
+    " while deleting the lines
+    let old_report = &report
+    set report=99999
+
+    " Remove the currently highlighted tag. Otherwise, the help text
+    " might be highlighted by mistake
+    match none
+
+    " Toggle between brief and full help text
+    if s:tlist_brief_help
+        let s:tlist_brief_help = 0
+
+        " Remove the previous help
+        exe '1,' . brief_help_size . ' delete _'
+
+        " Adjust the start/end line numbers for the files
+        call s:Tlist_Window_Update_Line_Offsets(0, 1, full_help_size - brief_help_size)
+    else
+        let s:tlist_brief_help = 1
+
+        " Remove the previous help
+        exe '1,' . full_help_size . ' delete _'
+
+        " Adjust the start/end line numbers for the files
+        call s:Tlist_Window_Update_Line_Offsets(0, 0, full_help_size - brief_help_size)
+    endif
+
+    call s:Tlist_Window_Display_Help()
+
+    " Restore the report option
+    let &report = old_report
+
+    setlocal nomodifiable
+endfunction
+
+" Taglist debug support
+let s:tlist_debug = 0
+
+" File for storing the debug messages
+let s:tlist_debug_file = ''
+
+" Tlist_Debug_Enable
+" Enable logging of taglist debug messages.
+function! s:Tlist_Debug_Enable(...)
+    let s:tlist_debug = 1
+
+    " Check whether a valid file name is supplied.
+    if a:1 != ''
+        let s:tlist_debug_file = fnamemodify(a:1, ':p')
+
+        " Empty the log file
+        exe 'redir! > ' . s:tlist_debug_file
+        redir END
+
+        " Check whether the log file is present/created
+        if !filewritable(s:tlist_debug_file)
+            call s:Tlist_Warning_Msg('Taglist: Unable to create log file '
+                        \ . s:tlist_debug_file)
+            let s:tlist_debug_file = ''
+        endif
+    endif
+endfunction
+
+" Tlist_Debug_Disable
+" Disable logging of taglist debug messages.
+function! s:Tlist_Debug_Disable(...)
+    let s:tlist_debug = 0
+    let s:tlist_debug_file = ''
+endfunction
+
+" Tlist_Debug_Show
+" Display the taglist debug messages in a new window
+function! s:Tlist_Debug_Show()
+    if s:tlist_msg == ''
+        call s:Tlist_Warning_Msg('Taglist: No debug messages')
+        return
+    endif
+
+    " Open a new window to display the taglist debug messages
+    new taglist_debug.txt
+    " Delete all the lines (if the buffer already exists)
+    silent! %delete _
+    " Add the messages
+    silent! put =s:tlist_msg
+    " Move the cursor to the first line
+    normal! gg
+endfunction
+
+" Tlist_Log_Msg
+" Log the supplied debug message along with the time
+function! s:Tlist_Log_Msg(msg)
+    if s:tlist_debug
+        if s:tlist_debug_file != ''
+            exe 'redir >> ' . s:tlist_debug_file
+            silent echon strftime('%H:%M:%S') . ': ' . a:msg . "\n"
+            redir END
+        else
+            " Log the message into a variable
+            " Retain only the last 3000 characters
+            let len = strlen(s:tlist_msg)
+            if len > 3000
+                let s:tlist_msg = strpart(s:tlist_msg, len - 3000)
+            endif
+            let s:tlist_msg = s:tlist_msg . strftime('%H:%M:%S') . ': ' . 
+                        \ a:msg . "\n"
+        endif
+    endif
+endfunction
+
+" Tlist_Warning_Msg()
+" Display a message using WarningMsg highlight group
+function! s:Tlist_Warning_Msg(msg)
+    echohl WarningMsg
+    echomsg a:msg
+    echohl None
+endfunction
+
+" Last returned file index for file name lookup.
+" Used to speed up file lookup
+let s:tlist_file_name_idx_cache = -1
+
+" Tlist_Get_File_Index()
+" Return the index of the specified filename
+function! s:Tlist_Get_File_Index(fname)
+    if s:tlist_file_count == 0 || a:fname == ''
+        return -1
+    endif
+
+    " If the new filename is same as the last accessed filename, then
+    " return that index
+    if s:tlist_file_name_idx_cache != -1 &&
+                \ s:tlist_file_name_idx_cache < s:tlist_file_count
+        if s:tlist_{s:tlist_file_name_idx_cache}_filename == a:fname
+            " Same as the last accessed file
+            return s:tlist_file_name_idx_cache
+        endif
+    endif
+
+    " First, check whether the filename is present
+    let s_fname = a:fname . "\n"
+    let i = stridx(s:tlist_file_names, s_fname)
+    if i == -1
+        let s:tlist_file_name_idx_cache = -1
+        return -1
+    endif
+
+    " Second, compute the file name index
+    let nl_txt = substitute(strpart(s:tlist_file_names, 0, i), "[^\n]", '', 'g')
+    let s:tlist_file_name_idx_cache = strlen(nl_txt)
+    return s:tlist_file_name_idx_cache
+endfunction
+
+" Last returned file index for line number lookup.
+" Used to speed up file lookup
+let s:tlist_file_lnum_idx_cache = -1
+
+" Tlist_Window_Get_File_Index_By_Linenum()
+" Return the index of the filename present in the specified line number
+" Line number refers to the line number in the taglist window
+function! s:Tlist_Window_Get_File_Index_By_Linenum(lnum)
+    call s:Tlist_Log_Msg('Tlist_Window_Get_File_Index_By_Linenum (' . a:lnum . ')')
+
+    " First try to see whether the new line number is within the range
+    " of the last returned file
+    if s:tlist_file_lnum_idx_cache != -1 &&
+                \ s:tlist_file_lnum_idx_cache < s:tlist_file_count
+        if a:lnum >= s:tlist_{s:tlist_file_lnum_idx_cache}_start &&
+                    \ a:lnum <= s:tlist_{s:tlist_file_lnum_idx_cache}_end
+            return s:tlist_file_lnum_idx_cache
+        endif
+    endif
+
+    let fidx = -1
+
+    if g:Tlist_Show_One_File
+        " Displaying only one file in the taglist window. Check whether
+        " the line is within the tags displayed for that file
+        if s:tlist_cur_file_idx != -1
+            if a:lnum >= s:tlist_{s:tlist_cur_file_idx}_start
+                        \ && a:lnum <= s:tlist_{s:tlist_cur_file_idx}_end
+                let fidx = s:tlist_cur_file_idx
+            endif
+
+        endif
+    else
+        " Do a binary search in the taglist
+        let left = 0
+        let right = s:tlist_file_count - 1
+
+        while left < right
+            let mid = (left + right) / 2
+
+            if a:lnum >= s:tlist_{mid}_start && a:lnum <= s:tlist_{mid}_end
+                let s:tlist_file_lnum_idx_cache = mid
+                return mid
+            endif
+
+            if a:lnum < s:tlist_{mid}_start
+                let right = mid - 1
+            else
+                let left = mid + 1
+            endif
+        endwhile
+
+        if left >= 0 && left < s:tlist_file_count
+                    \ && a:lnum >= s:tlist_{left}_start
+                    \ && a:lnum <= s:tlist_{left}_end
+            let fidx = left
+        endif
+    endif
+
+    let s:tlist_file_lnum_idx_cache = fidx
+
+    return fidx
+endfunction
+
+" Tlist_Exe_Cmd_No_Acmds
+" Execute the specified Ex command after disabling autocommands
+function! s:Tlist_Exe_Cmd_No_Acmds(cmd)
+    let old_eventignore = &eventignore
+    set eventignore=all
+    exe a:cmd
+    let &eventignore = old_eventignore
+endfunction
+
+" Tlist_Skip_File()
+" Check whether tag listing is supported for the specified file
+function! s:Tlist_Skip_File(filename, ftype)
+    " Skip buffers with no names and buffers with filetype not set
+    if a:filename == '' || a:ftype == ''
+        return 1
+    endif
+
+    " Skip files which are not supported by exuberant ctags
+    " First check whether default settings for this filetype are available.
+    " If it is not available, then check whether user specified settings are
+    " available. If both are not available, then don't list the tags for this
+    " filetype
+    let var = 's:tlist_def_' . a:ftype . '_settings'
+    if !exists(var)
+        let var = 'g:tlist_' . a:ftype . '_settings'
+        if !exists(var)
+            return 1
+        endif
+    endif
+
+    " Skip files which are not readable or files which are not yet stored
+    " to the disk
+    if !filereadable(a:filename)
+        return 1
+    endif
+
+    return 0
+endfunction
+
+" Tlist_User_Removed_File
+" Returns 1 if a file is removed by a user from the taglist
+function! s:Tlist_User_Removed_File(filename)
+    return stridx(s:tlist_removed_flist, a:filename . "\n") != -1
+endfunction
+
+" Tlist_Update_Remove_List
+" Update the list of user removed files from the taglist
+" add == 1, add the file to the removed list
+" add == 0, delete the file from the removed list
+function! s:Tlist_Update_Remove_List(filename, add)
+    if a:add
+        let s:tlist_removed_flist = s:tlist_removed_flist . a:filename . "\n"
+    else
+        let idx = stridx(s:tlist_removed_flist, a:filename . "\n")
+        let text_before = strpart(s:tlist_removed_flist, 0, idx)
+        let rem_text = strpart(s:tlist_removed_flist, idx)
+        let next_idx = stridx(rem_text, "\n")
+        let text_after = strpart(rem_text, next_idx + 1)
+
+        let s:tlist_removed_flist = text_before . text_after
+    endif
+endfunction
+
+" Tlist_FileType_Init
+" Initialize the ctags arguments and tag variable for the specified
+" file type
+function! s:Tlist_FileType_Init(ftype)
+    call s:Tlist_Log_Msg('Tlist_FileType_Init (' . a:ftype . ')')
+    " If the user didn't specify any settings, then use the default
+    " ctags args. Otherwise, use the settings specified by the user
+    let var = 'g:tlist_' . a:ftype . '_settings'
+    if exists(var)
+        " User specified ctags arguments
+        let settings = {var} . ';'
+    else
+        " Default ctags arguments
+        let var = 's:tlist_def_' . a:ftype . '_settings'
+        if !exists(var)
+            " No default settings for this file type. This filetype is
+            " not supported
+            return 0
+        endif
+        let settings = s:tlist_def_{a:ftype}_settings . ';'
+    endif
+
+    let msg = 'Taglist: Invalid ctags option setting - ' . settings
+
+    " Format of the option that specifies the filetype and ctags arugments:
+    "
+    "       <language_name>;flag1:name1;flag2:name2;flag3:name3
+    "
+
+    " Extract the file type to pass to ctags. This may be different from the
+    " file type detected by Vim
+    let pos = stridx(settings, ';')
+    if pos == -1
+        call s:Tlist_Warning_Msg(msg)
+        return 0
+    endif
+    let ctags_ftype = strpart(settings, 0, pos)
+    if ctags_ftype == ''
+        call s:Tlist_Warning_Msg(msg)
+        return 0
+    endif
+    " Make sure a valid filetype is supplied. If the user didn't specify a
+    " valid filetype, then the ctags option settings may be treated as the
+    " filetype
+    if ctags_ftype =~ ':'
+        call s:Tlist_Warning_Msg(msg)
+        return 0
+    endif
+
+    " Remove the file type from settings
+    let settings = strpart(settings, pos + 1)
+    if settings == ''
+        call s:Tlist_Warning_Msg(msg)
+        return 0
+    endif
+
+    " Process all the specified ctags flags. The format is
+    " flag1:name1;flag2:name2;flag3:name3
+    let ctags_flags = ''
+    let cnt = 0
+    while settings != ''
+        " Extract the flag
+        let pos = stridx(settings, ':')
+        if pos == -1
+            call s:Tlist_Warning_Msg(msg)
+            return 0
+        endif
+        let flag = strpart(settings, 0, pos)
+        if flag == ''
+            call s:Tlist_Warning_Msg(msg)
+            return 0
+        endif
+        " Remove the flag from settings
+        let settings = strpart(settings, pos + 1)
+
+        " Extract the tag type name
+        let pos = stridx(settings, ';')
+        if pos == -1
+            call s:Tlist_Warning_Msg(msg)
+            return 0
+        endif
+        let name = strpart(settings, 0, pos)
+        if name == ''
+            call s:Tlist_Warning_Msg(msg)
+            return 0
+        endif
+        let settings = strpart(settings, pos + 1)
+
+        let cnt = cnt + 1
+
+        let s:tlist_{a:ftype}_{cnt}_name = flag
+        let s:tlist_{a:ftype}_{cnt}_fullname = name
+        let ctags_flags = ctags_flags . flag
+    endwhile
+
+    let s:tlist_{a:ftype}_ctags_args = '--language-force=' . ctags_ftype .
+                            \ ' --' . ctags_ftype . '-types=' . ctags_flags
+    let s:tlist_{a:ftype}_count = cnt
+    let s:tlist_{a:ftype}_ctags_flags = ctags_flags
+
+    " Save the filetype name
+    let s:tlist_ftype_{s:tlist_ftype_count}_name = a:ftype
+    let s:tlist_ftype_count = s:tlist_ftype_count + 1
+
+    return 1
+endfunction
+
+" Tlist_Detect_Filetype
+" Determine the filetype for the specified file using the filetypedetect
+" autocmd.
+function! s:Tlist_Detect_Filetype(fname)
+    " Ignore the filetype autocommands
+    let old_eventignore = &eventignore
+    set eventignore=FileType
+
+    " Save the 'filetype', as this will be changed temporarily
+    let old_filetype = &filetype
+
+    " Run the filetypedetect group of autocommands to determine
+    " the filetype
+    exe 'doautocmd filetypedetect BufRead ' . a:fname
+
+    " Save the detected filetype
+    let ftype = &filetype
+
+    " Restore the previous state
+    let &filetype = old_filetype
+    let &eventignore = old_eventignore
+
+    return ftype
+endfunction
+
+" Tlist_Get_Buffer_Filetype
+" Get the filetype for the specified buffer
+function! s:Tlist_Get_Buffer_Filetype(bnum)
+    let buf_ft = getbufvar(a:bnum, '&filetype')
+
+    if bufloaded(a:bnum)
+        " For loaded buffers, the 'filetype' is already determined
+        return buf_ft
+    endif
+
+    " For unloaded buffers, if the 'filetype' option is set, return it
+    if buf_ft != ''
+        return buf_ft
+    endif
+
+    " Skip non-existent buffers
+    if !bufexists(a:bnum)
+        return ''
+    endif
+
+    " For buffers whose filetype is not yet determined, try to determine
+    " the filetype
+    let bname = bufname(a:bnum)
+
+    return s:Tlist_Detect_Filetype(bname)
+endfunction
+
+" Tlist_Discard_TagInfo
+" Discard the stored tag information for a file
+function! s:Tlist_Discard_TagInfo(fidx)
+    call s:Tlist_Log_Msg('Tlist_Discard_TagInfo (' .
+                \ s:tlist_{a:fidx}_filename . ')')
+    let ftype = s:tlist_{a:fidx}_filetype
+
+    " Discard information about the tags defined in the file
+    let i = 1
+    while i <= s:tlist_{a:fidx}_tag_count
+        let fidx_i = 's:tlist_' . a:fidx . '_' . i
+        unlet! {fidx_i}_tag
+        unlet! {fidx_i}_tag_name
+        unlet! {fidx_i}_tag_type
+        unlet! {fidx_i}_ttype_idx
+        unlet! {fidx_i}_tag_proto
+        unlet! {fidx_i}_tag_searchpat
+        unlet! {fidx_i}_tag_linenum
+        let i = i + 1
+    endwhile
+
+    let s:tlist_{a:fidx}_tag_count = 0
+
+    " Discard information about tag type groups
+    let i = 1
+    while i <= s:tlist_{ftype}_count
+        let ttype = s:tlist_{ftype}_{i}_name
+        if s:tlist_{a:fidx}_{ttype} != ''
+            let fidx_ttype = 's:tlist_' . a:fidx . '_' . ttype
+            let {fidx_ttype} = ''
+            let {fidx_ttype}_offset = 0
+            let cnt = {fidx_ttype}_count
+            let {fidx_ttype}_count = 0
+            let j = 1
+            while j <= cnt
+                unlet! {fidx_ttype}_{j}
+                let j = j + 1
+            endwhile
+        endif
+        let i = i + 1
+    endwhile
+
+    " Discard the stored menu command also
+    let s:tlist_{a:fidx}_menu_cmd = ''
+endfunction
+
+" Tlist_Window_Update_Line_Offsets
+" Update the line offsets for tags for files starting from start_idx
+" and displayed in the taglist window by the specified offset
+function! s:Tlist_Window_Update_Line_Offsets(start_idx, increment, offset)
+    let i = a:start_idx
+
+    while i < s:tlist_file_count
+        if s:tlist_{i}_visible
+            " Update the start/end line number only if the file is visible
+            if a:increment
+                let s:tlist_{i}_start = s:tlist_{i}_start + a:offset
+                let s:tlist_{i}_end = s:tlist_{i}_end + a:offset
+            else
+                let s:tlist_{i}_start = s:tlist_{i}_start - a:offset
+                let s:tlist_{i}_end = s:tlist_{i}_end - a:offset
+            endif
+        endif
+        let i = i + 1
+    endwhile
+endfunction
+
+" Tlist_Discard_FileInfo
+" Discard the stored information for a file
+function! s:Tlist_Discard_FileInfo(fidx)
+    call s:Tlist_Log_Msg('Tlist_Discard_FileInfo (' .
+                \ s:tlist_{a:fidx}_filename . ')')
+    call s:Tlist_Discard_TagInfo(a:fidx)
+
+    let ftype = s:tlist_{a:fidx}_filetype
+
+    let i = 1
+    while i <= s:tlist_{ftype}_count
+        let ttype = s:tlist_{ftype}_{i}_name
+        unlet! s:tlist_{a:fidx}_{ttype}
+        unlet! s:tlist_{a:fidx}_{ttype}_offset
+        unlet! s:tlist_{a:fidx}_{ttype}_count
+        let i = i + 1
+    endwhile
+
+    unlet! s:tlist_{a:fidx}_filename
+    unlet! s:tlist_{a:fidx}_sort_type
+    unlet! s:tlist_{a:fidx}_filetype
+    unlet! s:tlist_{a:fidx}_mtime
+    unlet! s:tlist_{a:fidx}_start
+    unlet! s:tlist_{a:fidx}_end
+    unlet! s:tlist_{a:fidx}_valid
+    unlet! s:tlist_{a:fidx}_visible
+    unlet! s:tlist_{a:fidx}_tag_count
+    unlet! s:tlist_{a:fidx}_menu_cmd
+endfunction
+
+" Tlist_Window_Remove_File_From_Display
+" Remove the specified file from display
+function! s:Tlist_Window_Remove_File_From_Display(fidx)
+    call s:Tlist_Log_Msg('Tlist_Window_Remove_File_From_Display (' .
+                \ s:tlist_{a:fidx}_filename . ')')
+    " If the file is not visible then no need to remove it
+    if !s:tlist_{a:fidx}_visible
+        return
+    endif
+
+    " Remove the tags displayed for the specified file from the window
+    let start = s:tlist_{a:fidx}_start
+    " Include the empty line after the last line also
+    if g:Tlist_Compact_Format
+        let end = s:tlist_{a:fidx}_end
+    else
+        let end = s:tlist_{a:fidx}_end + 1
+    endif
+
+    setlocal modifiable
+    exe 'silent! ' . start . ',' . end . 'delete _'
+    setlocal nomodifiable
+
+    " Correct the start and end line offsets for all the files following
+    " this file, as the tags for this file are removed
+    call s:Tlist_Window_Update_Line_Offsets(a:fidx + 1, 0, end - start + 1)
+endfunction
+
+" Tlist_Remove_File
+" Remove the file under the cursor or the specified file index
+" user_request - User requested to remove the file from taglist
+function! s:Tlist_Remove_File(file_idx, user_request)
+    let fidx = a:file_idx
+
+    if fidx == -1
+        let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.'))
+        if fidx == -1
+            return
+        endif
+    endif
+    call s:Tlist_Log_Msg('Tlist_Remove_File (' .
+                \ s:tlist_{fidx}_filename . ', ' . a:user_request . ')')
+
+    let save_winnr = winnr()
+    let winnum = bufwinnr(g:TagList_title)
+    if winnum != -1
+        " Taglist window is open, remove the file from display
+
+        if save_winnr != winnum
+            let old_eventignore = &eventignore
+            set eventignore=all
+            exe winnum . 'wincmd w'
+        endif
+
+        call s:Tlist_Window_Remove_File_From_Display(fidx)
+
+        if save_winnr != winnum
+            exe save_winnr . 'wincmd w'
+            let &eventignore = old_eventignore
+        endif
+    endif
+
+    let fname = s:tlist_{fidx}_filename
+
+    if a:user_request
+        " As the user requested to remove the file from taglist,
+        " add it to the removed list
+        call s:Tlist_Update_Remove_List(fname, 1)
+    endif
+
+    " Remove the file name from the taglist list of filenames
+    let idx = stridx(s:tlist_file_names, fname . "\n")
+    let text_before = strpart(s:tlist_file_names, 0, idx)
+    let rem_text = strpart(s:tlist_file_names, idx)
+    let next_idx = stridx(rem_text, "\n")
+    let text_after = strpart(rem_text, next_idx + 1)
+    let s:tlist_file_names = text_before . text_after
+
+    call s:Tlist_Discard_FileInfo(fidx)
+
+    " Shift all the file variables by one index
+    let i = fidx + 1
+
+    while i < s:tlist_file_count
+        let j = i - 1
+
+        let s:tlist_{j}_filename = s:tlist_{i}_filename
+        let s:tlist_{j}_sort_type = s:tlist_{i}_sort_type
+        let s:tlist_{j}_filetype = s:tlist_{i}_filetype
+        let s:tlist_{j}_mtime = s:tlist_{i}_mtime
+        let s:tlist_{j}_start = s:tlist_{i}_start
+        let s:tlist_{j}_end = s:tlist_{i}_end
+        let s:tlist_{j}_valid = s:tlist_{i}_valid
+        let s:tlist_{j}_visible = s:tlist_{i}_visible
+        let s:tlist_{j}_tag_count = s:tlist_{i}_tag_count
+        let s:tlist_{j}_menu_cmd = s:tlist_{i}_menu_cmd
+
+        let k = 1
+        while k <= s:tlist_{j}_tag_count
+            let s:tlist_{j}_{k}_tag = s:tlist_{i}_{k}_tag
+            let s:tlist_{j}_{k}_tag_name = s:tlist_{i}_{k}_tag_name
+            let s:tlist_{j}_{k}_tag_type = s:Tlist_Get_Tag_Type_By_Tag(i, k)
+            let s:tlist_{j}_{k}_ttype_idx = s:tlist_{i}_{k}_ttype_idx
+            let s:tlist_{j}_{k}_tag_proto = s:Tlist_Get_Tag_Prototype(i, k)
+            let s:tlist_{j}_{k}_tag_searchpat = s:Tlist_Get_Tag_SearchPat(i, k)
+            let s:tlist_{j}_{k}_tag_linenum = s:Tlist_Get_Tag_Linenum(i, k)
+            let k = k + 1
+        endwhile
+
+        let ftype = s:tlist_{i}_filetype
+
+        let k = 1
+        while k <= s:tlist_{ftype}_count
+            let ttype = s:tlist_{ftype}_{k}_name
+            let s:tlist_{j}_{ttype} = s:tlist_{i}_{ttype}
+            let s:tlist_{j}_{ttype}_offset = s:tlist_{i}_{ttype}_offset
+            let s:tlist_{j}_{ttype}_count = s:tlist_{i}_{ttype}_count
+            if s:tlist_{j}_{ttype} != ''
+                let l = 1
+                while l <= s:tlist_{j}_{ttype}_count
+                    let s:tlist_{j}_{ttype}_{l} = s:tlist_{i}_{ttype}_{l}
+                    let l = l + 1
+                endwhile
+            endif
+            let k = k + 1
+        endwhile
+
+        " As the file and tag information is copied to the new index,
+        " discard the previous information
+        call s:Tlist_Discard_FileInfo(i)
+
+        let i = i + 1
+    endwhile
+
+    " Reduce the number of files displayed
+    let s:tlist_file_count = s:tlist_file_count - 1
+
+    if g:Tlist_Show_One_File
+        " If the tags for only one file is displayed and if we just
+        " now removed that file, then invalidate the current file idx
+        if s:tlist_cur_file_idx == fidx
+            let s:tlist_cur_file_idx = -1
+        endif
+    endif
+endfunction
+
+" Tlist_Window_Goto_Window
+" Goto the taglist window
+function! s:Tlist_Window_Goto_Window()
+    let winnum = bufwinnr(g:TagList_title)
+    if winnum != -1
+        if winnr() != winnum
+            call s:Tlist_Exe_Cmd_No_Acmds(winnum . 'wincmd w')
+        endif
+    endif
+endfunction
+
+" Tlist_Window_Create
+" Create a new taglist window. If it is already open, jump to it
+function! s:Tlist_Window_Create()
+    call s:Tlist_Log_Msg('Tlist_Window_Create()')
+    " If the window is open, jump to it
+    let winnum = bufwinnr(g:TagList_title)
+    if winnum != -1
+        " Jump to the existing window
+        if winnr() != winnum
+            exe winnum . 'wincmd w'
+        endif
+        return
+    endif
+
+    " If used with winmanager don't open windows. Winmanager will handle
+    " the window/buffer management
+    if s:tlist_app_name == "winmanager"
+        return
+    endif
+
+    " Create a new window. If user prefers a horizontal window, then open
+    " a horizontally split window. Otherwise open a vertically split
+    " window
+    if g:Tlist_Use_Horiz_Window
+        " Open a horizontally split window
+        let win_dir = 'botright'
+        " Horizontal window height
+        let win_size = g:Tlist_WinHeight
+    else
+        if s:tlist_winsize_chgd == -1
+            " Open a vertically split window. Increase the window size, if
+            " needed, to accomodate the new window
+            if g:Tlist_Inc_Winwidth &&
+                        \ &columns < (80 + g:Tlist_WinWidth)
+                " Save the original window position
+                let s:tlist_pre_winx = getwinposx()
+                let s:tlist_pre_winy = getwinposy()
+
+                " one extra column is needed to include the vertical split
+                let &columns= &columns + g:Tlist_WinWidth + 1
+
+                let s:tlist_winsize_chgd = 1
+            else
+                let s:tlist_winsize_chgd = 0
+            endif
+        endif
+
+        if g:Tlist_Use_Right_Window
+            " Open the window at the rightmost place
+            let win_dir = 'botright vertical'
+        else
+            " Open the window at the leftmost place
+            let win_dir = 'topleft vertical'
+        endif
+        let win_size = g:Tlist_WinWidth
+    endif
+
+    " If the tag listing temporary buffer already exists, then reuse it.
+    " Otherwise create a new buffer
+    let bufnum = bufnr(g:TagList_title)
+    if bufnum == -1
+        " Create a new buffer
+        let wcmd = g:TagList_title
+    else
+        " Edit the existing buffer
+        let wcmd = '+buffer' . bufnum
+    endif
+
+    " Create the taglist window
+    exe 'silent! ' . win_dir . ' ' . win_size . 'split ' . wcmd
+
+    " Save the new window position
+    let s:tlist_winx = getwinposx()
+    let s:tlist_winy = getwinposy()
+
+    " Initialize the taglist window
+    call s:Tlist_Window_Init()
+endfunction
+
+" Tlist_Window_Zoom
+" Zoom (maximize/minimize) the taglist window
+function! s:Tlist_Window_Zoom()
+    if s:tlist_win_maximized
+        " Restore the window back to the previous size
+        if g:Tlist_Use_Horiz_Window
+            exe 'resize ' . g:Tlist_WinHeight
+        else
+            exe 'vert resize ' . g:Tlist_WinWidth
+        endif
+        let s:tlist_win_maximized = 0
+    else
+        " Set the window size to the maximum possible without closing other
+        " windows
+        if g:Tlist_Use_Horiz_Window
+            resize
+        else
+            vert resize
+        endif
+        let s:tlist_win_maximized = 1
+    endif
+endfunction
+
+" Tlist_Ballon_Expr
+" When the mouse cursor is over a tag in the taglist window, display the
+" tag prototype (balloon)
+function! Tlist_Ballon_Expr()
+    " Get the file index
+    let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(v:beval_lnum)
+    if fidx == -1
+        return ''
+    endif
+
+    " Get the tag output line for the current tag
+    let tidx = s:Tlist_Window_Get_Tag_Index(fidx, v:beval_lnum)
+    if tidx == 0
+        return ''
+    endif
+
+    " Get the tag search pattern and display it
+    return s:Tlist_Get_Tag_Prototype(fidx, tidx)
+endfunction
+
+" Tlist_Window_Check_Width
+" Check the width of the taglist window. For horizontally split windows, the
+" 'winfixheight' option is used to fix the height of the window. For
+" vertically split windows, Vim doesn't support the 'winfixwidth' option. So
+" need to handle window width changes from this function.
+function! s:Tlist_Window_Check_Width()
+    let tlist_winnr = bufwinnr(g:TagList_title)
+    if tlist_winnr == -1
+        return
+    endif
+
+    let width = winwidth(tlist_winnr)
+    if width != g:Tlist_WinWidth
+        call s:Tlist_Log_Msg("Tlist_Window_Check_Width: Changing window " .
+                    \ "width from " . width . " to " . g:Tlist_WinWidth)
+        let save_winnr = winnr()
+        if save_winnr != tlist_winnr
+            call s:Tlist_Exe_Cmd_No_Acmds(tlist_winnr . 'wincmd w')
+        endif
+        exe 'vert resize ' . g:Tlist_WinWidth
+        if save_winnr != tlist_winnr
+            call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
+        endif
+    endif
+endfunction
+
+" Tlist_Window_Exit_Only_Window
+" If the 'Tlist_Exit_OnlyWindow' option is set, then exit Vim if only the
+" taglist window is present.
+function! s:Tlist_Window_Exit_Only_Window()
+    " Before quitting Vim, delete the taglist buffer so that
+    " the '0 mark is correctly set to the previous buffer.
+    if v:version < 700
+	if winbufnr(2) == -1
+	    bdelete
+	    quit
+	endif
+    else
+	if winbufnr(2) == -1
+	    if tabpagenr('$') == 1
+		" Only one tag page is present
+		bdelete
+		quit
+	    else
+		" More than one tab page is present. Close only the current
+		" tab page
+		close
+	    endif
+	endif
+    endif
+endfunction
+
+" Tlist_Window_Init
+" Set the default options for the taglist window
+function! s:Tlist_Window_Init()
+    call s:Tlist_Log_Msg('Tlist_Window_Init()')
+
+    " The 'readonly' option should not be set for the taglist buffer.
+    " If Vim is started as "view/gview" or if the ":view" command is
+    " used, then the 'readonly' option is set for all the buffers.
+    " Unset it for the taglist buffer
+    setlocal noreadonly
+
+    " Set the taglist buffer filetype to taglist
+    setlocal filetype=taglist
+
+    " Define taglist window element highlighting
+    syntax match TagListComment '^" .*'
+    syntax match TagListFileName '^[^" ].*$'
+    syntax match TagListTitle '^  \S.*$'
+    syntax match TagListTagScope  '\s\[.\{-\}\]$'
+
+    " Define the highlighting only if colors are supported
+    if has('gui_running') || &t_Co > 2
+        " Colors to highlight various taglist window elements
+        " If user defined highlighting group exists, then use them.
+        " Otherwise, use default highlight groups.
+        if hlexists('MyTagListTagName')
+            highlight link TagListTagName MyTagListTagName
+        else
+            highlight default link TagListTagName Search
+        endif
+        " Colors to highlight comments and titles
+        if hlexists('MyTagListComment')
+            highlight link TagListComment MyTagListComment
+        else
+            highlight clear TagListComment
+            highlight default link TagListComment Comment
+        endif
+        if hlexists('MyTagListTitle')
+            highlight link TagListTitle MyTagListTitle
+        else
+            highlight clear TagListTitle
+            highlight default link TagListTitle Title
+        endif
+        if hlexists('MyTagListFileName')
+            highlight link TagListFileName MyTagListFileName
+        else
+            highlight clear TagListFileName
+            highlight default TagListFileName guibg=Grey ctermbg=darkgray
+                        \ guifg=white ctermfg=white
+        endif
+        if hlexists('MyTagListTagScope')
+            highlight link TagListTagScope MyTagListTagScope
+        else
+            highlight clear TagListTagScope
+            highlight default link TagListTagScope Identifier
+        endif
+    else
+        highlight default TagListTagName term=reverse cterm=reverse
+    endif
+
+    " Folding related settings
+    setlocal foldenable
+    setlocal foldminlines=0
+    setlocal foldmethod=manual
+    setlocal foldlevel=9999
+    if g:Tlist_Enable_Fold_Column
+        setlocal foldcolumn=3
+    else
+        setlocal foldcolumn=0
+    endif
+    setlocal foldtext=v:folddashes.getline(v:foldstart)
+
+    if s:tlist_app_name != "winmanager"
+        " Mark buffer as scratch
+        silent! setlocal buftype=nofile
+        if s:tlist_app_name == "none"
+            silent! setlocal bufhidden=delete
+        endif
+        silent! setlocal noswapfile
+        " Due to a bug in Vim 6.0, the winbufnr() function fails for unlisted
+        " buffers. So if the taglist buffer is unlisted, multiple taglist
+        " windows will be opened. This bug is fixed in Vim 6.1 and above
+        if v:version >= 601
+            silent! setlocal nobuflisted
+        endif
+    endif
+
+    silent! setlocal nowrap
+
+    " If the 'number' option is set in the source window, it will affect the
+    " taglist window. So forcefully disable 'number' option for the taglist
+    " window
+    silent! setlocal nonumber
+
+    " Use fixed height when horizontally split window is used
+    if g:Tlist_Use_Horiz_Window
+        if v:version >= 602
+            set winfixheight
+        endif
+    endif
+    if !g:Tlist_Use_Horiz_Window && v:version >= 700
+        set winfixwidth
+    endif
+
+    " Setup balloon evaluation to display tag prototype
+    if v:version >= 700 && has('balloon_eval')
+        setlocal balloonexpr=Tlist_Ballon_Expr()
+        set ballooneval
+    endif
+
+    " Setup the cpoptions properly for the maps to work
+    let old_cpoptions = &cpoptions
+    set cpoptions&vim
+
+    " Create buffer local mappings for jumping to the tags and sorting the list
+    nnoremap <buffer> <silent> <CR>
+                \ :call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
+    nnoremap <buffer> <silent> o
+                \ :call <SID>Tlist_Window_Jump_To_Tag('newwin')<CR>
+    nnoremap <buffer> <silent> p
+                \ :call <SID>Tlist_Window_Jump_To_Tag('preview')<CR>
+    nnoremap <buffer> <silent> P
+                \ :call <SID>Tlist_Window_Jump_To_Tag('prevwin')<CR>
+    if v:version >= 700
+    nnoremap <buffer> <silent> t
+                \ :call <SID>Tlist_Window_Jump_To_Tag('checktab')<CR>
+    nnoremap <buffer> <silent> <C-t>
+                \ :call <SID>Tlist_Window_Jump_To_Tag('newtab')<CR>
+    endif
+    nnoremap <buffer> <silent> <2-LeftMouse>
+                \ :call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
+    nnoremap <buffer> <silent> s
+                \ :call <SID>Tlist_Change_Sort('cmd', 'toggle', '')<CR>
+    nnoremap <buffer> <silent> + :silent! foldopen<CR>
+    nnoremap <buffer> <silent> - :silent! foldclose<CR>
+    nnoremap <buffer> <silent> * :silent! %foldopen!<CR>
+    nnoremap <buffer> <silent> = :silent! %foldclose<CR>
+    nnoremap <buffer> <silent> <kPlus> :silent! foldopen<CR>
+    nnoremap <buffer> <silent> <kMinus> :silent! foldclose<CR>
+    nnoremap <buffer> <silent> <kMultiply> :silent! %foldopen!<CR>
+    nnoremap <buffer> <silent> <Space> :call <SID>Tlist_Window_Show_Info()<CR>
+    nnoremap <buffer> <silent> u :call <SID>Tlist_Window_Update_File()<CR>
+    nnoremap <buffer> <silent> d :call <SID>Tlist_Remove_File(-1, 1)<CR>
+    nnoremap <buffer> <silent> x :call <SID>Tlist_Window_Zoom()<CR>
+    nnoremap <buffer> <silent> [[ :call <SID>Tlist_Window_Move_To_File(-1)<CR>
+    nnoremap <buffer> <silent> <BS> :call <SID>Tlist_Window_Move_To_File(-1)<CR>
+    nnoremap <buffer> <silent> ]] :call <SID>Tlist_Window_Move_To_File(1)<CR>
+    nnoremap <buffer> <silent> <Tab> :call <SID>Tlist_Window_Move_To_File(1)<CR>
+    nnoremap <buffer> <silent> <F1> :call <SID>Tlist_Window_Toggle_Help_Text()<CR>
+    nnoremap <buffer> <silent> q :close<CR>
+
+    " Insert mode mappings
+    inoremap <buffer> <silent> <CR>
+                \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
+    " Windows needs return
+    inoremap <buffer> <silent> <Return>
+                \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
+    inoremap <buffer> <silent> o
+                \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('newwin')<CR>
+    inoremap <buffer> <silent> p
+                \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('preview')<CR>
+    inoremap <buffer> <silent> P
+                \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('prevwin')<CR>
+    if v:version >= 700
+    inoremap <buffer> <silent> t
+                \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('checktab')<CR>
+    inoremap <buffer> <silent> <C-t>
+                \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('newtab')<CR>
+    endif
+    inoremap <buffer> <silent> <2-LeftMouse>
+                \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
+    inoremap <buffer> <silent> s
+                \ <C-o>:call <SID>Tlist_Change_Sort('cmd', 'toggle', '')<CR>
+    inoremap <buffer> <silent> +             <C-o>:silent! foldopen<CR>
+    inoremap <buffer> <silent> -             <C-o>:silent! foldclose<CR>
+    inoremap <buffer> <silent> *             <C-o>:silent! %foldopen!<CR>
+    inoremap <buffer> <silent> =             <C-o>:silent! %foldclose<CR>
+    inoremap <buffer> <silent> <kPlus>       <C-o>:silent! foldopen<CR>
+    inoremap <buffer> <silent> <kMinus>      <C-o>:silent! foldclose<CR>
+    inoremap <buffer> <silent> <kMultiply>   <C-o>:silent! %foldopen!<CR>
+    inoremap <buffer> <silent> <Space>       <C-o>:call
+                                    \ <SID>Tlist_Window_Show_Info()<CR>
+    inoremap <buffer> <silent> u
+                            \ <C-o>:call <SID>Tlist_Window_Update_File()<CR>
+    inoremap <buffer> <silent> d    <C-o>:call <SID>Tlist_Remove_File(-1, 1)<CR>
+    inoremap <buffer> <silent> x    <C-o>:call <SID>Tlist_Window_Zoom()<CR>
+    inoremap <buffer> <silent> [[   <C-o>:call <SID>Tlist_Window_Move_To_File(-1)<CR>
+    inoremap <buffer> <silent> <BS> <C-o>:call <SID>Tlist_Window_Move_To_File(-1)<CR>
+    inoremap <buffer> <silent> ]]   <C-o>:call <SID>Tlist_Window_Move_To_File(1)<CR>
+    inoremap <buffer> <silent> <Tab> <C-o>:call <SID>Tlist_Window_Move_To_File(1)<CR>
+    inoremap <buffer> <silent> <F1>  <C-o>:call <SID>Tlist_Window_Toggle_Help_Text()<CR>
+    inoremap <buffer> <silent> q    <C-o>:close<CR>
+
+    " Map single left mouse click if the user wants this functionality
+    if g:Tlist_Use_SingleClick == 1
+        " Contributed by Bindu Wavell
+        " attempt to perform single click mapping, it would be much
+        " nicer if we could nnoremap <buffer> ... however vim does
+        " not fire the <buffer> <leftmouse> when you use the mouse
+        " to enter a buffer.
+        let clickmap = ':if bufname("%") =~ "__Tag_List__" <bar> ' .
+                    \ 'call <SID>Tlist_Window_Jump_To_Tag("useopen") ' .
+                    \ '<bar> endif <CR>'
+        if maparg('<leftmouse>', 'n') == ''
+            " no mapping for leftmouse
+            exe ':nnoremap <silent> <leftmouse> <leftmouse>' . clickmap
+        else
+            " we have a mapping
+            let mapcmd = ':nnoremap <silent> <leftmouse> <leftmouse>'
+            let mapcmd = mapcmd . substitute(substitute(
+                        \ maparg('<leftmouse>', 'n'), '|', '<bar>', 'g'),
+                        \ '\c^<leftmouse>', '', '')
+            let mapcmd = mapcmd . clickmap
+            exe mapcmd
+        endif
+    endif
+
+    " Define the taglist autocommands
+    augroup TagListAutoCmds
+        autocmd!
+        " Display the tag prototype for the tag under the cursor.
+        autocmd CursorHold __Tag_List__ call s:Tlist_Window_Show_Info()
+        " Highlight the current tag periodically
+        autocmd CursorHold * silent call s:Tlist_Window_Highlight_Tag(
+                            \ fnamemodify(bufname('%'), ':p'), line('.'), 1, 0)
+
+        " Adjust the Vim window width when taglist window is closed
+        autocmd BufUnload __Tag_List__ call s:Tlist_Post_Close_Cleanup()
+        " Close the fold for this buffer when leaving the buffer
+        if g:Tlist_File_Fold_Auto_Close
+            autocmd BufEnter * silent
+                \ call s:Tlist_Window_Open_File_Fold(expand('<abuf>'))
+        endif
+        " Exit Vim itself if only the taglist window is present (optional)
+        if g:Tlist_Exit_OnlyWindow
+	    autocmd BufEnter __Tag_List__ nested
+			\ call s:Tlist_Window_Exit_Only_Window()
+        endif
+        if s:tlist_app_name != "winmanager" &&
+                    \ !g:Tlist_Process_File_Always &&
+                    \ (!has('gui_running') || !g:Tlist_Show_Menu)
+            " Auto refresh the taglist window
+            autocmd BufEnter * call s:Tlist_Refresh()
+        endif
+
+        if !g:Tlist_Use_Horiz_Window
+            if v:version < 700
+                autocmd WinEnter * call s:Tlist_Window_Check_Width()
+            endif
+        endif
+        if v:version >= 700
+            autocmd TabEnter * silent call s:Tlist_Refresh_Folds()
+        endif
+    augroup end
+
+    " Restore the previous cpoptions settings
+    let &cpoptions = old_cpoptions
+endfunction
+
+" Tlist_Window_Refresh
+" Display the tags for all the files in the taglist window
+function! s:Tlist_Window_Refresh()
+    call s:Tlist_Log_Msg('Tlist_Window_Refresh()')
+    " Set report option to a huge value to prevent informational messages
+    " while deleting the lines
+    let old_report = &report
+    set report=99999
+
+    " Mark the buffer as modifiable
+    setlocal modifiable
+
+    " Delete the contents of the buffer to the black-hole register
+    silent! %delete _
+
+    " As we have cleared the taglist window, mark all the files
+    " as not visible
+    let i = 0
+    while i < s:tlist_file_count
+        let s:tlist_{i}_visible = 0
+        let i = i + 1
+    endwhile
+
+    if g:Tlist_Compact_Format == 0
+        " Display help in non-compact mode
+        call s:Tlist_Window_Display_Help()
+    endif
+
+    " Mark the buffer as not modifiable
+    setlocal nomodifiable
+
+    " Restore the report option
+    let &report = old_report
+
+    " If the tags for only one file should be displayed in the taglist
+    " window, then no need to add the tags here. The bufenter autocommand
+    " will add the tags for that file.
+    if g:Tlist_Show_One_File
+        return
+    endif
+
+    " List all the tags for the previously processed files
+    " Do this only if taglist is configured to display tags for more than
+    " one file. Otherwise, when Tlist_Show_One_File is configured,
+    " tags for the wrong file will be displayed.
+    let i = 0
+    while i < s:tlist_file_count
+        call s:Tlist_Window_Refresh_File(s:tlist_{i}_filename,
+                    \ s:tlist_{i}_filetype)
+        let i = i + 1
+    endwhile
+
+    if g:Tlist_Auto_Update
+        " Add and list the tags for all buffers in the Vim buffer list
+        let i = 1
+        let last_bufnum = bufnr('$')
+        while i <= last_bufnum
+            if buflisted(i)
+                let fname = fnamemodify(bufname(i), ':p')
+                let ftype = s:Tlist_Get_Buffer_Filetype(i)
+                " If the file doesn't support tag listing, skip it
+                if !s:Tlist_Skip_File(fname, ftype)
+                    call s:Tlist_Window_Refresh_File(fname, ftype)
+                endif
+            endif
+            let i = i + 1
+        endwhile
+    endif
+
+    " If Tlist_File_Fold_Auto_Close option is set, then close all the folds
+    if g:Tlist_File_Fold_Auto_Close
+        " Close all the folds
+        silent! %foldclose
+    endif
+
+    " Move the cursor to the top of the taglist window
+    normal! gg
+endfunction
+
+" Tlist_Post_Close_Cleanup()
+" Close the taglist window and adjust the Vim window width
+function! s:Tlist_Post_Close_Cleanup()
+    call s:Tlist_Log_Msg('Tlist_Post_Close_Cleanup()')
+    " Mark all the files as not visible
+    let i = 0
+    while i < s:tlist_file_count
+        let s:tlist_{i}_visible = 0
+        let i = i + 1
+    endwhile
+
+    " Remove the taglist autocommands
+    silent! autocmd! TagListAutoCmds
+
+    " Clear all the highlights
+    match none
+
+    silent! syntax clear TagListTitle
+    silent! syntax clear TagListComment
+    silent! syntax clear TagListTagScope
+
+    " Remove the left mouse click mapping if it was setup initially
+    if g:Tlist_Use_SingleClick
+        if hasmapto('<LeftMouse>')
+            nunmap <LeftMouse>
+        endif
+    endif
+
+    if s:tlist_app_name != "winmanager"
+    if g:Tlist_Use_Horiz_Window || g:Tlist_Inc_Winwidth == 0 ||
+                \ s:tlist_winsize_chgd != 1 ||
+                \ &columns < (80 + g:Tlist_WinWidth)
+        " No need to adjust window width if using horizontally split taglist
+        " window or if columns is less than 101 or if the user chose not to
+        " adjust the window width
+    else
+        " If the user didn't manually move the window, then restore the window
+        " position to the pre-taglist position
+        if s:tlist_pre_winx != -1 && s:tlist_pre_winy != -1 &&
+                    \ getwinposx() == s:tlist_winx &&
+                    \ getwinposy() == s:tlist_winy
+            exe 'winpos ' . s:tlist_pre_winx . ' ' . s:tlist_pre_winy
+        endif
+
+        " Adjust the Vim window width
+        let &columns= &columns - (g:Tlist_WinWidth + 1)
+    endif
+    endif
+
+    let s:tlist_winsize_chgd = -1
+
+    " Reset taglist state variables
+    if s:tlist_app_name == "winmanager"
+        let s:tlist_app_name = "none"
+    endif
+    let s:tlist_window_initialized = 0
+endfunction
+
+" Tlist_Window_Refresh_File()
+" List the tags defined in the specified file in a Vim window
+function! s:Tlist_Window_Refresh_File(filename, ftype)
+    call s:Tlist_Log_Msg('Tlist_Window_Refresh_File (' . a:filename . ')')
+    " First check whether the file already exists
+    let fidx = s:Tlist_Get_File_Index(a:filename)
+    if fidx != -1
+        let file_listed = 1
+    else
+        let file_listed = 0
+    endif
+
+    if !file_listed
+        " Check whether this file is removed based on user request
+        " If it is, then don't display the tags for this file
+        if s:Tlist_User_Removed_File(a:filename)
+            return
+        endif
+    endif
+
+    if file_listed && s:tlist_{fidx}_visible
+        " Check whether the file tags are currently valid
+        if s:tlist_{fidx}_valid
+            " Goto the first line in the file
+            exe s:tlist_{fidx}_start
+
+            " If the line is inside a fold, open the fold
+            if foldclosed('.') != -1
+                exe "silent! " . s:tlist_{fidx}_start . "," .
+                            \ s:tlist_{fidx}_end . "foldopen!"
+            endif
+            return
+        endif
+
+        " Discard and remove the tags for this file from display
+        call s:Tlist_Discard_TagInfo(fidx)
+        call s:Tlist_Window_Remove_File_From_Display(fidx)
+    endif
+
+    " Process and generate a list of tags defined in the file
+    if !file_listed || !s:tlist_{fidx}_valid
+        let ret_fidx = s:Tlist_Process_File(a:filename, a:ftype)
+        if ret_fidx == -1
+            return
+        endif
+        let fidx = ret_fidx
+    endif
+
+    " Set report option to a huge value to prevent informational messages
+    " while adding lines to the taglist window
+    let old_report = &report
+    set report=99999
+
+    if g:Tlist_Show_One_File
+        " Remove the previous file
+        if s:tlist_cur_file_idx != -1
+            call s:Tlist_Window_Remove_File_From_Display(s:tlist_cur_file_idx)
+            let s:tlist_{s:tlist_cur_file_idx}_visible = 0
+            let s:tlist_{s:tlist_cur_file_idx}_start = 0
+            let s:tlist_{s:tlist_cur_file_idx}_end = 0
+        endif
+        let s:tlist_cur_file_idx = fidx
+    endif
+
+    " Mark the buffer as modifiable
+    setlocal modifiable
+
+    " Add new files to the end of the window. For existing files, add them at
+    " the same line where they were previously present. If the file is not
+    " visible, then add it at the end
+    if s:tlist_{fidx}_start == 0 || !s:tlist_{fidx}_visible
+        if g:Tlist_Compact_Format
+            let s:tlist_{fidx}_start = line('$')
+        else
+            let s:tlist_{fidx}_start = line('$') + 1
+        endif
+    endif
+
+    let s:tlist_{fidx}_visible = 1
+
+    " Goto the line where this file should be placed
+    if g:Tlist_Compact_Format
+        exe s:tlist_{fidx}_start
+    else
+        exe s:tlist_{fidx}_start - 1
+    endif
+
+    let txt = fnamemodify(s:tlist_{fidx}_filename, ':t') . ' (' .
+                \ fnamemodify(s:tlist_{fidx}_filename, ':p:h') . ')'
+    if g:Tlist_Compact_Format == 0
+        silent! put =txt
+    else
+        silent! put! =txt
+        " Move to the next line
+        exe line('.') + 1
+    endif
+    let file_start = s:tlist_{fidx}_start
+
+    " Add the tag names grouped by tag type to the buffer with a title
+    let i = 1
+    let ttype_cnt = s:tlist_{a:ftype}_count
+    while i <= ttype_cnt
+        let ttype = s:tlist_{a:ftype}_{i}_name
+        " Add the tag type only if there are tags for that type
+        let fidx_ttype = 's:tlist_' . fidx . '_' . ttype
+        let ttype_txt = {fidx_ttype}
+        if ttype_txt != ''
+            let txt = '  ' . s:tlist_{a:ftype}_{i}_fullname
+            if g:Tlist_Compact_Format == 0
+                let ttype_start_lnum = line('.') + 1
+                silent! put =txt
+            else
+                let ttype_start_lnum = line('.')
+                silent! put! =txt
+            endif
+            silent! put =ttype_txt
+
+            let {fidx_ttype}_offset = ttype_start_lnum - file_start
+
+            " create a fold for this tag type
+            let fold_start = ttype_start_lnum
+            let fold_end = fold_start + {fidx_ttype}_count
+            exe fold_start . ',' . fold_end  . 'fold'
+
+            " Adjust the cursor position
+            if g:Tlist_Compact_Format == 0
+                exe ttype_start_lnum + {fidx_ttype}_count
+            else
+                exe ttype_start_lnum + {fidx_ttype}_count + 1
+            endif
+
+            if g:Tlist_Compact_Format == 0
+                " Separate the tag types by a empty line
+                silent! put =''
+            endif
+        endif
+        let i = i + 1
+    endwhile
+
+    if s:tlist_{fidx}_tag_count == 0
+        if g:Tlist_Compact_Format == 0
+            silent! put =''
+        endif
+    endif
+
+    let s:tlist_{fidx}_end = line('.') - 1
+
+    " Create a fold for the entire file
+    exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'fold'
+    exe 'silent! ' . s:tlist_{fidx}_start . ',' .
+                \ s:tlist_{fidx}_end . 'foldopen!'
+
+    " Goto the starting line for this file,
+    exe s:tlist_{fidx}_start
+
+    if s:tlist_app_name == "winmanager"
+        " To handle a bug in the winmanager plugin, add a space at the
+        " last line
+        call setline('$', ' ')
+    endif
+
+    " Mark the buffer as not modifiable
+    setlocal nomodifiable
+
+    " Restore the report option
+    let &report = old_report
+
+    " Update the start and end line numbers for all the files following this
+    " file
+    let start = s:tlist_{fidx}_start
+    " include the empty line after the last line
+    if g:Tlist_Compact_Format
+        let end = s:tlist_{fidx}_end
+    else
+        let end = s:tlist_{fidx}_end + 1
+    endif
+    call s:Tlist_Window_Update_Line_Offsets(fidx + 1, 1, end - start + 1)
+
+    " Now that we have updated the taglist window, update the tags
+    " menu (if present)
+    if g:Tlist_Show_Menu
+        call s:Tlist_Menu_Update_File(1)
+    endif
+endfunction
+
+" Tlist_Init_File
+" Initialize the variables for a new file
+function! s:Tlist_Init_File(filename, ftype)
+    call s:Tlist_Log_Msg('Tlist_Init_File (' . a:filename . ')')
+    " Add new files at the end of the list
+    let fidx = s:tlist_file_count
+    let s:tlist_file_count = s:tlist_file_count + 1
+    " Add the new file name to the taglist list of file names
+    let s:tlist_file_names = s:tlist_file_names . a:filename . "\n"
+
+    " Initialize the file variables
+    let s:tlist_{fidx}_filename = a:filename
+    let s:tlist_{fidx}_sort_type = g:Tlist_Sort_Type
+    let s:tlist_{fidx}_filetype = a:ftype
+    let s:tlist_{fidx}_mtime = -1
+    let s:tlist_{fidx}_start = 0
+    let s:tlist_{fidx}_end = 0
+    let s:tlist_{fidx}_valid = 0
+    let s:tlist_{fidx}_visible = 0
+    let s:tlist_{fidx}_tag_count = 0
+    let s:tlist_{fidx}_menu_cmd = ''
+
+    " Initialize the tag type variables
+    let i = 1
+    while i <= s:tlist_{a:ftype}_count
+        let ttype = s:tlist_{a:ftype}_{i}_name
+        let s:tlist_{fidx}_{ttype} = ''
+        let s:tlist_{fidx}_{ttype}_offset = 0
+        let s:tlist_{fidx}_{ttype}_count = 0
+        let i = i + 1
+    endwhile
+
+    return fidx
+endfunction
+
+" Tlist_Get_Tag_Type_By_Tag
+" Return the tag type for the specified tag index
+function! s:Tlist_Get_Tag_Type_By_Tag(fidx, tidx)
+    let ttype_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_type'
+
+    " Already parsed and have the tag name
+    if exists(ttype_var)
+        return {ttype_var}
+    endif
+
+    let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag
+    let {ttype_var} = s:Tlist_Extract_Tagtype(tag_line)
+
+    return {ttype_var}
+endfunction
+
+" Tlist_Get_Tag_Prototype
+function! s:Tlist_Get_Tag_Prototype(fidx, tidx)
+    let tproto_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_proto'
+
+    " Already parsed and have the tag prototype
+    if exists(tproto_var)
+        return {tproto_var}
+    endif
+
+    " Parse and extract the tag prototype
+    let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag
+    let start = stridx(tag_line, '/^') + 2
+    let end = stridx(tag_line, '/;"' . "\t")
+    if tag_line[end - 1] == '$'
+        let end = end -1
+    endif
+    let tag_proto = strpart(tag_line, start, end - start)
+    let {tproto_var} = substitute(tag_proto, '\s*', '', '')
+
+    return {tproto_var}
+endfunction
+
+" Tlist_Get_Tag_SearchPat
+function! s:Tlist_Get_Tag_SearchPat(fidx, tidx)
+    let tpat_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_searchpat'
+
+    " Already parsed and have the tag search pattern
+    if exists(tpat_var)
+        return {tpat_var}
+    endif
+
+    " Parse and extract the tag search pattern
+    let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag
+    let start = stridx(tag_line, '/^') + 2
+    let end = stridx(tag_line, '/;"' . "\t")
+    if tag_line[end - 1] == '$'
+        let end = end -1
+    endif
+    let {tpat_var} = '\V\^' . strpart(tag_line, start, end - start) .
+                        \ (tag_line[end] == '$' ? '\$' : '')
+
+    return {tpat_var}
+endfunction
+
+" Tlist_Get_Tag_Linenum
+" Return the tag line number, given the tag index
+function! s:Tlist_Get_Tag_Linenum(fidx, tidx)
+    let tline_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_linenum'
+
+    " Already parsed and have the tag line number
+    if exists(tline_var)
+        return {tline_var}
+    endif
+
+    " Parse and extract the tag line number
+    let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag
+    let start = strridx(tag_line, 'line:') + 5
+    let end = strridx(tag_line, "\t")
+    if end < start
+        let {tline_var} = strpart(tag_line, start) + 0
+    else
+        let {tline_var} = strpart(tag_line, start, end - start) + 0
+    endif
+
+    return {tline_var}
+endfunction
+
+" Tlist_Parse_Tagline
+" Parse a tag line from the ctags output. Separate the tag output based on the
+" tag type and store it in the tag type variable.
+" The format of each line in the ctags output is:
+"
+"     tag_name<TAB>file_name<TAB>ex_cmd;"<TAB>extension_fields
+"
+function! s:Tlist_Parse_Tagline(tag_line)
+    if a:tag_line == ''
+        " Skip empty lines
+        return
+    endif
+
+    " Extract the tag type
+    let ttype = s:Tlist_Extract_Tagtype(a:tag_line)
+
+    " Make sure the tag type is a valid and supported one
+    if ttype == '' || stridx(s:ctags_flags, ttype) == -1
+        " Line is not in proper tags format or Tag type is not supported
+        return
+    endif
+
+    " Update the total tag count
+    let s:tidx = s:tidx + 1
+
+    " The following variables are used to optimize this code.  Vim is slow in
+    " using curly brace names. To reduce the amount of processing needed, the
+    " curly brace variables are pre-processed here
+    let fidx_tidx = 's:tlist_' . s:fidx . '_' . s:tidx
+    let fidx_ttype = 's:tlist_' . s:fidx . '_' . ttype
+
+    " Update the count of this tag type
+    let ttype_idx = {fidx_ttype}_count + 1
+    let {fidx_ttype}_count = ttype_idx
+
+    " Store the ctags output for this tag
+    let {fidx_tidx}_tag = a:tag_line
+
+    " Store the tag index and the tag type index (back pointers)
+    let {fidx_ttype}_{ttype_idx} = s:tidx
+    let {fidx_tidx}_ttype_idx = ttype_idx
+
+    " Extract the tag name
+    let tag_name = strpart(a:tag_line, 0, stridx(a:tag_line, "\t"))
+
+    " Extract the tag scope/prototype
+    if g:Tlist_Display_Prototype
+        let ttxt = '    ' . s:Tlist_Get_Tag_Prototype(s:fidx, s:tidx)
+    else
+        let ttxt = '    ' . tag_name
+
+        " Add the tag scope, if it is available and is configured. Tag
+        " scope is the last field after the 'line:<num>\t' field
+        if g:Tlist_Display_Tag_Scope
+            let tag_scope = s:Tlist_Extract_Tag_Scope(a:tag_line)
+            if tag_scope != ''
+                let ttxt = ttxt . ' [' . tag_scope . ']'
+            endif
+        endif
+    endif
+
+    " Add this tag to the tag type variable
+    let {fidx_ttype} = {fidx_ttype} . ttxt . "\n"
+
+    " Save the tag name
+    let {fidx_tidx}_tag_name = tag_name
+endfunction
+
+" Tlist_Process_File
+" Get the list of tags defined in the specified file and store them
+" in Vim variables. Returns the file index where the tags are stored.
+function! s:Tlist_Process_File(filename, ftype)
+    call s:Tlist_Log_Msg('Tlist_Process_File (' . a:filename . ', ' .
+                \ a:ftype . ')')
+    " Check whether this file is supported
+    if s:Tlist_Skip_File(a:filename, a:ftype)
+        return -1
+    endif
+
+    " If the tag types for this filetype are not yet created, then create
+    " them now
+    let var = 's:tlist_' . a:ftype . '_count'
+    if !exists(var)
+        if s:Tlist_FileType_Init(a:ftype) == 0
+            return -1
+        endif
+    endif
+
+    " If this file is already processed, then use the cached values
+    let fidx = s:Tlist_Get_File_Index(a:filename)
+    if fidx == -1
+        " First time, this file is loaded
+        let fidx = s:Tlist_Init_File(a:filename, a:ftype)
+    else
+        " File was previously processed. Discard the tag information
+        call s:Tlist_Discard_TagInfo(fidx)
+    endif
+
+    let s:tlist_{fidx}_valid = 1
+
+    " Exuberant ctags arguments to generate a tag list
+    let ctags_args = ' -f - --format=2 --excmd=pattern --fields=nks '
+
+    " Form the ctags argument depending on the sort type
+    if s:tlist_{fidx}_sort_type == 'name'
+        let ctags_args = ctags_args . '--sort=yes'
+    else
+        let ctags_args = ctags_args . '--sort=no'
+    endif
+
+    " Add the filetype specific arguments
+    let ctags_args = ctags_args . ' ' . s:tlist_{a:ftype}_ctags_args
+
+    " Ctags command to produce output with regexp for locating the tags
+    let ctags_cmd = g:Tlist_Ctags_Cmd . ctags_args
+    let ctags_cmd = ctags_cmd . ' "' . a:filename . '"'
+
+    if &shellxquote == '"'
+        " Double-quotes within double-quotes will not work in the
+        " command-line.If the 'shellxquote' option is set to double-quotes,
+        " then escape the double-quotes in the ctags command-line.
+        let ctags_cmd = escape(ctags_cmd, '"')
+    endif
+
+    " In Windows 95, if not using cygwin, disable the 'shellslash'
+    " option. Otherwise, this will cause problems when running the
+    " ctags command.
+    if has('win95') && !has('win32unix')
+        let old_shellslash = &shellslash
+        set noshellslash
+    endif
+
+    if has('win32') && !has('win32unix') && !has('win95')
+                \ && (&shell =~ 'cmd.exe')
+        " Windows does not correctly deal with commands that have more than 1
+        " set of double quotes.  It will strip them all resulting in:
+        " 'C:\Program' is not recognized as an internal or external command
+        " operable program or batch file.  To work around this, place the
+        " command inside a batch file and call the batch file.
+        " Do this only on Win2K, WinXP and above.
+        " Contributed by: David Fishburn.
+        let s:taglist_tempfile = fnamemodify(tempname(), ':h') .
+                    \ '\taglist.cmd'
+        exe 'redir! > ' . s:taglist_tempfile
+        silent echo ctags_cmd
+        redir END
+
+        call s:Tlist_Log_Msg('Cmd inside batch file: ' . ctags_cmd)
+        let ctags_cmd = '"' . s:taglist_tempfile . '"'
+    endif
+
+    call s:Tlist_Log_Msg('Cmd: ' . ctags_cmd)
+
+    " Run ctags and get the tag list
+    let cmd_output = system(ctags_cmd)
+
+    " Restore the value of the 'shellslash' option.
+    if has('win95') && !has('win32unix')
+        let &shellslash = old_shellslash
+    endif
+
+    if exists('s:taglist_tempfile')
+        " Delete the temporary cmd file created on MS-Windows
+        call delete(s:taglist_tempfile)
+    endif
+
+    " Handle errors
+    if v:shell_error
+        let msg = "Taglist: Failed to generate tags for " . a:filename
+        call s:Tlist_Warning_Msg(msg)
+        if cmd_output != ''
+            call s:Tlist_Warning_Msg(cmd_output)
+        endif
+        return fidx
+    endif
+
+    " Store the modification time for the file
+    let s:tlist_{fidx}_mtime = getftime(a:filename)
+
+    " No tags for current file
+    if cmd_output == ''
+        call s:Tlist_Log_Msg('No tags defined in ' . a:filename)
+        return fidx
+    endif
+
+    call s:Tlist_Log_Msg('Generated tags information for ' . a:filename)
+
+    if v:version > 601
+        " The following script local variables are used by the
+        " Tlist_Parse_Tagline() function.
+        let s:ctags_flags = s:tlist_{a:ftype}_ctags_flags
+        let s:fidx = fidx
+        let s:tidx = 0
+
+        " Process the ctags output one line at a time.  The substitute()
+        " command is used to parse the tag lines instead of using the
+        " matchstr()/stridx()/strpart() functions for performance reason
+        call substitute(cmd_output, "\\([^\n]\\+\\)\n",
+                    \ '\=s:Tlist_Parse_Tagline(submatch(1))', 'g')
+
+        " Save the number of tags for this file
+        let s:tlist_{fidx}_tag_count = s:tidx
+
+        " The following script local variables are no longer needed
+        unlet! s:ctags_flags
+        unlet! s:tidx
+        unlet! s:fidx
+    else
+        " Due to a bug in Vim earlier than version 6.1,
+        " we cannot use substitute() to parse the ctags output.
+        " Instead the slow str*() functions are used
+        let ctags_flags = s:tlist_{a:ftype}_ctags_flags
+        let tidx = 0
+
+        while cmd_output != ''
+            " Extract one line at a time
+            let idx = stridx(cmd_output, "\n")
+            let one_line = strpart(cmd_output, 0, idx)
+            " Remove the line from the tags output
+            let cmd_output = strpart(cmd_output, idx + 1)
+
+            if one_line == ''
+                " Line is not in proper tags format
+                continue
+            endif
+
+            " Extract the tag type
+            let ttype = s:Tlist_Extract_Tagtype(one_line)
+
+            " Make sure the tag type is a valid and supported one
+            if ttype == '' || stridx(ctags_flags, ttype) == -1
+                " Line is not in proper tags format or Tag type is not
+                " supported
+                continue
+            endif
+
+            " Update the total tag count
+            let tidx = tidx + 1
+
+            " The following variables are used to optimize this code.  Vim is
+            " slow in using curly brace names. To reduce the amount of
+            " processing needed, the curly brace variables are pre-processed
+            " here
+            let fidx_tidx = 's:tlist_' . fidx . '_' . tidx
+            let fidx_ttype = 's:tlist_' . fidx . '_' . ttype
+
+            " Update the count of this tag type
+            let ttype_idx = {fidx_ttype}_count + 1
+            let {fidx_ttype}_count = ttype_idx
+
+            " Store the ctags output for this tag
+            let {fidx_tidx}_tag = one_line
+
+            " Store the tag index and the tag type index (back pointers)
+            let {fidx_ttype}_{ttype_idx} = tidx
+            let {fidx_tidx}_ttype_idx = ttype_idx
+
+            " Extract the tag name
+            let tag_name = strpart(one_line, 0, stridx(one_line, "\t"))
+
+            " Extract the tag scope/prototype
+            if g:Tlist_Display_Prototype
+                let ttxt = '    ' . s:Tlist_Get_Tag_Prototype(fidx, tidx)
+            else
+                let ttxt = '    ' . tag_name
+
+                " Add the tag scope, if it is available and is configured. Tag
+                " scope is the last field after the 'line:<num>\t' field
+                if g:Tlist_Display_Tag_Scope
+                    let tag_scope = s:Tlist_Extract_Tag_Scope(one_line)
+                    if tag_scope != ''
+                        let ttxt = ttxt . ' [' . tag_scope . ']'
+                    endif
+                endif
+            endif
+
+            " Add this tag to the tag type variable
+            let {fidx_ttype} = {fidx_ttype} . ttxt . "\n"
+
+            " Save the tag name
+            let {fidx_tidx}_tag_name = tag_name
+        endwhile
+
+        " Save the number of tags for this file
+        let s:tlist_{fidx}_tag_count = tidx
+    endif
+
+    call s:Tlist_Log_Msg('Processed ' . s:tlist_{fidx}_tag_count . 
+                \ ' tags in ' . a:filename)
+
+    return fidx
+endfunction
+
+" Tlist_Update_File
+" Update the tags for a file (if needed)
+function! Tlist_Update_File(filename, ftype)
+    call s:Tlist_Log_Msg('Tlist_Update_File (' . a:filename . ')')
+    " If the file doesn't support tag listing, skip it
+    if s:Tlist_Skip_File(a:filename, a:ftype)
+        return
+    endif
+
+    " Convert the file name to a full path
+    let fname = fnamemodify(a:filename, ':p')
+
+    " First check whether the file already exists
+    let fidx = s:Tlist_Get_File_Index(fname)
+
+    if fidx != -1 && s:tlist_{fidx}_valid
+        " File exists and the tags are valid
+        " Check whether the file was modified after the last tags update
+        " If it is modified, then update the tags
+        if s:tlist_{fidx}_mtime == getftime(fname)
+            return
+        endif
+    else
+        " If the tags were removed previously based on a user request,
+        " as we are going to update the tags (based on the user request),
+        " remove the filename from the deleted list
+        call s:Tlist_Update_Remove_List(fname, 0)
+    endif
+
+    " If the taglist window is opened, update it
+    let winnum = bufwinnr(g:TagList_title)
+    if winnum == -1
+        " Taglist window is not present. Just update the taglist
+        " and return
+        call s:Tlist_Process_File(fname, a:ftype)
+    else
+        if g:Tlist_Show_One_File && s:tlist_cur_file_idx != -1
+            " If tags for only one file are displayed and we are not
+            " updating the tags for that file, then no need to
+            " refresh the taglist window. Otherwise, the taglist
+            " window should be updated.
+            if s:tlist_{s:tlist_cur_file_idx}_filename != fname
+                call s:Tlist_Process_File(fname, a:ftype)
+                return
+            endif
+        endif
+
+        " Save the current window number
+        let save_winnr = winnr()
+
+        " Goto the taglist window
+        call s:Tlist_Window_Goto_Window()
+
+        " Save the cursor position
+        let save_line = line('.')
+        let save_col = col('.')
+
+        " Update the taglist window
+        call s:Tlist_Window_Refresh_File(fname, a:ftype)
+
+        " Restore the cursor position
+        if v:version >= 601
+            call cursor(save_line, save_col)
+        else
+            exe save_line
+            exe 'normal! ' . save_col . '|'
+        endif
+
+        if winnr() != save_winnr
+            " Go back to the original window
+            call s:Tlist_Exe_Cmd_No_Acmds(save_winnr . 'wincmd w')
+        endif
+    endif
+
+    " Update the taglist menu
+    if g:Tlist_Show_Menu
+        call s:Tlist_Menu_Update_File(1)
+    endif
+endfunction
+
+" Tlist_Window_Close
+" Close the taglist window
+function! s:Tlist_Window_Close()
+    call s:Tlist_Log_Msg('Tlist_Window_Close()')
+    " Make sure the taglist window exists
+    let winnum = bufwinnr(g:TagList_title)
+    if winnum == -1
+        call s:Tlist_Warning_Msg('Error: Taglist window is not open')
+        return
+    endif
+
+    if winnr() == winnum
+        " Already in the taglist window. Close it and return
+        if winbufnr(2) != -1
+            " If a window other than the taglist window is open,
+            " then only close the taglist window.
+            close
+        endif
+    else
+        " Goto the taglist window, close it and then come back to the
+        " original window
+        let curbufnr = bufnr('%')
+        exe winnum . 'wincmd w'
+        close
+        " Need to jump back to the original window only if we are not
+        " already in that window
+        let winnum = bufwinnr(curbufnr)
+        if winnr() != winnum
+            exe winnum . 'wincmd w'
+        endif
+    endif
+endfunction
+
+" Tlist_Window_Mark_File_Window
+" Mark the current window as the file window to use when jumping to a tag.
+" Only if the current window is a non-plugin, non-preview and non-taglist
+" window
+function! s:Tlist_Window_Mark_File_Window()
+    if getbufvar('%', '&buftype') == '' && !&previewwindow
+        let w:tlist_file_window = "yes"
+    endif
+endfunction
+
+" Tlist_Window_Open
+" Open and refresh the taglist window
+function! s:Tlist_Window_Open()
+    call s:Tlist_Log_Msg('Tlist_Window_Open()')
+    " If the window is open, jump to it
+    let winnum = bufwinnr(g:TagList_title)
+    if winnum != -1
+        " Jump to the existing window
+        if winnr() != winnum
+            exe winnum . 'wincmd w'
+        endif
+        return
+    endif
+
+    if s:tlist_app_name == "winmanager"
+        " Taglist plugin is no longer part of the winmanager app
+        let s:tlist_app_name = "none"
+    endif
+
+    " Get the filename and filetype for the specified buffer
+    let curbuf_name = fnamemodify(bufname('%'), ':p')
+    let curbuf_ftype = s:Tlist_Get_Buffer_Filetype('%')
+    let cur_lnum = line('.')
+
+    " Mark the current window as the desired window to open a file when a tag
+    " is selected.
+    call s:Tlist_Window_Mark_File_Window()
+
+    " Open the taglist window
+    call s:Tlist_Window_Create()
+
+    call s:Tlist_Window_Refresh()
+
+    if g:Tlist_Show_One_File
+        " Add only the current buffer and file
+        "
+        " If the file doesn't support tag listing, skip it
+        if !s:Tlist_Skip_File(curbuf_name, curbuf_ftype)
+            call s:Tlist_Window_Refresh_File(curbuf_name, curbuf_ftype)
+        endif
+    endif
+
+    if g:Tlist_File_Fold_Auto_Close
+        " Open the fold for the current file, as all the folds in
+        " the taglist window are closed
+        let fidx = s:Tlist_Get_File_Index(curbuf_name)
+        if fidx != -1
+            exe "silent! " . s:tlist_{fidx}_start . "," .
+                        \ s:tlist_{fidx}_end . "foldopen!"
+        endif
+    endif
+
+    " Highlight the current tag
+    call s:Tlist_Window_Highlight_Tag(curbuf_name, cur_lnum, 1, 1)
+endfunction
+
+" Tlist_Window_Toggle()
+" Open or close a taglist window
+function! s:Tlist_Window_Toggle()
+    call s:Tlist_Log_Msg('Tlist_Window_Toggle()')
+    " If taglist window is open then close it.
+    let winnum = bufwinnr(g:TagList_title)
+    if winnum != -1
+        call s:Tlist_Window_Close()
+        return
+    endif
+
+    call s:Tlist_Window_Open()
+
+    " Go back to the original window, if Tlist_GainFocus_On_ToggleOpen is not
+    " set
+    if !g:Tlist_GainFocus_On_ToggleOpen
+        call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
+    endif
+
+    " Update the taglist menu
+    if g:Tlist_Show_Menu
+        call s:Tlist_Menu_Update_File(0)
+    endif
+endfunction
+
+" Tlist_Process_Filelist
+" Process multiple files. Each filename is separated by "\n"
+" Returns the number of processed files
+function! s:Tlist_Process_Filelist(file_names)
+    let flist = a:file_names
+
+    " Enable lazy screen updates
+    let old_lazyredraw = &lazyredraw
+    set lazyredraw
+
+    " Keep track of the number of processed files
+    let fcnt = 0
+
+    " Process one file at a time
+    while flist != ''
+        let nl_idx = stridx(flist, "\n")
+        let one_file = strpart(flist, 0, nl_idx)
+
+        " Remove the filename from the list
+        let flist = strpart(flist, nl_idx + 1)
+
+        if one_file == ''
+            continue
+        endif
+
+        " Skip directories
+        if isdirectory(one_file)
+            continue
+        endif
+
+        let ftype = s:Tlist_Detect_Filetype(one_file)
+
+        echon "\r                                                              "
+        echon "\rProcessing tags for " . fnamemodify(one_file, ':p:t')
+
+        let fcnt = fcnt + 1
+
+        call Tlist_Update_File(one_file, ftype)
+    endwhile
+
+    " Clear the displayed informational messages
+    echon "\r                                                            "
+
+    " Restore the previous state
+    let &lazyredraw = old_lazyredraw
+
+    return fcnt
+endfunction
+
+" Tlist_Process_Dir
+" Process the files in a directory matching the specified pattern
+function! s:Tlist_Process_Dir(dir_name, pat)
+    let flist = glob(a:dir_name . '/' . a:pat) . "\n"
+
+    let fcnt = s:Tlist_Process_Filelist(flist)
+
+    let len = strlen(a:dir_name)
+    if a:dir_name[len - 1] == '\' || a:dir_name[len - 1] == '/'
+        let glob_expr = a:dir_name . '*'
+    else
+        let glob_expr = a:dir_name . '/*'
+    endif
+    let all_files = glob(glob_expr) . "\n"
+
+    while all_files != ''
+        let nl_idx = stridx(all_files, "\n")
+        let one_file = strpart(all_files, 0, nl_idx)
+
+        let all_files = strpart(all_files, nl_idx + 1)
+        if one_file == ''
+            continue
+        endif
+
+        " Skip non-directory names
+        if !isdirectory(one_file)
+            continue
+        endif
+
+        echon "\r                                                              "
+        echon "\rProcessing files in directory " . fnamemodify(one_file, ':t')
+        let fcnt = fcnt + s:Tlist_Process_Dir(one_file, a:pat)
+    endwhile
+
+    return fcnt
+endfunction
+
+" Tlist_Add_Files_Recursive
+" Add files recursively from a directory
+function! s:Tlist_Add_Files_Recursive(dir, ...)
+    let dir_name = fnamemodify(a:dir, ':p')
+    if !isdirectory(dir_name)
+        call s:Tlist_Warning_Msg('Error: ' . dir_name . ' is not a directory')
+        return
+    endif
+
+    if a:0 == 1
+        " User specified file pattern
+        let pat = a:1
+    else
+        " Default file pattern
+        let pat = '*'
+    endif
+
+    echon "\r                                                              "
+    echon "\rProcessing files in directory " . fnamemodify(dir_name, ':t')
+    let fcnt = s:Tlist_Process_Dir(dir_name, pat)
+
+    echon "\rAdded " . fcnt . " files to the taglist"
+endfunction
+
+" Tlist_Add_Files
+" Add the specified list of files to the taglist
+function! s:Tlist_Add_Files(...)
+    let flist = ''
+    let i = 1
+
+    " Get all the files matching the file patterns supplied as argument
+    while i <= a:0
+        let flist = flist . glob(a:{i}) . "\n"
+        let i = i + 1
+    endwhile
+
+    if flist == ''
+        call s:Tlist_Warning_Msg('Error: No matching files are found')
+        return
+    endif
+
+    let fcnt = s:Tlist_Process_Filelist(flist)
+    echon "\rAdded " . fcnt . " files to the taglist"
+endfunction
+
+" Tlist_Extract_Tagtype
+" Extract the tag type from the tag text
+function! s:Tlist_Extract_Tagtype(tag_line)
+    " The tag type is after the tag prototype field. The prototype field
+    " ends with the /;"\t string. We add 4 at the end to skip the characters
+    " in this special string..
+    let start = strridx(a:tag_line, '/;"' . "\t") + 4
+    let end = strridx(a:tag_line, 'line:') - 1
+    let ttype = strpart(a:tag_line, start, end - start)
+
+    return ttype
+endfunction
+
+" Tlist_Extract_Tag_Scope
+" Extract the tag scope from the tag text
+function! s:Tlist_Extract_Tag_Scope(tag_line)
+    let start = strridx(a:tag_line, 'line:')
+    let end = strridx(a:tag_line, "\t")
+    if end <= start
+        return ''
+    endif
+
+    let tag_scope = strpart(a:tag_line, end + 1)
+    let tag_scope = strpart(tag_scope, stridx(tag_scope, ':') + 1)
+
+    return tag_scope
+endfunction
+
+" Tlist_Refresh()
+" Refresh the taglist
+function! s:Tlist_Refresh()
+    call s:Tlist_Log_Msg('Tlist_Refresh (Skip_Refresh = ' .
+                \ s:Tlist_Skip_Refresh . ', ' . bufname('%') . ')')
+    " If we are entering the buffer from one of the taglist functions, then
+    " no need to refresh the taglist window again.
+    if s:Tlist_Skip_Refresh
+        " We still need to update the taglist menu
+        if g:Tlist_Show_Menu
+            call s:Tlist_Menu_Update_File(0)
+        endif
+        return
+    endif
+
+    " If part of the winmanager plugin and not configured to process
+    " tags always and not configured to display the tags menu, then return
+    if (s:tlist_app_name == 'winmanager') && !g:Tlist_Process_File_Always
+                \ && !g:Tlist_Show_Menu
+        return
+    endif
+
+    " Skip buffers with 'buftype' set to nofile, nowrite, quickfix or help
+    if &buftype != ''
+        return
+    endif
+
+    let filename = fnamemodify(bufname('%'), ':p')
+    let ftype = s:Tlist_Get_Buffer_Filetype('%')
+
+    " If the file doesn't support tag listing, skip it
+    if s:Tlist_Skip_File(filename, ftype)
+        return
+    endif
+
+    let tlist_win = bufwinnr(g:TagList_title)
+
+    " If the taglist window is not opened and not configured to process
+    " tags always and not displaying the tags menu, then return
+    if tlist_win == -1 && !g:Tlist_Process_File_Always && !g:Tlist_Show_Menu
+        return
+    endif
+
+    let fidx = s:Tlist_Get_File_Index(filename)
+    if fidx == -1
+        " Check whether this file is removed based on user request
+        " If it is, then don't display the tags for this file
+        if s:Tlist_User_Removed_File(filename)
+            return
+        endif
+
+        " If the taglist should not be auto updated, then return
+        if !g:Tlist_Auto_Update
+            return
+        endif
+    endif
+
+    let cur_lnum = line('.')
+
+    if fidx == -1
+        " Update the tags for the file
+        let fidx = s:Tlist_Process_File(filename, ftype)
+    else
+        let mtime = getftime(filename)
+        if s:tlist_{fidx}_mtime != mtime
+            " Invalidate the tags listed for this file
+            let s:tlist_{fidx}_valid = 0
+
+            " Update the taglist and the window
+            call Tlist_Update_File(filename, ftype)
+
+            " Store the new file modification time
+            let s:tlist_{fidx}_mtime = mtime
+        endif
+    endif
+
+    " Update the taglist window
+    if tlist_win != -1
+        " Disable screen updates
+        let old_lazyredraw = &lazyredraw
+        set nolazyredraw
+
+        " Save the current window number
+        let save_winnr = winnr()
+
+        " Goto the taglist window
+        call s:Tlist_Window_Goto_Window()
+
+        if !g:Tlist_Auto_Highlight_Tag || !g:Tlist_Highlight_Tag_On_BufEnter
+            " Save the cursor position
+            let save_line = line('.')
+            let save_col = col('.')
+        endif
+
+        " Update the taglist window
+        call s:Tlist_Window_Refresh_File(filename, ftype)
+
+        " Open the fold for the file
+        exe "silent! " . s:tlist_{fidx}_start . "," .
+                    \ s:tlist_{fidx}_end . "foldopen!"
+
+        if g:Tlist_Highlight_Tag_On_BufEnter && g:Tlist_Auto_Highlight_Tag
+            if g:Tlist_Show_One_File && s:tlist_cur_file_idx != fidx
+                " If displaying tags for only one file in the taglist
+                " window and about to display the tags for a new file,
+                " then center the current tag line for the new file
+                let center_tag_line = 1
+            else
+                let center_tag_line = 0
+            endif
+
+            " Highlight the current tag
+            call s:Tlist_Window_Highlight_Tag(filename, cur_lnum, 1, center_tag_line)
+        else
+            " Restore the cursor position
+            if v:version >= 601
+                call cursor(save_line, save_col)
+            else
+                exe save_line
+                exe 'normal! ' . save_col . '|'
+            endif
+        endif
+
+        " Jump back to the original window
+        if save_winnr != winnr()
+            call s:Tlist_Exe_Cmd_No_Acmds(save_winnr . 'wincmd w')
+        endif
+
+        " Restore screen updates
+        let &lazyredraw = old_lazyredraw
+    endif
+
+    " Update the taglist menu
+    if g:Tlist_Show_Menu
+        call s:Tlist_Menu_Update_File(0)
+    endif
+endfunction
+
+" Tlist_Change_Sort()
+" Change the sort order of the tag listing
+" caller == 'cmd', command used in the taglist window
+" caller == 'menu', taglist menu
+" action == 'toggle', toggle sort from name to order and vice versa
+" action == 'set', set the sort order to sort_type
+function! s:Tlist_Change_Sort(caller, action, sort_type)
+    call s:Tlist_Log_Msg('Tlist_Change_Sort (caller = ' . a:caller .
+            \ ', action = ' . a:action . ', sort_type = ' . a:sort_type . ')')
+    if a:caller == 'cmd'
+        let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.'))
+        if fidx == -1
+            return
+        endif
+
+        " Remove the previous highlighting
+        match none
+    elseif a:caller == 'menu'
+        let fidx = s:Tlist_Get_File_Index(fnamemodify(bufname('%'), ':p'))
+        if fidx == -1
+            return
+        endif
+    endif
+
+    if a:action == 'toggle'
+        let sort_type = s:tlist_{fidx}_sort_type
+
+        " Toggle the sort order from 'name' to 'order' and vice versa
+        if sort_type == 'name'
+            let s:tlist_{fidx}_sort_type = 'order'
+        else
+            let s:tlist_{fidx}_sort_type = 'name'
+        endif
+    else
+        let s:tlist_{fidx}_sort_type = a:sort_type
+    endif
+
+    " Invalidate the tags listed for this file
+    let s:tlist_{fidx}_valid = 0
+
+    if a:caller  == 'cmd'
+        " Save the current line for later restoration
+        let curline = '\V\^' . getline('.') . '\$'
+
+        call s:Tlist_Window_Refresh_File(s:tlist_{fidx}_filename,
+                    \   s:tlist_{fidx}_filetype)
+
+        exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'foldopen!'
+
+        " Go back to the cursor line before the tag list is sorted
+        call search(curline, 'w')
+
+        call s:Tlist_Menu_Update_File(1)
+    else
+        call s:Tlist_Menu_Remove_File()
+
+        call s:Tlist_Refresh()
+    endif
+endfunction
+
+" Tlist_Update_Current_File()
+" Update taglist for the current buffer by regenerating the tag list
+" Contributed by WEN Guopeng.
+function! s:Tlist_Update_Current_File()
+    call s:Tlist_Log_Msg('Tlist_Update_Current_File()')
+    if winnr() == bufwinnr(g:TagList_title)
+        " In the taglist window. Update the current file
+        call s:Tlist_Window_Update_File()
+    else
+        " Not in the taglist window. Update the current buffer
+        let filename = fnamemodify(bufname('%'), ':p')
+        let fidx = s:Tlist_Get_File_Index(filename)
+        if fidx != -1
+            let s:tlist_{fidx}_valid = 0
+        endif
+        let ft = s:Tlist_Get_Buffer_Filetype('%')
+        call Tlist_Update_File(filename, ft)
+    endif
+endfunction
+
+" Tlist_Window_Update_File()
+" Update the tags displayed in the taglist window
+function! s:Tlist_Window_Update_File()
+    call s:Tlist_Log_Msg('Tlist_Window_Update_File()')
+    let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.'))
+    if fidx == -1
+        return
+    endif
+
+    " Remove the previous highlighting
+    match none
+
+    " Save the current line for later restoration
+    let curline = '\V\^' . getline('.') . '\$'
+
+    let s:tlist_{fidx}_valid = 0
+
+    " Update the taglist window
+    call s:Tlist_Window_Refresh_File(s:tlist_{fidx}_filename,
+                \ s:tlist_{fidx}_filetype)
+
+    exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'foldopen!'
+
+    " Go back to the tag line before the list is updated
+    call search(curline, 'w')
+endfunction
+
+" Tlist_Window_Get_Tag_Type_By_Linenum()
+" Return the tag type index for the specified line in the taglist window
+function! s:Tlist_Window_Get_Tag_Type_By_Linenum(fidx, lnum)
+    let ftype = s:tlist_{a:fidx}_filetype
+
+    " Determine to which tag type the current line number belongs to using the
+    " tag type start line number and the number of tags in a tag type
+    let i = 1
+    while i <= s:tlist_{ftype}_count
+        let ttype = s:tlist_{ftype}_{i}_name
+        let start_lnum =
+                    \ s:tlist_{a:fidx}_start + s:tlist_{a:fidx}_{ttype}_offset
+        let end =  start_lnum + s:tlist_{a:fidx}_{ttype}_count
+        if a:lnum >= start_lnum && a:lnum <= end
+            break
+        endif
+        let i = i + 1
+    endwhile
+
+    " Current line doesn't belong to any of the displayed tag types
+    if i > s:tlist_{ftype}_count
+        return ''
+    endif
+
+    return ttype
+endfunction
+
+" Tlist_Window_Get_Tag_Index()
+" Return the tag index for the specified line in the taglist window
+function! s:Tlist_Window_Get_Tag_Index(fidx, lnum)
+    let ttype = s:Tlist_Window_Get_Tag_Type_By_Linenum(a:fidx, a:lnum)
+
+    " Current line doesn't belong to any of the displayed tag types
+    if ttype == ''
+        return 0
+    endif
+
+    " Compute the index into the displayed tags for the tag type
+    let ttype_lnum = s:tlist_{a:fidx}_start + s:tlist_{a:fidx}_{ttype}_offset
+    let tidx = a:lnum - ttype_lnum
+    if tidx == 0
+        return 0
+    endif
+
+    " Get the corresponding tag line and return it
+    return s:tlist_{a:fidx}_{ttype}_{tidx}
+endfunction
+
+" Tlist_Window_Highlight_Line
+" Highlight the current line
+function! s:Tlist_Window_Highlight_Line()
+    " Clear previously selected name
+    match none
+
+    " Highlight the current line
+    if g:Tlist_Display_Prototype == 0
+        let pat = '/\%' . line('.') . 'l\s\+\zs.*/'
+    else
+        let pat = '/\%' . line('.') . 'l.*/'
+    endif
+
+    exe 'match TagListTagName ' . pat
+endfunction
+
+" Tlist_Window_Open_File
+" Open the specified file in either a new window or an existing window
+" and place the cursor at the specified tag pattern
+function! s:Tlist_Window_Open_File(win_ctrl, filename, tagpat)
+    call s:Tlist_Log_Msg('Tlist_Window_Open_File (' . a:filename . ',' .
+                \ a:win_ctrl . ')')
+    let prev_Tlist_Skip_Refresh = s:Tlist_Skip_Refresh
+    let s:Tlist_Skip_Refresh = 1
+
+    if s:tlist_app_name == "winmanager"
+        " Let the winmanager edit the file
+        call WinManagerFileEdit(a:filename, a:win_ctrl == 'newwin')
+    else
+
+    if a:win_ctrl == 'newtab'
+        " Create a new tab
+        exe 'tabnew ' . escape(a:filename, ' ')
+        " Open the taglist window in the new tab
+        call s:Tlist_Window_Open()
+    endif
+
+    if a:win_ctrl == 'checktab'
+        " Check whether the file is present in any of the tabs.
+        " If the file is present in the current tab, then use the
+        " current tab.
+        if bufwinnr(a:filename) != -1
+            let file_present_in_tab = 1
+            let i = tabpagenr()
+        else
+            let i = 1
+            let bnum = bufnr(a:filename)
+            let file_present_in_tab = 0
+            while i <= tabpagenr('$')
+                if index(tabpagebuflist(i), bnum) != -1
+                    let file_present_in_tab = 1
+                    break
+                endif
+                let i += 1
+            endwhile
+        endif
+
+        if file_present_in_tab
+            " Goto the tab containing the file
+            exe 'tabnext ' . i
+        else
+            " Open a new tab
+            exe 'tabnew ' . escape(a:filename, ' ')
+
+            " Open the taglist window
+            call s:Tlist_Window_Open()
+        endif
+    endif
+
+    let winnum = -1
+    if a:win_ctrl == 'prevwin'
+        " Open the file in the previous window, if it is usable
+        let cur_win = winnr()
+        wincmd p
+        if &buftype == '' && !&previewwindow
+            exe "edit " . escape(a:filename, ' ')
+            let winnum = winnr()
+        else
+            " Previous window is not usable
+            exe cur_win . 'wincmd w'
+        endif
+    endif
+
+    " Goto the window containing the file.  If the window is not there, open a
+    " new window
+    if winnum == -1
+        let winnum = bufwinnr(a:filename)
+    endif
+
+    if winnum == -1
+        " Locate the previously used window for opening a file
+        let fwin_num = 0
+        let first_usable_win = 0
+
+        let i = 1
+        let bnum = winbufnr(i)
+        while bnum != -1
+            if getwinvar(i, 'tlist_file_window') == 'yes'
+                let fwin_num = i
+                break
+            endif
+            if first_usable_win == 0 &&
+                        \ getbufvar(bnum, '&buftype') == '' &&
+                        \ !getwinvar(i, '&previewwindow')
+                " First non-taglist, non-plugin and non-preview window
+                let first_usable_win = i
+            endif
+            let i = i + 1
+            let bnum = winbufnr(i)
+        endwhile
+
+        " If a previously used window is not found, then use the first
+        " non-taglist window
+        if fwin_num == 0
+            let fwin_num = first_usable_win
+        endif
+
+        if fwin_num != 0
+            " Jump to the file window
+            exe fwin_num . "wincmd w"
+
+            " If the user asked to jump to the tag in a new window, then split
+            " the existing window into two.
+            if a:win_ctrl == 'newwin'
+                split
+            endif
+            exe "edit " . escape(a:filename, ' ')
+        else
+            " Open a new window
+            if g:Tlist_Use_Horiz_Window
+                exe 'leftabove split ' . escape(a:filename, ' ')
+            else
+                if winbufnr(2) == -1
+                    " Only the taglist window is present
+                    if g:Tlist_Use_Right_Window
+                        exe 'leftabove vertical split ' .
+                                    \ escape(a:filename, ' ')
+                    else
+                        exe 'rightbelow vertical split ' .
+                                    \ escape(a:filename, ' ')
+                    endif
+
+                    " Go to the taglist window to change the window size to
+                    " the user configured value
+                    call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
+                    if g:Tlist_Use_Horiz_Window
+                        exe 'resize ' . g:Tlist_WinHeight
+                    else
+                        exe 'vertical resize ' . g:Tlist_WinWidth
+                    endif
+                    " Go back to the file window
+                    call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
+                else
+                    " A plugin or help window is also present
+                    wincmd w
+                    exe 'leftabove split ' . escape(a:filename, ' ')
+                endif
+            endif
+        endif
+        " Mark the window, so that it can be reused.
+        call s:Tlist_Window_Mark_File_Window()
+    else
+        if v:version >= 700
+            " If the file is opened in more than one window, then check
+            " whether the last accessed window has the selected file.
+            " If it does, then use that window.
+            let lastwin_bufnum = winbufnr(winnr('#'))
+            if bufnr(a:filename) == lastwin_bufnum
+                let winnum = winnr('#')
+            endif
+        endif
+        exe winnum . 'wincmd w'
+
+        " If the user asked to jump to the tag in a new window, then split the
+        " existing window into two.
+        if a:win_ctrl == 'newwin'
+            split
+        endif
+    endif
+    endif
+
+    " Jump to the tag
+    if a:tagpat != ''
+        " Add the current cursor position to the jump list, so that user can
+        " jump back using the ' and ` marks.
+        mark '
+        silent call search(a:tagpat, 'w')
+
+        " Bring the line to the middle of the window
+        normal! z.
+
+        " If the line is inside a fold, open the fold
+        if foldclosed('.') != -1
+            .foldopen
+        endif
+    endif
+
+    " If the user selects to preview the tag then jump back to the
+    " taglist window
+    if a:win_ctrl == 'preview'
+        " Go back to the taglist window
+        let winnum = bufwinnr(g:TagList_title)
+        exe winnum . 'wincmd w'
+    else
+        " If the user has selected to close the taglist window, when a
+        " tag is selected, close the taglist  window
+        if g:Tlist_Close_On_Select
+            call s:Tlist_Window_Goto_Window()
+            close
+
+            " Go back to the window displaying the selected file
+            let wnum = bufwinnr(a:filename)
+            if wnum != -1 && wnum != winnr()
+                call s:Tlist_Exe_Cmd_No_Acmds(wnum . 'wincmd w')
+            endif
+        endif
+    endif
+
+    let s:Tlist_Skip_Refresh = prev_Tlist_Skip_Refresh
+endfunction
+
+" Tlist_Window_Jump_To_Tag()
+" Jump to the location of the current tag
+" win_ctrl == useopen - Reuse the existing file window
+" win_ctrl == newwin - Open a new window
+" win_ctrl == preview - Preview the tag
+" win_ctrl == prevwin - Open in previous window
+" win_ctrl == newtab - Open in new tab
+function! s:Tlist_Window_Jump_To_Tag(win_ctrl)
+    call s:Tlist_Log_Msg('Tlist_Window_Jump_To_Tag(' . a:win_ctrl . ')')
+    " Do not process comment lines and empty lines
+    let curline = getline('.')
+    if curline =~ '^\s*$' || curline[0] == '"'
+        return
+    endif
+
+    " If inside a closed fold, then use the first line of the fold
+    " and jump to the file.
+    let lnum = foldclosed('.')
+    if lnum == -1
+        " Jump to the selected tag or file
+        let lnum = line('.')
+    else
+        " Open the closed fold
+        .foldopen!
+    endif
+
+    let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(lnum)
+    if fidx == -1
+        return
+    endif
+
+    " Get the tag output for the current tag
+    let tidx = s:Tlist_Window_Get_Tag_Index(fidx, lnum)
+    if tidx != 0
+        let tagpat = s:Tlist_Get_Tag_SearchPat(fidx, tidx)
+
+        " Highlight the tagline
+        call s:Tlist_Window_Highlight_Line()
+    else
+        " Selected a line which is not a tag name. Just edit the file
+        let tagpat = ''
+    endif
+
+    call s:Tlist_Window_Open_File(a:win_ctrl, s:tlist_{fidx}_filename, tagpat)
+endfunction
+
+" Tlist_Window_Show_Info()
+" Display information about the entry under the cursor
+function! s:Tlist_Window_Show_Info()
+    call s:Tlist_Log_Msg('Tlist_Window_Show_Info()')
+
+    " Clear the previously displayed line
+    echo
+
+    " Do not process comment lines and empty lines
+    let curline = getline('.')
+    if curline =~ '^\s*$' || curline[0] == '"'
+        return
+    endif
+
+    " If inside a fold, then don't display the prototype
+    if foldclosed('.') != -1
+        return
+    endif
+
+    let lnum = line('.')
+
+    " Get the file index
+    let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(lnum)
+    if fidx == -1
+        return
+    endif
+
+    if lnum == s:tlist_{fidx}_start
+        " Cursor is on a file name
+        let fname = s:tlist_{fidx}_filename
+        if strlen(fname) > 50
+            let fname = fnamemodify(fname, ':t')
+        endif
+        echo fname . ', Filetype=' . s:tlist_{fidx}_filetype .
+                    \  ', Tag count=' . s:tlist_{fidx}_tag_count
+        return
+    endif
+
+    " Get the tag output line for the current tag
+    let tidx = s:Tlist_Window_Get_Tag_Index(fidx, lnum)
+    if tidx == 0
+        " Cursor is on a tag type
+        let ttype = s:Tlist_Window_Get_Tag_Type_By_Linenum(fidx, lnum)
+        if ttype == ''
+            return
+        endif
+
+        let ttype_name = ''
+
+        let ftype = s:tlist_{fidx}_filetype
+        let i = 1
+        while i <= s:tlist_{ftype}_count
+            if ttype == s:tlist_{ftype}_{i}_name
+                let ttype_name = s:tlist_{ftype}_{i}_fullname
+                break
+            endif
+            let i = i + 1
+        endwhile
+
+        echo 'Tag type=' . ttype_name .
+                    \ ', Tag count=' . s:tlist_{fidx}_{ttype}_count
+        return
+    endif
+
+    " Get the tag search pattern and display it
+    echo s:Tlist_Get_Tag_Prototype(fidx, tidx)
+endfunction
+
+" Tlist_Find_Nearest_Tag_Idx
+" Find the tag idx nearest to the supplied line number
+" Returns -1, if a tag couldn't be found for the specified line number
+function! s:Tlist_Find_Nearest_Tag_Idx(fidx, linenum)
+    let sort_type = s:tlist_{a:fidx}_sort_type
+
+    let left = 1
+    let right = s:tlist_{a:fidx}_tag_count
+
+    if sort_type == 'order'
+        " Tags sorted by order, use a binary search.
+        " The idea behind this function is taken from the ctags.vim script (by
+        " Alexey Marinichev) available at the Vim online website.
+
+        " If the current line is the less than the first tag, then no need to
+        " search
+        let first_lnum = s:Tlist_Get_Tag_Linenum(a:fidx, 1)
+
+        if a:linenum < first_lnum
+            return -1
+        endif
+
+        while left < right
+            let middle = (right + left + 1) / 2
+            let middle_lnum = s:Tlist_Get_Tag_Linenum(a:fidx, middle)
+
+            if middle_lnum == a:linenum
+                let left = middle
+                break
+            endif
+
+            if middle_lnum > a:linenum
+                let right = middle - 1
+            else
+                let left = middle
+            endif
+        endwhile
+    else
+        " Tags sorted by name, use a linear search. (contributed by Dave
+        " Eggum).
+        " Look for a tag with a line number less than or equal to the supplied
+        " line number. If multiple tags are found, then use the tag with the
+        " line number closest to the supplied line number. IOW, use the tag
+        " with the highest line number.
+        let closest_lnum = 0
+        let final_left = 0
+        while left <= right
+            let lnum = s:Tlist_Get_Tag_Linenum(a:fidx, left)
+
+            if lnum < a:linenum && lnum > closest_lnum
+                let closest_lnum = lnum
+                let final_left = left
+            elseif lnum == a:linenum
+                let closest_lnum = lnum
+                let final_left = left
+                break
+            else
+                let left = left + 1
+            endif
+        endwhile
+        if closest_lnum == 0
+            return -1
+        endif
+        if left >= right
+            let left = final_left
+        endif
+    endif
+
+    return left
+endfunction
+
+" Tlist_Window_Highlight_Tag()
+" Highlight the current tag
+" cntx == 1, Called by the taglist plugin itself
+" cntx == 2, Forced by the user through the TlistHighlightTag command
+" center = 1, move the tag line to the center of the taglist window
+function! s:Tlist_Window_Highlight_Tag(filename, cur_lnum, cntx, center)
+    " Highlight the current tag only if the user configured the
+    " taglist plugin to do so or if the user explictly invoked the
+    " command to highlight the current tag.
+    if !g:Tlist_Auto_Highlight_Tag && a:cntx == 1
+        return
+    endif
+
+    if a:filename == ''
+        return
+    endif
+
+    " Make sure the taglist window is present
+    let winnum = bufwinnr(g:TagList_title)
+    if winnum == -1
+        call s:Tlist_Warning_Msg('Error: Taglist window is not open')
+        return
+    endif
+
+    let fidx = s:Tlist_Get_File_Index(a:filename)
+    if fidx == -1
+        return
+    endif
+
+    " If the file is currently not displayed in the taglist window, then retrn
+    if !s:tlist_{fidx}_visible
+        return
+    endif
+
+    " If there are no tags for this file, then no need to proceed further
+    if s:tlist_{fidx}_tag_count == 0
+        return
+    endif
+
+    " Ignore all autocommands
+    let old_ei = &eventignore
+    set eventignore=all
+
+    " Save the original window number
+    let org_winnr = winnr()
+
+    if org_winnr == winnum
+        let in_taglist_window = 1
+    else
+        let in_taglist_window = 0
+    endif
+
+    " Go to the taglist window
+    if !in_taglist_window
+        exe winnum . 'wincmd w'
+    endif
+
+    " Clear previously selected name
+    match none
+
+    let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, a:cur_lnum)
+    if tidx == -1
+        " Make sure the current tag line is visible in the taglist window.
+        " Calling the winline() function makes the line visible.  Don't know
+        " of a better way to achieve this.
+        let lnum = line('.')
+
+        if lnum < s:tlist_{fidx}_start || lnum > s:tlist_{fidx}_end
+            " Move the cursor to the beginning of the file
+            exe s:tlist_{fidx}_start
+        endif
+
+        if foldclosed('.') != -1
+            .foldopen
+        endif
+
+        call winline()
+
+        if !in_taglist_window
+            exe org_winnr . 'wincmd w'
+        endif
+
+        " Restore the autocommands
+        let &eventignore = old_ei
+        return
+    endif
+
+    " Extract the tag type
+    let ttype = s:Tlist_Get_Tag_Type_By_Tag(fidx, tidx)
+
+    " Compute the line number
+    " Start of file + Start of tag type + offset
+    let lnum = s:tlist_{fidx}_start + s:tlist_{fidx}_{ttype}_offset +
+                \ s:tlist_{fidx}_{tidx}_ttype_idx
+
+    " Goto the line containing the tag
+    exe lnum
+
+    " Open the fold
+    if foldclosed('.') != -1
+        .foldopen
+    endif
+
+    if a:center
+        " Move the tag line to the center of the taglist window
+        normal! z.
+    else
+        " Make sure the current tag line is visible in the taglist window.
+        " Calling the winline() function makes the line visible.  Don't know
+        " of a better way to achieve this.
+        call winline()
+    endif
+
+    " Highlight the tag name
+    call s:Tlist_Window_Highlight_Line()
+
+    " Go back to the original window
+    if !in_taglist_window
+        exe org_winnr . 'wincmd w'
+    endif
+
+    " Restore the autocommands
+    let &eventignore = old_ei
+    return
+endfunction
+
+" Tlist_Get_Tag_Prototype_By_Line
+" Get the prototype for the tag on or before the specified line number in the
+" current buffer
+function! Tlist_Get_Tag_Prototype_By_Line(...)
+    if a:0 == 0
+        " Arguments are not supplied. Use the current buffer name
+        " and line number
+        let filename = bufname('%')
+        let linenr = line('.')
+    elseif a:0 == 2
+        " Filename and line number are specified
+        let filename = a:1
+        let linenr = a:2
+        if linenr !~ '\d\+'
+            " Invalid line number
+            return ""
+        endif
+    else
+        " Sufficient arguments are not supplied
+        let msg =  'Usage: Tlist_Get_Tag_Prototype_By_Line <filename> ' .
+                                \ '<line_number>'
+        call s:Tlist_Warning_Msg(msg)
+        return ""
+    endif
+
+    " Expand the file to a fully qualified name
+    let filename = fnamemodify(filename, ':p')
+    if filename == ''
+        return ""
+    endif
+
+    let fidx = s:Tlist_Get_File_Index(filename)
+    if fidx == -1
+        return ""
+    endif
+
+    " If there are no tags for this file, then no need to proceed further
+    if s:tlist_{fidx}_tag_count == 0
+        return ""
+    endif
+
+    " Get the tag text using the line number
+    let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, linenr)
+    if tidx == -1
+        return ""
+    endif
+
+    return s:Tlist_Get_Tag_Prototype(fidx, tidx)
+endfunction
+
+" Tlist_Get_Tagname_By_Line
+" Get the tag name on or before the specified line number in the
+" current buffer
+function! Tlist_Get_Tagname_By_Line(...)
+    if a:0 == 0
+        " Arguments are not supplied. Use the current buffer name
+        " and line number
+        let filename = bufname('%')
+        let linenr = line('.')
+    elseif a:0 == 2
+        " Filename and line number are specified
+        let filename = a:1
+        let linenr = a:2
+        if linenr !~ '\d\+'
+            " Invalid line number
+            return ""
+        endif
+    else
+        " Sufficient arguments are not supplied
+        let msg =  'Usage: Tlist_Get_Tagname_By_Line <filename> <line_number>'
+        call s:Tlist_Warning_Msg(msg)
+        return ""
+    endif
+
+    " Make sure the current file has a name
+    let filename = fnamemodify(filename, ':p')
+    if filename == ''
+        return ""
+    endif
+
+    let fidx = s:Tlist_Get_File_Index(filename)
+    if fidx == -1
+        return ""
+    endif
+
+    " If there are no tags for this file, then no need to proceed further
+    if s:tlist_{fidx}_tag_count == 0
+        return ""
+    endif
+
+    " Get the tag name using the line number
+    let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, linenr)
+    if tidx == -1
+        return ""
+    endif
+
+    return s:tlist_{fidx}_{tidx}_tag_name
+endfunction
+
+" Tlist_Window_Move_To_File
+" Move the cursor to the beginning of the current file or the next file
+" or the previous file in the taglist window
+" dir == -1, move to start of current or previous function
+" dir == 1, move to start of next function
+function! s:Tlist_Window_Move_To_File(dir)
+    if foldlevel('.') == 0
+        " Cursor is on a non-folded line (it is not in any of the files)
+        " Move it to a folded line
+        if a:dir == -1
+            normal! zk
+        else
+            " While moving down to the start of the next fold,
+            " no need to do go to the start of the next file.
+            normal! zj
+            return
+        endif
+    endif
+
+    let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.'))
+    if fidx == -1
+        return
+    endif
+
+    let cur_lnum = line('.')
+
+    if a:dir == -1
+        if cur_lnum > s:tlist_{fidx}_start
+            " Move to the beginning of the current file
+            exe s:tlist_{fidx}_start
+            return
+        endif
+
+        if fidx != 0
+            " Move to the beginning of the previous file
+            let fidx = fidx - 1
+        else
+            " Cursor is at the first file, wrap around to the last file
+            let fidx = s:tlist_file_count - 1
+        endif
+
+        exe s:tlist_{fidx}_start
+        return
+    else
+        " Move to the beginning of the next file
+        let fidx = fidx + 1
+
+        if fidx >= s:tlist_file_count
+            " Cursor is at the last file, wrap around to the first file
+            let fidx = 0
+        endif
+
+        if s:tlist_{fidx}_start != 0
+            exe s:tlist_{fidx}_start
+        endif
+        return
+    endif
+endfunction
+
+" Tlist_Session_Load
+" Load a taglist session (information about all the displayed files
+" and the tags) from the specified file
+function! s:Tlist_Session_Load(...)
+    if a:0 == 0 || a:1 == ''
+        call s:Tlist_Warning_Msg('Usage: TlistSessionLoad <filename>')
+        return
+    endif
+
+    let sessionfile = a:1
+
+    if !filereadable(sessionfile)
+        let msg = 'Taglist: Error - Unable to open file ' . sessionfile
+        call s:Tlist_Warning_Msg(msg)
+        return
+    endif
+
+    " Mark the current window as the file window
+    call s:Tlist_Window_Mark_File_Window()
+
+    " Source the session file
+    exe 'source ' . sessionfile
+
+    let new_file_count = g:tlist_file_count
+    unlet! g:tlist_file_count
+
+    let i = 0
+    while i < new_file_count
+        let ftype = g:tlist_{i}_filetype
+        unlet! g:tlist_{i}_filetype
+
+        if !exists('s:tlist_' . ftype . '_count')
+            if s:Tlist_FileType_Init(ftype) == 0
+                let i = i + 1
+                continue
+            endif
+        endif
+
+        let fname = g:tlist_{i}_filename
+        unlet! g:tlist_{i}_filename
+
+        let fidx = s:Tlist_Get_File_Index(fname)
+        if fidx != -1
+            let s:tlist_{fidx}_visible = 0
+            let i = i + 1
+            continue
+        else
+            " As we are loading the tags from the session file, if this
+            " file was previously deleted by the user, now we need to
+            " add it back. So remove the file from the deleted list.
+            call s:Tlist_Update_Remove_List(fname, 0)
+        endif
+
+        let fidx = s:Tlist_Init_File(fname, ftype)
+
+        let s:tlist_{fidx}_filename = fname
+
+        let s:tlist_{fidx}_sort_type = g:tlist_{i}_sort_type
+        unlet! g:tlist_{i}_sort_type
+
+        let s:tlist_{fidx}_filetype = ftype
+        let s:tlist_{fidx}_mtime = getftime(fname)
+
+        let s:tlist_{fidx}_start = 0
+        let s:tlist_{fidx}_end = 0
+
+        let s:tlist_{fidx}_valid = 1
+
+        let s:tlist_{fidx}_tag_count = g:tlist_{i}_tag_count
+        unlet! g:tlist_{i}_tag_count
+
+        let j = 1
+        while j <= s:tlist_{fidx}_tag_count
+            let s:tlist_{fidx}_{j}_tag = g:tlist_{i}_{j}_tag
+            let s:tlist_{fidx}_{j}_tag_name = g:tlist_{i}_{j}_tag_name
+            let s:tlist_{fidx}_{j}_ttype_idx = g:tlist_{i}_{j}_ttype_idx
+            unlet! g:tlist_{i}_{j}_tag
+            unlet! g:tlist_{i}_{j}_tag_name
+            unlet! g:tlist_{i}_{j}_ttype_idx
+            let j = j + 1
+        endwhile
+
+        let j = 1
+        while j <= s:tlist_{ftype}_count
+            let ttype = s:tlist_{ftype}_{j}_name
+
+            if exists('g:tlist_' . i . '_' . ttype)
+                let s:tlist_{fidx}_{ttype} = g:tlist_{i}_{ttype}
+                unlet! g:tlist_{i}_{ttype}
+                let s:tlist_{fidx}_{ttype}_offset = 0
+                let s:tlist_{fidx}_{ttype}_count = g:tlist_{i}_{ttype}_count
+                unlet! g:tlist_{i}_{ttype}_count
+
+                let k = 1
+                while k <= s:tlist_{fidx}_{ttype}_count
+                    let s:tlist_{fidx}_{ttype}_{k} = g:tlist_{i}_{ttype}_{k}
+                    unlet! g:tlist_{i}_{ttype}_{k}
+                    let k = k + 1
+                endwhile
+            else
+                let s:tlist_{fidx}_{ttype} = ''
+                let s:tlist_{fidx}_{ttype}_offset = 0
+                let s:tlist_{fidx}_{ttype}_count = 0
+            endif
+
+            let j = j + 1
+        endwhile
+
+        let i = i + 1
+    endwhile
+
+    " If the taglist window is open, then update it
+    let winnum = bufwinnr(g:TagList_title)
+    if winnum != -1
+        let save_winnr = winnr()
+
+        " Goto the taglist window
+        call s:Tlist_Window_Goto_Window()
+
+        " Refresh the taglist window
+        call s:Tlist_Window_Refresh()
+
+        " Go back to the original window
+        if save_winnr != winnr()
+            call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
+        endif
+    endif
+endfunction
+
+" Tlist_Session_Save
+" Save a taglist session (information about all the displayed files
+" and the tags) into the specified file
+function! s:Tlist_Session_Save(...)
+    if a:0 == 0 || a:1 == ''
+        call s:Tlist_Warning_Msg('Usage: TlistSessionSave <filename>')
+        return
+    endif
+
+    let sessionfile = a:1
+
+    if s:tlist_file_count == 0
+        " There is nothing to save
+        call s:Tlist_Warning_Msg('Warning: Taglist is empty. Nothing to save.')
+        return
+    endif
+
+    if filereadable(sessionfile)
+        let ans = input('Do you want to overwrite ' . sessionfile . ' (Y/N)?')
+        if ans !=? 'y'
+            return
+        endif
+
+        echo "\n"
+    endif
+
+    let old_verbose = &verbose
+    set verbose&vim
+
+    exe 'redir! > ' . sessionfile
+
+    silent! echo '" Taglist session file. This file is auto-generated.'
+    silent! echo '" File information'
+    silent! echo 'let tlist_file_count = ' . s:tlist_file_count
+
+    let i = 0
+
+    while i < s:tlist_file_count
+        " Store information about the file
+        silent! echo 'let tlist_' . i . "_filename = '" .
+                                            \ s:tlist_{i}_filename . "'"
+        silent! echo 'let tlist_' . i . '_sort_type = "' .
+                                                \ s:tlist_{i}_sort_type . '"'
+        silent! echo 'let tlist_' . i . '_filetype = "' .
+                                            \ s:tlist_{i}_filetype . '"'
+        silent! echo 'let tlist_' . i . '_tag_count = ' .
+                                                        \ s:tlist_{i}_tag_count
+        " Store information about all the tags
+        let j = 1
+        while j <= s:tlist_{i}_tag_count
+            let txt = escape(s:tlist_{i}_{j}_tag, '"\\')
+            silent! echo 'let tlist_' . i . '_' . j . '_tag = "' . txt . '"'
+            silent! echo 'let tlist_' . i . '_' . j . '_tag_name = "' .
+                        \ s:tlist_{i}_{j}_tag_name . '"'
+            silent! echo 'let tlist_' . i . '_' . j . '_ttype_idx' . ' = ' .
+                        \ s:tlist_{i}_{j}_ttype_idx
+            let j = j + 1
+        endwhile
+
+        " Store information about all the tags grouped by their type
+        let ftype = s:tlist_{i}_filetype
+        let j = 1
+        while j <= s:tlist_{ftype}_count
+            let ttype = s:tlist_{ftype}_{j}_name
+            if s:tlist_{i}_{ttype}_count != 0
+                let txt = escape(s:tlist_{i}_{ttype}, '"\')
+                let txt = substitute(txt, "\n", "\\\\n", 'g')
+                silent! echo 'let tlist_' . i . '_' . ttype . ' = "' .
+                                                \ txt . '"'
+                silent! echo 'let tlist_' . i . '_' . ttype . '_count = ' .
+                                                     \ s:tlist_{i}_{ttype}_count
+                let k = 1
+                while k <= s:tlist_{i}_{ttype}_count
+                    silent! echo 'let tlist_' . i . '_' . ttype . '_' . k .
+                                \ ' = ' . s:tlist_{i}_{ttype}_{k}
+                    let k = k + 1
+                endwhile
+            endif
+            let j = j + 1
+        endwhile
+
+        silent! echo
+
+        let i = i + 1
+    endwhile
+
+    redir END
+
+    let &verbose = old_verbose
+endfunction
+
+" Tlist_Buffer_Removed
+" A buffer is removed from the Vim buffer list. Remove the tags defined
+" for that file
+function! s:Tlist_Buffer_Removed(filename)
+    call s:Tlist_Log_Msg('Tlist_Buffer_Removed (' . a:filename .  ')')
+
+    " Make sure a valid filename is supplied
+    if a:filename == ''
+        return
+    endif
+
+    " Get tag list index of the specified file
+    let fidx = s:Tlist_Get_File_Index(a:filename)
+    if fidx == -1
+        " File not present in the taglist
+        return
+    endif
+
+    " Remove the file from the list
+    call s:Tlist_Remove_File(fidx, 0)
+endfunction
+
+" When a buffer is deleted, remove the file from the taglist
+autocmd BufDelete * silent call s:Tlist_Buffer_Removed(expand('<afile>:p'))
+
+" Tlist_Window_Open_File_Fold
+" Open the fold for the specified file and close the fold for all the
+" other files
+function! s:Tlist_Window_Open_File_Fold(acmd_bufnr)
+    call s:Tlist_Log_Msg('Tlist_Window_Open_File_Fold (' . a:acmd_bufnr . ')')
+
+    " Make sure the taglist window is present
+    let winnum = bufwinnr(g:TagList_title)
+    if winnum == -1
+        call s:Tlist_Warning_Msg('Taglist: Error - Taglist window is not open')
+        return
+    endif
+
+    " Save the original window number
+    let org_winnr = winnr()
+    if org_winnr == winnum
+        let in_taglist_window = 1
+    else
+        let in_taglist_window = 0
+    endif
+
+    if in_taglist_window
+        " When entering the taglist window, no need to update the folds
+        return
+    endif
+
+    " Go to the taglist window
+    if !in_taglist_window
+        call s:Tlist_Exe_Cmd_No_Acmds(winnum . 'wincmd w')
+    endif
+
+    " Close all the folds
+    silent! %foldclose
+
+    " Get tag list index of the specified file
+    let fname = fnamemodify(bufname(a:acmd_bufnr + 0), ':p')
+    if filereadable(fname)
+        let fidx = s:Tlist_Get_File_Index(fname)
+        if fidx != -1
+            " Open the fold for the file
+            exe "silent! " . s:tlist_{fidx}_start . "," .
+                        \ s:tlist_{fidx}_end . "foldopen"
+        endif
+    endif
+
+    " Go back to the original window
+    if !in_taglist_window
+        call s:Tlist_Exe_Cmd_No_Acmds(org_winnr . 'wincmd w')
+    endif
+endfunction
+
+" Tlist_Window_Check_Auto_Open
+" Open the taglist window automatically on Vim startup.
+" Open the window only when files present in any of the Vim windows support
+" tags.
+function! s:Tlist_Window_Check_Auto_Open()
+    let open_window = 0
+
+    let i = 1
+    let buf_num = winbufnr(i)
+    while buf_num != -1
+        let filename = fnamemodify(bufname(buf_num), ':p')
+        let ft = s:Tlist_Get_Buffer_Filetype(buf_num)
+        if !s:Tlist_Skip_File(filename, ft)
+            let open_window = 1
+            break
+        endif
+        let i = i + 1
+        let buf_num = winbufnr(i)
+    endwhile
+
+    if open_window
+        call s:Tlist_Window_Toggle()
+    endif
+endfunction
+
+" Tlist_Refresh_Folds
+" Remove and create the folds for all the files displayed in the taglist
+" window. Used after entering a tab. If this is not done, then the folds
+" are not properly created for taglist windows displayed in multiple tabs.
+function! s:Tlist_Refresh_Folds()
+    let winnum = bufwinnr(g:TagList_title)
+    if winnum == -1
+        return
+    endif
+
+    let save_wnum = winnr()
+    exe winnum . 'wincmd w'
+
+    " First remove all the existing folds
+    normal! zE
+
+    " Create the folds for each in the tag list
+    let fidx = 0
+    while fidx < s:tlist_file_count
+        let ftype = s:tlist_{fidx}_filetype
+
+        " Create the folds for each tag type in a file
+        let j = 1
+        while j <= s:tlist_{ftype}_count
+            let ttype = s:tlist_{ftype}_{j}_name
+            if s:tlist_{fidx}_{ttype}_count
+                let s = s:tlist_{fidx}_start + s:tlist_{fidx}_{ttype}_offset
+                let e = s + s:tlist_{fidx}_{ttype}_count
+                exe s . ',' . e . 'fold'
+            endif
+            let j = j + 1
+        endwhile
+
+        exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'fold'
+        exe 'silent! ' . s:tlist_{fidx}_start . ',' .
+                    \ s:tlist_{fidx}_end . 'foldopen!'
+        let fidx = fidx + 1
+    endwhile
+
+    exe save_wnum . 'wincmd w'
+endfunction
+
+function! s:Tlist_Menu_Add_Base_Menu()
+    call s:Tlist_Log_Msg('Adding the base menu')
+
+    " Add the menu
+    anoremenu <silent> T&ags.Refresh\ menu :call <SID>Tlist_Menu_Refresh()<CR>
+    anoremenu <silent> T&ags.Sort\ menu\ by.Name
+                    \ :call <SID>Tlist_Change_Sort('menu', 'set', 'name')<CR>
+    anoremenu <silent> T&ags.Sort\ menu\ by.Order
+                    \ :call <SID>Tlist_Change_Sort('menu', 'set', 'order')<CR>
+    anoremenu T&ags.-SEP1-           :
+
+    if &mousemodel =~ 'popup'
+        anoremenu <silent> PopUp.T&ags.Refresh\ menu
+                    \ :call <SID>Tlist_Menu_Refresh()<CR>
+        anoremenu <silent> PopUp.T&ags.Sort\ menu\ by.Name
+                  \ :call <SID>Tlist_Change_Sort('menu', 'set', 'name')<CR>
+        anoremenu <silent> PopUp.T&ags.Sort\ menu\ by.Order
+                  \ :call <SID>Tlist_Change_Sort('menu', 'set', 'order')<CR>
+        anoremenu PopUp.T&ags.-SEP1-           :
+    endif
+endfunction
+
+let s:menu_char_prefix =
+            \ '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+
+" Tlist_Menu_Get_Tag_Type_Cmd
+" Get the menu command for the specified tag type
+" fidx - File type index
+" ftype - File Type
+" add_ttype_name - To add or not to add the tag type name to the menu entries
+" ttype_idx - Tag type index
+function! s:Tlist_Menu_Get_Tag_Type_Cmd(fidx, ftype, add_ttype_name, ttype_idx)
+    " Curly brace variable name optimization
+    let ftype_ttype_idx = a:ftype . '_' . a:ttype_idx
+
+    let ttype = s:tlist_{ftype_ttype_idx}_name
+    if a:add_ttype_name
+        " If the tag type name contains space characters, escape it. This
+        " will be used to create the menu entries.
+        let ttype_fullname = escape(s:tlist_{ftype_ttype_idx}_fullname, ' ')
+    endif
+
+    " Curly brace variable name optimization
+    let fidx_ttype = a:fidx . '_' . ttype
+
+    " Number of tag entries for this tag type
+    let tcnt = s:tlist_{fidx_ttype}_count
+    if tcnt == 0 " No entries for this tag type
+        return ''
+    endif
+
+    let mcmd = ''
+
+    " Create the menu items for the tags.
+    " Depending on the number of tags of this type, split the menu into
+    " multiple sub-menus, if needed.
+    if tcnt > g:Tlist_Max_Submenu_Items
+        let j = 1
+        while j <= tcnt
+            let final_index = j + g:Tlist_Max_Submenu_Items - 1
+            if final_index > tcnt
+                let final_index = tcnt
+            endif
+
+            " Extract the first and last tag name and form the
+            " sub-menu name
+            let tidx = s:tlist_{fidx_ttype}_{j}
+            let first_tag = s:tlist_{a:fidx}_{tidx}_tag_name
+
+            let tidx = s:tlist_{fidx_ttype}_{final_index}
+            let last_tag = s:tlist_{a:fidx}_{tidx}_tag_name
+
+            " Truncate the names, if they are greater than the
+            " max length
+            let first_tag = strpart(first_tag, 0, g:Tlist_Max_Tag_Length)
+            let last_tag = strpart(last_tag, 0, g:Tlist_Max_Tag_Length)
+
+            " Form the menu command prefix
+            let m_prefix = 'anoremenu <silent> T\&ags.'
+            if a:add_ttype_name
+                let m_prefix = m_prefix . ttype_fullname . '.'
+            endif
+            let m_prefix = m_prefix . first_tag . '\.\.\.' . last_tag . '.'
+
+            " Character prefix used to number the menu items (hotkey)
+            let m_prefix_idx = 0
+
+            while j <= final_index
+                let tidx = s:tlist_{fidx_ttype}_{j}
+
+                let tname = s:tlist_{a:fidx}_{tidx}_tag_name
+
+                let mcmd = mcmd . m_prefix . '\&' .
+                            \ s:menu_char_prefix[m_prefix_idx] . '\.' .
+                            \ tname . ' :call <SID>Tlist_Menu_Jump_To_Tag(' .
+                            \ tidx . ')<CR>|'
+
+                let m_prefix_idx = m_prefix_idx + 1
+                let j = j + 1
+            endwhile
+        endwhile
+    else
+        " Character prefix used to number the menu items (hotkey)
+        let m_prefix_idx = 0
+
+        let m_prefix = 'anoremenu <silent> T\&ags.'
+        if a:add_ttype_name
+            let m_prefix = m_prefix . ttype_fullname . '.'
+        endif
+        let j = 1
+        while j <= tcnt
+            let tidx = s:tlist_{fidx_ttype}_{j}
+
+            let tname = s:tlist_{a:fidx}_{tidx}_tag_name
+
+            let mcmd = mcmd . m_prefix . '\&' .
+                        \ s:menu_char_prefix[m_prefix_idx] . '\.' .
+                        \ tname . ' :call <SID>Tlist_Menu_Jump_To_Tag(' . tidx
+                        \ . ')<CR>|'
+
+            let m_prefix_idx = m_prefix_idx + 1
+            let j = j + 1
+        endwhile
+    endif
+
+    return mcmd
+endfunction
+
+" Update the taglist menu with the tags for the specified file
+function! s:Tlist_Menu_File_Refresh(fidx)
+    call s:Tlist_Log_Msg('Refreshing the tag menu for ' . s:tlist_{a:fidx}_filename)
+    " The 'B' flag is needed in the 'cpoptions' option
+    let old_cpoptions = &cpoptions
+    set cpoptions&vim
+
+    exe s:tlist_{a:fidx}_menu_cmd
+
+    " Update the popup menu (if enabled)
+    if &mousemodel =~ 'popup'
+        let cmd = substitute(s:tlist_{a:fidx}_menu_cmd, ' T\\&ags\.',
+                                        \ ' PopUp.T\\\&ags.', "g")
+        exe cmd
+    endif
+
+    " The taglist menu is not empty now
+    let s:tlist_menu_empty = 0
+
+    " Restore the 'cpoptions' settings
+    let &cpoptions = old_cpoptions
+endfunction
+
+" Tlist_Menu_Update_File
+" Add the taglist menu
+function! s:Tlist_Menu_Update_File(clear_menu)
+    if !has('gui_running')
+        " Not running in GUI mode
+        return
+    endif
+
+    call s:Tlist_Log_Msg('Updating the tag menu, clear_menu = ' . a:clear_menu)
+
+    " Remove the tags menu
+    if a:clear_menu
+        call s:Tlist_Menu_Remove_File()
+
+    endif
+
+    " Skip buffers with 'buftype' set to nofile, nowrite, quickfix or help
+    if &buftype != ''
+        return
+    endif
+
+    let filename = fnamemodify(bufname('%'), ':p')
+    let ftype = s:Tlist_Get_Buffer_Filetype('%')
+
+    " If the file doesn't support tag listing, skip it
+    if s:Tlist_Skip_File(filename, ftype)
+        return
+    endif
+
+    let fidx = s:Tlist_Get_File_Index(filename)
+    if fidx == -1 || !s:tlist_{fidx}_valid
+        " Check whether this file is removed based on user request
+        " If it is, then don't display the tags for this file
+        if s:Tlist_User_Removed_File(filename)
+            return
+        endif
+
+        " Process the tags for the file
+        let fidx = s:Tlist_Process_File(filename, ftype)
+        if fidx == -1
+            return
+        endif
+    endif
+
+    let fname = escape(fnamemodify(bufname('%'), ':t'), '.')
+    if fname != ''
+        exe 'anoremenu T&ags.' .  fname . ' <Nop>'
+        anoremenu T&ags.-SEP2-           :
+    endif
+
+    if !s:tlist_{fidx}_tag_count
+        return
+    endif
+
+    if s:tlist_{fidx}_menu_cmd != ''
+        " Update the menu with the cached command
+        call s:Tlist_Menu_File_Refresh(fidx)
+
+        return
+    endif
+
+    " We are going to add entries to the tags menu, so the menu won't be
+    " empty
+    let s:tlist_menu_empty = 0
+
+    let cmd = ''
+
+    " Determine whether the tag type name needs to be added to the menu
+    " If more than one tag type is present in the taglisting for a file,
+    " then the tag type name needs to be present
+    let add_ttype_name = -1
+    let i = 1
+    while i <= s:tlist_{ftype}_count && add_ttype_name < 1
+        let ttype = s:tlist_{ftype}_{i}_name
+        if s:tlist_{fidx}_{ttype}_count
+            let add_ttype_name = add_ttype_name + 1
+        endif
+        let i = i + 1
+    endwhile
+
+    " Process the tags by the tag type and get the menu command
+    let i = 1
+    while i <= s:tlist_{ftype}_count
+        let mcmd = s:Tlist_Menu_Get_Tag_Type_Cmd(fidx, ftype, add_ttype_name, i)
+        if mcmd != ''
+            let cmd = cmd . mcmd
+        endif
+
+        let i = i + 1
+    endwhile
+
+    " Cache the menu command for reuse
+    let s:tlist_{fidx}_menu_cmd = cmd
+
+    " Update the menu
+    call s:Tlist_Menu_File_Refresh(fidx)
+endfunction
+
+" Tlist_Menu_Remove_File
+" Remove the tags displayed in the tags menu
+function! s:Tlist_Menu_Remove_File()
+    if !has('gui_running') || s:tlist_menu_empty
+        return
+    endif
+
+    call s:Tlist_Log_Msg('Removing the tags menu for a file')
+
+    " Cleanup the Tags menu
+    silent! unmenu T&ags
+    if &mousemodel =~ 'popup'
+        silent! unmenu PopUp.T&ags
+    endif
+
+    " Add a dummy menu item to retain teared off menu
+    noremenu T&ags.Dummy l
+
+    silent! unmenu! T&ags
+    if &mousemodel =~ 'popup'
+        silent! unmenu! PopUp.T&ags
+    endif
+
+    call s:Tlist_Menu_Add_Base_Menu()
+
+    " Remove the dummy menu item
+    unmenu T&ags.Dummy
+
+    let s:tlist_menu_empty = 1
+endfunction
+
+" Tlist_Menu_Refresh
+" Refresh the taglist menu
+function! s:Tlist_Menu_Refresh()
+    call s:Tlist_Log_Msg('Refreshing the tags menu')
+    let fidx = s:Tlist_Get_File_Index(fnamemodify(bufname('%'), ':p'))
+    if fidx != -1
+        " Invalidate the cached menu command
+        let s:tlist_{fidx}_menu_cmd = ''
+    endif
+
+    " Update the taglist, menu and window
+    call s:Tlist_Update_Current_File()
+endfunction
+
+" Tlist_Menu_Jump_To_Tag
+" Jump to the selected tag
+function! s:Tlist_Menu_Jump_To_Tag(tidx)
+    let fidx = s:Tlist_Get_File_Index(fnamemodify(bufname('%'), ':p'))
+    if fidx == -1
+        return
+    endif
+
+    let tagpat = s:Tlist_Get_Tag_SearchPat(fidx, a:tidx)
+    if tagpat == ''
+        return
+    endif
+
+    " Add the current cursor position to the jump list, so that user can
+    " jump back using the ' and ` marks.
+    mark '
+
+    silent call search(tagpat, 'w')
+
+    " Bring the line to the middle of the window
+    normal! z.
+
+    " If the line is inside a fold, open the fold
+    if foldclosed('.') != -1
+        .foldopen
+    endif
+endfunction
+
+" Tlist_Menu_Init
+" Initialize the taglist menu
+function! s:Tlist_Menu_Init()
+    call s:Tlist_Menu_Add_Base_Menu()
+
+    " Automatically add the tags defined in the current file to the menu
+    augroup TagListMenuCmds
+        autocmd!
+
+        if !g:Tlist_Process_File_Always
+            autocmd BufEnter * call s:Tlist_Refresh()
+        endif
+        autocmd BufLeave * call s:Tlist_Menu_Remove_File()
+    augroup end
+
+    call s:Tlist_Menu_Update_File(0)
+endfunction
+
+" Tlist_Vim_Session_Load
+" Initialize the taglist window/buffer, which is created when loading
+" a Vim session file.
+function! s:Tlist_Vim_Session_Load()
+    call s:Tlist_Log_Msg('Tlist_Vim_Session_Load')
+
+    " Initialize the taglist window
+    call s:Tlist_Window_Init()
+
+    " Refresh the taglist window
+    call s:Tlist_Window_Refresh()
+endfunction
+
+" Tlist_Set_App
+" Set the name of the external plugin/application to which taglist
+" belongs.
+" Taglist plugin is part of another plugin like cream or winmanager.
+function! Tlist_Set_App(name)
+    if a:name == ""
+        return
+    endif
+
+    let s:tlist_app_name = a:name
+endfunction
+
+" Winmanager integration
+
+" Initialization required for integration with winmanager
+function! TagList_Start()
+    " If current buffer is not taglist buffer, then don't proceed
+    if bufname('%') != '__Tag_List__'
+        return
+    endif
+
+    call Tlist_Set_App('winmanager')
+
+    " Get the current filename from the winmanager plugin
+    let bufnum = WinManagerGetLastEditedFile()
+    if bufnum != -1
+        let filename = fnamemodify(bufname(bufnum), ':p')
+        let ftype = s:Tlist_Get_Buffer_Filetype(bufnum)
+    endif
+
+    " Initialize the taglist window, if it is not already initialized
+    if !exists('s:tlist_window_initialized') || !s:tlist_window_initialized
+        call s:Tlist_Window_Init()
+        call s:Tlist_Window_Refresh()
+        let s:tlist_window_initialized = 1
+    endif
+
+    " Update the taglist window
+    if bufnum != -1
+        if !s:Tlist_Skip_File(filename, ftype) && g:Tlist_Auto_Update
+            call s:Tlist_Window_Refresh_File(filename, ftype)
+        endif
+    endif
+endfunction
+
+function! TagList_IsValid()
+    return 0
+endfunction
+
+function! TagList_WrapUp()
+    return 0
+endfunction
+
+" restore 'cpo'
+let &cpo = s:cpo_save
+unlet s:cpo_save
+