Subversion Repositories programming

Rev

Blame | Last modification | View Log | RSS feed

"*****************************************************************************
"** Name:      chartab.vim - print a character table                        **
"**                                                                         **
"** Type:      global VIM plugin                                            **
"**                                                                         **
"** Author:    Christian Habermann                                          **
"**            christian (at) habermann-net (point) de                      **
"**                                                                         **
"** Copyright: (c) 2004 by Christian Habermann                              **
"**                                                                         **
"** License:   GNU General Public License 2 (GPL 2) or later                **
"**                                                                         **
"**            This program is free software; you can redistribute it       **
"**            and/or modify it under the terms of the GNU General Public   **
"**            License as published by the Free Software Foundation; either **
"**            version 2 of the License, or (at your option) any later      **
"**            version.                                                     **
"**                                                                         **
"**            This program is distributed in the hope that it will be      **
"**            useful, but WITHOUT ANY WARRANTY; without even the implied   **
"**            warrenty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      **
"**            PURPOSE.                                                     **
"**            See the GNU General Public License for more details.         **
"**                                                                         **
"** Version:   1.0.0                                                        **
"**            tested under Linux and Win32, VIM and GVIM 6.2               **
"**                                                                         **
"** History:   1.0.0  31. Jan. 2004                                         **
"**              initial version                                            **
"**                                                                         **
"**                                                                         **
"*****************************************************************************
"** Description:                                                            **
"**   This script provides a character table (yes, yet another one :-) ).   **
"**   But it has some nice features:                                        **
"**     - it takes advantage of syntax-highlighting                         **
"**     - it allows to toggle base of codes without leaving buffer          **
"**     - it opens in currently active window, so no rearrangement of       **
"**       windows occur                                                     **
"**     - special codes are viewed with their real names (NUL, ETX,...)     **
"**     - quitting is very simple and fast - just one keystroke             **
"**                                                                         **
"**   Installation:                                                         **
"**     To use this script copy it into your local plugin-directory         **
"**     Unix:    ~./.vim/plugin                                             **
"**     Windows: c:\vimfiles\plugin                                         **
"**     After starting VIM this script is sourced automatically.            **
"**                                                                         **
"**     By default, press <Leader>ct to view character table.               **
"**                                                                         **
"**   Configuration:                                                        **
"**     - <Plug>CT_CharTable                                                **
"**       mapping to open character table                                   **
"**       default:                                                          **
"**          map <silent> <unique> <Leader>ct <Plug>CT_CharTable            **
"**                                                                         **
"**     - g:ct_base                                                         **
"**       Defines base of codes. Allowed values are 'hex' and 'dec'.        **
"**       Default is 'dec'.                                                 **
"**       Add  let g:ct_base="hex" to your .vimrc if you want to change it. **
"**                                                                         **
"**   Known limitations:                                                    **
"**     If a character is not printable by Vim it is printed as two         **
"**     characters, e.g. ~A. This may cause a misalignment of the table.    **
"**                                                                         **
"**   Known bugs:                                                           **
"**     none - well, up to now :-)                                          **
"**                                                                         **
"**                                                                         **
"**   Happy vimming....                                                     **
"*****************************************************************************

" allow user to avoid loading this plugin and prevent loading twice
if exists ("ct_chartable")
    finish
endif

let ct_chartable = 1




"*****************************************************************************
"************************** C O N F I G U R A T I O N ************************
"*****************************************************************************

" the mappings:
if !hasmapto('<Plug>CT_CharTable')
    map <silent> <unique> <Leader>ct <Plug>CT_CharTable
endif

map <silent> <unique> <script> <Plug>CT_CharTable  :call <SID>CT_CharTable()<CR>



if !exists('g:ct_base')      " base of numbers, default is hex (hex, dec)
    let g:ct_base = "dec"
endif




"*****************************************************************************
"****************** I N T E R F A C E  T O  C O R E **************************
"*****************************************************************************

"*****************************************************************************
"** this function separates plugin-core-function from user                  **
"*****************************************************************************
function <SID>CT_CharTable()
    call s:CharTable()
