]> git.madduck.net Git - etc/vim.git/commitdiff

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

add table plugin
authormartin f. krafft <madduck@madduck.net>
Wed, 29 Oct 2008 14:26:12 +0000 (15:26 +0100)
committermartin f. krafft <madduck@madduck.net>
Wed, 29 Oct 2008 14:26:12 +0000 (15:26 +0100)
.vim/macros/table.vim [new file with mode: 0644]
.vimrc

diff --git a/.vim/macros/table.vim b/.vim/macros/table.vim
new file mode 100644 (file)
index 0000000..4f4d24d
--- /dev/null
@@ -0,0 +1,324 @@
+" Script: table.vim
+" Version: 0.1 
+"
+" Maintainer: Usman Latif Email: latif@techuser.net 
+" Webpage: http://www.techuser.net
+"
+" Description:
+" This script defines maps for easier editing and alignmnet of tables.
+" For usage and installation instructions consult the documentation
+" files that came with this script. In case you are missing the 
+" documentation files, download a complete distribution of the files
+" from http://www.techuser.net/files
+
+
+map <silent> <Leader>tt :call TableToggle()<CR>
+map <silent> <Leader>th :call TableHeading()<CR>
+map <silent> <Leader>ta :call TableAlign()<CR>
+
+let s:tablemode = 0
+let s:heading = ''
+let s:fieldsep = ' \{2,}'
+
+" Function: TableHeading
+" Args: None
+"
+" use current line as the heading line of the table
+" current line should be non-empty
+func! TableHeading() 
+    " get heading line and store it in a script variable
+    let s:heading = TrimWS(ExpandTabs(getline(".")))
+
+    if !ValidHeading(s:heading)
+        return 
+    endif
+
+    " map keys to invoke table navigation functions
+    call EnableMaps() 
+
+    let s:tablemode = 1
+endfunc
+
+" Function: ValidHeading
+" Args: None
+" Return: boolean
+"
+" returns 1 if heading is valid, i.e., non-whitespace
+" returns 0 otherwise 
+
+func! ValidHeading(heading)
+    " heading line empty ==> invalid heading
+    let l:str = a:heading
+    if strlen(str) == matchend(str,'^ *')
+        return 0
+    endif
+    return 1
+endfunc
+
+" Function: TableToggle
+" Args: None
+"
+" Toggle Table Mode
+" Enable/Disable maps for tablemode keys
+
+func! TableToggle()
+
+    if !ValidHeading(s:heading)
+        return 
+    endif
+
+    " enable/disable maps
+    if s:tablemode
+        call DisableMaps()
+    else
+        call EnableMaps()
+    endif
+
+    " toggle tablemode
+    let s:tablemode = !s:tablemode
+endfunc
+
+" Function: Enable Maps
+" Args: None
+"
+" Enable maps for tablemode keys
+
+func! EnableMaps()
+    nnoremap <silent> <Tab>    :call NextField(0)<CR>
+    inoremap <silent> <Tab>    <C-O>:call NextField(1)<CR>
+    nnoremap <silent> <S-Tab>  :call PrevField()<CR>
+    inoremap <silent> <S-Tab>  <C-O>:call PrevField()<CR>
+endfunc
+
+" Function: Disable Maps
+" Args: None
+"
+" Disable maps for tablemode keys
+
+func! DisableMaps()
+    nunmap <Tab>
+    iunmap <Tab>
+    nunmap <S-Tab>
+    iunmap <S-Tab>
+endfunc
+
+
+" Function: TableAlign
+" Args: None
+" Description: align the fields of the row with the fields of the heading
+
+func! TableAlign()
+    if !s:tablemode
+        return
+    endif
+    let temp = ""
+    let linetext = TrimWS(ExpandTabs(getline('.')))
+
+    let nfhead = LenWS(s:heading,0) + 1
+    let nftext = LenWS(linetext,0) + 1
+    let error = 0
+
+    while 1
+        " flag error if current field too big to fit
+        if (nfhead - strlen(temp))  <= 1 && strlen(temp) != 0 
+            let error = 1 
+            break
+        endif
+
+        " pad to next field of heading and add contents of the next text
+        " field after that
+        let temp = temp . Replicate(' ',nfhead - strlen(temp)-1) . Gettext(linetext,nftext-1)
+
+        let nfhead = NextFieldPos(s:heading,s:fieldsep,nfhead)
+        let nftext = NextFieldPos(linetext,s:fieldsep,nftext)
+
+        " If no next field exit loop
+        if nfhead == 0 || nftext == 0
+            " flag error if row to be aligned has more fields than heading
+            if nftext != 0 
+                let error = 1
+            endif
+            break
+        endif
+    endwhile
+    if !error && temp != linetext
+        call setline('.',temp)
+    endif
+endfunc
+
+
+" Function: PrevField
+" Args: None
+"
+" position the cursor at the start of the prev field position 
+
+func! PrevField()
+    let nextpos = 1
+    let lastpos = 1
+    let pos = col('.')
+    let linenum = line('.')
+    let fstfield = LenWS(s:heading,0) + 1
+
+    while nextpos != 0
+        let lastpos = nextpos
+        let nextpos = NextFieldPos(s:heading,s:fieldsep,nextpos) 
+        if pos > lastpos && (pos <= nextpos || nextpos == 0)
+            let pos = lastpos
+        endif
+    endwhile
+
+    if pos <= fstfield && linenum != 1 && col('.') <= fstfield
+        let linenum = linenum - 1
+        let pos = lastpos
+    endif
+
+    call cursor(linenum,pos)
+endfunc
+
+
+" Function: NextField
+" Args: curmode
+"
+" position the cursor at the start of next field position
+" pad the current line with spaces if needed when in insertion
+" or replace mode
+
+func! NextField(curmode)
+    let l:pos = Max(col('.') - 2,0)
+    let l:startnext = NextFieldPos(s:heading,s:fieldsep,pos)
+    let l:linenum = line('.')
+
+    "If no nextfield on line goto next line
+    "append an empty line if in insert/replace mode
+    if startnext == 0
+        if a:curmode 
+            call append(linenum,'')
+        endif
+        let linenum = linenum+1
+        let startnext = LenWS(s:heading,0) + 1
+    endif
+
+    let l:linetext = ExpandTabs(getline(linenum))
+    let l:linelen = strlen(linetext)
+
+    "If padding required
+    if linelen < startnext
+        let linetext = linetext . Replicate(' ',startnext-linelen+1)
+        call setline(linenum,linetext)
+    endif
+
+    if linenum > line('$')
+        let linenum = line('$')
+        let startnext = col('.')
+    endif
+    call cursor(linenum,startnext)
+endfunc
+
+
+" Function: NextFieldPos
+" Args: string,pattern,startposition
+"
+" returns the position of the end of field in which pos
+" is contained
+
+func! NextFieldPos(str,pat,pos)
+    return matchend(a:str,a:pat,a:pos) + 1
+endfunc
+
+
+" Function: Gettext
+" Args: str, pos 
+" Description: Extract the text contents of a field from the 
+" string str, starting at position pos
+
+func! Gettext(str,pos)
+    let endpos = match(a:str,s:fieldsep,a:pos)
+    if endpos == -1
+        let endpos = strlen(a:str) - 1
+    endif
+    return strpart(a:str,a:pos,endpos - a:pos + 1)
+endfunc
+
+
+" Function: TrimWS
+" Args: str
+" Description: Trim any WS at the end of the string str
+
+func! TrimWS(str)
+    let len = match(a:str,' \{1,}$',0)
+    if len == -1 
+        return a:str 
+    else
+        return strpart(a:str,0,len)
+    endif
+endfunc
+
+
+" Function: LenWS
+" Args: str, startpos
+" Description: Length of contiguous whitespace starting at
+" position startpos in string str
+
+func! LenWS(str,startpos)
+    let i = 0
+    while a:str[a:startpos+i] == ' '
+        let i = i + 1
+    endwhile
+    return i
+endfunc
+
+
+" Function: Replicate
+" Args: str,cnt
+"
+" Repeat the given string cnt number of times
+
+func! Replicate(str,cnt)
+    let l:temp = ""
+
+    let l:i = 0
+    while i < a:cnt
+        let temp = temp . a:str
+        let i = i + 1
+    endwhile
+
+    return temp
+endfunc
+
+
+" Function: ExpandTabs
+" Args: str
+" Return value: string 
+"
+" Expand all tabs in the string to spaces 
+" according to tabstop value
+
+func! ExpandTabs(str)
+    let l:str = a:str
+    let l:temp = ""
+
+    let l:i = 0
+    while i < strlen(str)
+        if str[i] == "\t"
+            let temp = temp . Replicate(' ',&tabstop)
+        else
+            let temp = temp . str[i]
+        endif
+        let i = i + 1
+    endwhile
+
+    return temp
+endfunc
+
+" Function: Max
+" Args: x,y
+" Description: return the max of x and y
+
+func! Max(x,y)
+    if a:x >= a:y 
+        return a:x
+    else 
+        return a:y
+    endif
+endfunc
diff --git a/.vimrc b/.vimrc
index a38f61ba9cf0abb261b51d51bc29173a00d13f08..a483050eb75dfeaefb730654e462b695b954f3a6 100644 (file)
--- a/.vimrc
+++ b/.vimrc
@@ -1458,6 +1458,8 @@ augroup listinsert
   autocmd InsertLeave * set list
 augroup end
 
+source $VIMRUNTIME/macros/table.vim
+
 if &cp | set nocp | endif
 let s:cpo_save=&cpo
 set cpo&vim