endfunction



"***************************  END OF USER'S WORLD  ***************************




"*****************************************************************************
"************************* I N I T I A L I S A T I O N ***********************
"*****************************************************************************

" used to store number of buffer showing character table 
" set it to impossible value
let s:viewBufNr = -1 






"*****************************************************************************
"************************ C O R E  F U N C T I O N S *************************
"*****************************************************************************




"*****************************************************************************
"** input:   none                                                           **
"** output:  none                                                           **
"*****************************************************************************
"** remarks:                                                                **
"**   This is the main function where all jobs are initiated.               **
"**                                                                         **
"**   The buffer loaded to view search-result will be deleted at:           **
"**     - loading another buffer into the same window (automatic)           **
"**     - user cancles view (see CloseViewBuffer())                         **
"**                                                                         **
"*****************************************************************************
function s:CharTable()

    " allow modifications (necessary if called from the scripts own buffer)
    setlocal modifiable


    "open buffer for viewing character table
    call s:OpenViewBuffer()


    " define locale mappings of user interface
    call s:SetLocalKeyMappings()


    " set syntax highlighting for view
    call s:SetupSyntaxHighlighting()


    
    " make string for header of view => s:txt
    call s:MakeHeader()


    " add character table => s:txt; that's what user want to see
    call s:MakeCharTable()

    
    " output result
    setlocal modifiable
    
    put! = s:txt

    setlocal nomodifiable

endfunction




"*****************************************************************************
"** input:   none                                                           **
"** output:  none                                                           **
"*****************************************************************************
"** remarks:                                                                **
"**   Make string for header of view.                                       **
"*****************************************************************************
function s:MakeHeader()

    let s:txt =         "\"             Character Table\n"
    let s:txt = s:txt . "\"            =================\n"
    let s:txt = s:txt . "\"\n"
    let s:txt = s:txt . "\"  b : toggle base\n"
    let s:txt = s:txt . "\"  q : quit\n\n\n"

endfunction




"*****************************************************************************
"** input:   none                                                           **
"** output:  none                                                           **
"*****************************************************************************
"** remarks:                                                                **
"**   Print character table into current buffer.                            **
"*****************************************************************************
function s:MakeCharTable()

    let NUM_OF_ROWS = 32
    let NUM_OF_COLS = 8
    
    let code = 0
    let row  = 0  
   
   
    while row < NUM_OF_ROWS
    
        let column = 0

        while column < NUM_OF_COLS
            let code = row + column * NUM_OF_ROWS

            " add code number
            let s:txt = s:txt ." " . s:Nr2String(code, g:ct_base). " "

            " add character
            if (s:IsCodeSpecialChar(code))
                let s:txt = s:txt . s:GetStringOfSpecialChar(code)
                let spaceToNext = " "
            else
                let s:txt = s:txt . nr2char(code)
                let spaceToNext = "   "
            endif
            
            let s:txt = s:txt . ( (column == (NUM_OF_COLS - 1)) ? "" : spaceToNext . "|" )

            let column = column + 1
        endwhile
    
        let s:txt = s:txt . "\n"
      
        let row = row + 1
    endwhile

  
endfunction




"*****************************************************************************
"** input:   code: number to be converted to a string                       **
"**          base: defines base of number ("hex" or "dec")                  **
"** output:  formated string                                                **
"*****************************************************************************
"** remarks:                                                                **
"**   This function converts a number to a string.                          **
"*****************************************************************************
function s:Nr2String(nr, base)

    let nr   = a:nr
    let base = a:base


    " get base as a number
    if (a:base == "dec")
        let base = 10
    else
        let base = 16
    endif


    " convert number to string
    let strng = (nr == 0) ? "0" : ""

    while nr
        let strng = '0123456789ABCDEF'[nr % base] . strng
        let nr = nr / base
    endwhile
   
   
    " format string: 3 digits, right alignment
    if (base == 10)
        if (strlen(strng) == 1)
            let strng = "  " . strng 
        elseif (strlen(strng) == 2)
            let strng = " " . strng      
        endif
    else       " assume hex
        if (strlen(strng) == 1)
            let strng = "0" . strng 
        endif

        let strng = strng . "h"
    endif
    
    
    
    return strng
    
endfunction





"*****************************************************************************
"** input:   code: number to be tested                                      **
"** output:  0  : no special character                                      **
"**          > 0: code is a special character                               **
"*****************************************************************************
"** remarks:                                                                **
"**   This function tests whether 'code' is a special character.            **
"**   Special characters are: 0...0x20 and 0x7F, space (0x20) is included   **
"**                           here to print it as ' '                       **
"*****************************************************************************
function s:IsCodeSpecialChar(code)

  if ( ((a:code >= 0) && (a:code <= 0x20)) || (a:code == 0x7F) )
      return 1
  else
      return 0
  endif


endfunction




"*****************************************************************************
"** input:   code: code of special character 0..0x20 or 0x7F                **
"** output:  name of special character                                      **
"*****************************************************************************
"** remarks:                                                                **
"**   returns name of special character, e.g. code = 0 will return NUL      **
"*****************************************************************************
function s:GetStringOfSpecialChar(code)
    
    let strng = "-"

    if (a:code == 0)
        let strng = "NUL"
    elseif (a:code ==  1)
        let strng = "SOH"
    elseif (a:code ==  2)
        let strng = "STX"
    elseif (a:code ==  3)
        let strng = "ETX"
    elseif (a:code ==  4)
        let strng = "EOT"
    elseif (a:code ==  5)
        let strng = "ENQ"
    elseif (a:code ==  6)
        let strng = "ACK"
    elseif (a:code ==  7)
        let strng = "BEL"
    elseif (a:code ==  8)
        let strng = "BS "
    elseif (a:code ==  9)
        let strng = "TAB"
    elseif (a:code == 10)
        let strng = "LF "
    elseif (a:code == 11)
        let strng = "VT "
    elseif (a:code == 12)
        let strng = "FF "
    elseif (a:code == 13)
        let strng = "CR "
    elseif (a:code == 14)
        let strng = "SO "
    elseif (a:code == 15)
        let strng = "SI "
    elseif (a:code == 16)
        let strng = "DLE"
    elseif (a:code == 17)
        let strng = "DC1"
    elseif (a:code == 18)
        let strng = "DC2"
    elseif (a:code == 19)
        let strng = "DC3"
    elseif (a:code == 20)
        let strng = "DC4"
    elseif (a:code == 21)
        let strng = "NAK"
    elseif (a:code == 22)
        let strng = "SYN"
    elseif (a:code == 23)
        let strng = "ETB"
    elseif (a:code == 24)
        let strng = "CAN"
    elseif (a:code == 25)
        let strng = "EM "
    elseif (a:code == 26)
        let strng = "SUB"
    elseif (a:code == 27)
        let strng = "ESC"
    elseif (a:code == 28)
        let strng = "FS "
    elseif (a:code == 29)
        let strng = "GS "
    elseif (a:code == 30)
        let strng = "RS "
    elseif (a:code == 31)
        let strng = "US "
    elseif (a:code == 32)
        let strng = "\' \'"
    elseif (a:code == 127)
        let strng = "DEL"
    endif
        

    return strng
    
endfunction





"*****************************************************************************
"** input:   none                                                           **
"** output:  none                                                           **
"*****************************************************************************
"** remarks:                                                                **
"**   set local/temporarily key-mappings valid while viewing result         **
"*****************************************************************************
function s:SetLocalKeyMappings()
                                         " use 'q' to close view-buffer
                                         " and switch to previously used buffer
    nnoremap <buffer> <silent> q :call <SID>CT_Exit()<cr>

                                         " use 'b' to toggle base of codes
    nnoremap <buffer> <silent> b :call <SID>CT_ToggleBase()<cr>

endfunction




"*****************************************************************************
"** input:   errNr: number which defines an error (> 0)                     **
"** output:  none                                                           **
"*****************************************************************************
"** remarks:                                                                **
"**   this function prints an error-msg                                     **
"*****************************************************************************
"function s:Error(errNr)
"    
"    if (a:errNr == 1)
"        echo scriptName.": can't open buffer"
"    else
"        echo scriptName.": unknown error"
"    endif
"
"endfunction




"*****************************************************************************
"** input:   none                                                           **
"** output:  none                                                           **
"*****************************************************************************
"** remarks:                                                                **
"**   set syntax-highlighting (if VIM has 'syntax')                         **
"*****************************************************************************
function s:SetupSyntaxHighlighting()

    " don't continue, if this version of VIM does not support syntax-highlighting
    if !has('syntax')
        return
    endif

    syntax match ctComment  "^\".*"
    

    " matches both separator or start of line and code
    syn match ctSepaCode  "\(^\||\)[ ]\+[0-9A-Fa-fh]\+" contains=ctCode,ctSeparator
    
    " matches code only
    syn match ctCode      "[0-9A-Fa-fh]\+" contained
    
    " matches serparator only
    syn match ctSeparator "|" contained


    if !exists('g:ct_syntaxHighInit')
        let g:ct_syntaxHighInit = 0

        hi def link ctComment   Comment
        hi def link ctCode      String
        hi def link ctSeparator Comment
    endif

endfunction




"*****************************************************************************
"** input:   none                                                           **
"** output:  none                                                           **
"*****************************************************************************
"** remarks:                                                                **
"**   Open a buffer to view character table and for user interaction.       **
"**                                                                         **
"*****************************************************************************
function s:OpenViewBuffer()

    " save current buffer number so that we can switch back to this buffer
    " when finishing job
    " but only if the current buffer isn't already one of chartab's
    if (s:viewBufNr != winbufnr(0))
        let s:startBufNr = winbufnr(0)
    endif


    " open new buffer
    execute "enew"
    

    " save buffer number used by this script to view result
    let s:viewBufNr = winbufnr(0)


    " buffer specific settings:
    "   - nomodifiable:     don't allow to edit this buffer
    "   - noswapfile:       we don't need a swapfile
    "   - buftype=nowrite:  buffer will not be written
    "   - bufhidden=delete: delete this buffer if it will be hidden
    "   - nowrap:           don't wrap around long lines
    "   - iabclear:         no abbreviations in insert mode
    setlocal nomodifiable
    setlocal noswapfile
    setlocal buftype=nowrite
    setlocal bufhidden=delete
    setlocal nowrap
    iabclear <buffer>

endfunction




"*****************************************************************************
"** input:   none                                                           **
"** output:  none                                                           **
"*****************************************************************************
"** remarks:                                                                **
"**   Switch to buffer in which the script was invoked. Then the view-      **
"**   buffer will be deleted automatically.                                 **
"**   If there was no buffer at start of script, delete view-buffer         **
"**   explicitely.                                                          **
"*****************************************************************************
function s:CloseViewBuffer()

    " if start and view-buffer are the same, there was no buffer at invoking script
    if (s:startBufNr != s:viewBufNr)
        exec("buffer! ".s:startBufNr)
    else
        exec("bdelete ".s:startBufNr)
    endif

endfunction




"*****************************************************************************
"** input:   none                                                           **
"** output:  none                                                           **
"*****************************************************************************
"** remarks:                                                                **
"**   toggle base of numbers                                                **
"*****************************************************************************
function <SID>CT_ToggleBase()

    " save current cursor position
    let lineNr = line(".")
    let colNr  = col(".")


    " toggle base of numbers
    let g:ct_base = (g:ct_base == "dec") ? "hex" : "dec"

    " redraw view with new base
    call <SID>CT_CharTable()


    " restore cursor position
    call cursor(lineNr, colNr)

endfunction




"*****************************************************************************
"** input:   none                                                           **
"** output:  none                                                           **
"*****************************************************************************
"** remarks:                                                                **
"**   Job is done. Clean up.                                                **
"*****************************************************************************
function <SID>CT_Exit()

    call s:CloseViewBuffer()

endfunction



"*** EOF ***