├── README.md ├── autoload └── colddeck.vim ├── doc └── colddeck.txt ├── ftdetect └── colddeck.vim ├── ftplugin └── colddeck.vim ├── plugin └── colddeck.vim └── syntax └── colddeck.vim /README.md: -------------------------------------------------------------------------------- 1 | Vim-colddeck 2 | ------------- 3 | 4 | > Vim meets Instacalc meets Hewlett-Packard calculators 5 | 6 | Colddeck ("Column dc") is a single-column spreadsheet using `dc` for 7 | computations. You jot down values and formulas, one per line, and the result 8 | is shown on the right. 9 | 10 | Extra features: 11 | 12 | - References to other rows (absolute and relative) 13 | - Ranges 14 | - Aggregates (sum, min/max, average...) 15 | - Vim expressions (experimental) 16 | - Value references (experimental) 17 | 18 | Example 19 | -------- 20 | 21 | [![asciicast](https://asciinema.org/a/0NgfyWgetZBIoXi6O3ikawkIE.svg)](https://asciinema.org/a/0NgfyWgetZBIoXi6O3ikawkIE) 22 | 23 | Syntax in a nutshell 24 | --------------------- 25 | 26 | - `R3`: reference to row #3 27 | - `R-1`: relative reference to the row above 28 | - `R+2`: relative reference to the second row below 29 | - `R1:R3`: range of rows from #1 to #3 (insert values and number of elements) 30 | - `R1:R3 @sum`: sum of row #1 to #3 (other aggregates: `@min`, `@max`, `@avg`, 31 | `@prod`) 32 | - `42 # text`: add "text" as a comment, while passing the value '42' to `dc` 33 | - `42 ## Label`: add "Label" as a right-aligned comment and hide the value or 34 | formula on its left, that is still passed to `dc` 35 | - `log(2)`: vim expression (evaluated before passing the 36 | line to `dc`) 37 | - `$2`: *result* of the evalutation of row #2 (must have been previously 38 | computed; evaluated before passing the line to `dc`) 39 | 40 | See [the documentation](doc/colddeck.txt) for full manual. 41 | 42 | FAQ 43 | ---- 44 | 45 | *What is it?* 46 | A single-column spreadsheet, in Vim, with postfix operators. 47 | Look ma, no Excel. 48 | 49 | *"dc", WTF?* 50 | Who doesn't love rabid panda notation? 51 | 52 | Installation 53 | ------------- 54 | Use your favorite method: 55 | * [Pathogen][1] - git clone https://github.com/fcpg/vim-colddeck ~/.vim/bundle/vim-colddeck 56 | * [NeoBundle][2] - NeoBundle 'fcpg/vim-colddeck' 57 | * [Vundle][3] - Plugin 'fcpg/vim-colddeck' 58 | * [Plug][4] - Plug 'fcpg/vim-colddeck' 59 | * manual - copy all files into your ~/.vim directory 60 | 61 | License 62 | -------- 63 | [Attribution-ShareAlike 4.0 Int.](https://creativecommons.org/licenses/by-sa/4.0/) 64 | 65 | [1]: https://github.com/tpope/vim-pathogen 66 | [2]: https://github.com/Shougo/neobundle.vim 67 | [3]: https://github.com/gmarik/vundle 68 | [4]: https://github.com/junegunn/vim-plug 69 | 70 | -------------------------------------------------------------------------------- /autoload/colddeck.vim: -------------------------------------------------------------------------------- 1 | " colddeck.vim - column-dc spreadsheet 2 | 3 | let s:save_cpo = &cpo 4 | set cpo&vim 5 | 6 | "------------ 7 | " Debug {{{1 8 | "------------ 9 | 10 | let g:cdeck_debug = 1 11 | if 0 12 | append 13 | " comment out all dbg calls 14 | :g,\c^\s*call Dbg(,s/call/"call/ 15 | " uncomment 16 | :g,\c^\s*"call Dbg(,s/"call/call/ 17 | . 18 | endif 19 | 20 | 21 | "-------------- 22 | " Options {{{1 23 | "-------------- 24 | 25 | " Defaults 26 | let s:def_rcol = 78 27 | let s:def_prec = 2 28 | let s:def_precmd = '' 29 | let s:def_autoahc = 1 30 | let s:def_dcerr = 0 31 | 32 | " Errors 33 | let s:err_notavail = get(g:, 'cdeck_err_notavail', '[N/A]') 34 | let s:err_valref_notfound = printf('[%s]', 35 | \ get(g:, 'cdeck_err_valref_notfound', 'value ref not found (yet)')) 36 | let s:err_vimexpr = printf('[%s]', 37 | \ get(g:, 'cdeck_err_vim_expr', 'vim expression error')) 38 | 39 | " Library of dc macros 40 | " - stored in '*' array 41 | " - input expected in '(' array 42 | " - output goes in ')' array (though these macros don't depend on it) 43 | " 44 | " 0: expand ranges 45 | " 1: pop number and execute 'Y' macro that many times ('fold', kinda) 46 | " 2: sum over stack with num of elems on top 47 | " 3: multiply over stack with num of elems on top 48 | " 4: find min over stack with num of elems on top 49 | " 5: find max over stack with num of elems on top 50 | " 6: compute average over stack with num of elems on top 51 | let s:dc_lib_cmd = join([ 52 | \ '[SEdSSSI[lI;(xlI1+dsIlE!Rs-LAs-LBs-LRs-]SY1;*x]', '5:*', 58 | \ '[dSN[+]SY1;*xLN/]', '6:*', 59 | \]) 60 | 61 | " Macros invocation 62 | let s:dc_range = ' 0;*x' 63 | let s:dc_sum = ' 2;*x' 64 | let s:dc_prod = ' 3;*x' 65 | let s:dc_min = ' 4;*x' 66 | let s:dc_max = ' 5;*x' 67 | let s:dc_avg = ' 6;*x' 68 | 69 | " Default value '[]' in 's' register 70 | let s:dc_defval_cmd = '[[]]s+' 71 | 72 | " '[True]' string in '?' (for user convenience, not used internally) 73 | let s:dc_truereg_cmd = '[[True]]s?' 74 | 75 | 76 | "---------------- 77 | " Functions {{{1 78 | "---------------- 79 | 80 | " colddeck#ParseLine() 81 | " 82 | " Parse a single line from current buffer 83 | " 84 | " Args: 85 | " - line number 86 | " Returns: 87 | " - dict: 88 | " - 'cmd': command 89 | " - 'rem': comment 90 | " 91 | function! colddeck#ParseLine(linenr) abort 92 | let ret = {'cmd': '', 'rem': ''} 93 | let rcol = get(b:, 'cdeck_rcol', get(g:, 'cdeck_rcol', s:def_rcol)) 94 | let line = getline(a:linenr) 95 | " trim results 96 | let line_nores = substitute(strpart(line, 0, rcol), '\s*$', '', '') 97 | let mlist = matchlist(line_nores, '\v\c^([^#]*)(#%(.*\S)?)?\s*$') 98 | let cmdpart = substitute(get(mlist, 1, ''), '\s\+$', ' ', '') 99 | let ret['rem'] = get(mlist, 2, '') 100 | if cmdpart =~ '^\s*$' 101 | " store an empty string 102 | let tmpcmd = '[]' 103 | else 104 | let tmpcmd = cmdpart 105 | " expand `$+num` refs 106 | let tmpcmd = substitute(tmpcmd, 107 | \ '\$\(\d\+\)', 108 | \ '\=get(b:cdeck_results, submatch(1), "VALREF_ERROR")', 109 | \ 'g') 110 | if tmpcmd =~ 'VALREF_ERROR' 111 | " expansion error, ignore this line 112 | let tmpcmd = s:err_valref_notfound 113 | endif 114 | " expand backticks 115 | try 116 | let tmpcmd = substitute(tmpcmd, 117 | \ '`\([^`]*\)`', 118 | \ '\=string(eval(submatch(1)))', 119 | \ 'g') 120 | catch 121 | " eval error, ignore this line 122 | let tmpcmd = s:err_vimexpr 123 | endtry 124 | " expand `R+num:R+num` ref ranges 125 | let tmpcmd = substitute(tmpcmd, 126 | \ '\CR\(\d\+\):R\(\d\+\)', 127 | \ ' \1 \2 ' . s:dc_range, 128 | \ 'g') 129 | " expand `@sum` 130 | let tmpcmd = substitute(tmpcmd, '\C@sum', s:dc_sum, 'g') 131 | " expand `@prod` 132 | let tmpcmd = substitute(tmpcmd, '\C@prod', s:dc_prod, 'g') 133 | " expand `@min` 134 | let tmpcmd = substitute(tmpcmd, '\C@min', s:dc_min, 'g') 135 | " expand `@max` 136 | let tmpcmd = substitute(tmpcmd, '\C@max', s:dc_max, 'g') 137 | " expand `@avg` 138 | let tmpcmd = substitute(tmpcmd, '\C@avg', s:dc_avg, 'g') 139 | " expand `R+num` refs 140 | let tmpcmd = substitute(tmpcmd, '\C\vR(\d+)', ' \1;(x', 'g') 141 | " expand relative refs 142 | let tmpcmd = substitute(tmpcmd, '\C\vR([+-]\d+)', 143 | \ '\=" ".('.a:linenr.'+submatch(1)).";(x"', 'g') 144 | endif 145 | " store cmd as string into array '(', indexed by line num 146 | let ret['cmd'] = printf('[%s]%s:(', tmpcmd, a:linenr) 147 | "call Dbg("parsed line (#, cmd, rem):", a:linenr, ret['cmd'], ret['rem']) 148 | return ret 149 | endfun 150 | 151 | 152 | " colddeck#CalcBuffer() 153 | " 154 | " Evaluate values and commands, then insert results after rcol 155 | " 156 | function! colddeck#CalcBuffer() abort 157 | let rcol = get(b:, 'cdeck_rcol', get(g:, 'cdeck_rcol', s:def_rcol)) 158 | let prec = get(b:, 'cdeck_prec', get(g:, 'cdeck_prec', s:def_prec)) 159 | let precmd = get(b:, 'cdeck_precmd', get(g:, 'cdeck_precmd', s:def_precmd)) 160 | let autoac = get(b:, 'cdeck_autoahc', get(g:, 'cdeck_autoahc', s:def_autoahc)) 161 | let rchar = get(g:, 'cdeck_rchar', '>') 162 | let dcpath = get(g:, 'cdeck_dc_path', 'dc') 163 | let dc_init_cmd = join([ 164 | \ prec."k", 165 | \ s:dc_defval_cmd, 166 | \ s:dc_truereg_cmd, 167 | \ precmd, 168 | \ "c", 169 | \], '') 170 | let dc_store_cmd = "" 171 | let dc_calc_cmd = "" 172 | let dc_show_cmd = "" 173 | let dc_cmd = "" 174 | let lastlinenr = line('$') 175 | let bufmodified = &modified 176 | 177 | let curpos = getcurpos() 178 | 179 | " clear previous results 180 | call colddeck#RemoveResults() 181 | 182 | " parse buffer and build dc cmdline 183 | let linenr = 1 184 | while linenr <= lastlinenr 185 | let parsedline = colddeck#ParseLine(linenr) 186 | let dc_store_cmd .= parsedline['cmd'] 187 | let dc_calc_cmd .= "c".linenr.';(xz0=+'.linenr.':) ' 188 | let dc_show_cmd = linenr.';)' . dc_show_cmd 189 | let linenr += 1 190 | endwhile 191 | 192 | " execute in dc 193 | let dc_cmd = join([ 194 | \ s:dc_lib_cmd, 195 | \ dc_init_cmd, 196 | \ dc_store_cmd, 197 | \ dc_calc_cmd, 198 | \ "c", 199 | \ dc_show_cmd, 200 | \ "f", 201 | \]) 202 | "call Dbg("dc_cmd:", dc_cmd) 203 | let dc = dcpath . 204 | \ (!get(b:, 'cdeck_dcerr', get(g:, 'cdeck_dcerr', s:def_dcerr)) 205 | \ ? ' 2>/dev/null' 206 | \ : '') 207 | let dc_result = systemlist(dc, dc_cmd) 208 | "call Dbg("dc_result:", string(dc_result)) 209 | 210 | " insert new results 211 | let linenr = 1 212 | let b:cdeck_results = {} 213 | while linenr <= lastlinenr 214 | let curline = getline(linenr) 215 | let linelen = strwidth(curline) 216 | let fillcount = max([rcol - linelen, 1]) 217 | let lineresult = get(dc_result, linenr - 1, s:err_notavail) 218 | if !empty(lineresult) 219 | let updatedline = substitute(curline, 220 | \ '$', 221 | \ printf('\=repeat(" ", %d)."%s %s"', 222 | \ fillcount, rchar, escape(lineresult, '"')), 223 | \ "") 224 | call setline(linenr, updatedline) 225 | endif 226 | let b:cdeck_results[linenr] = lineresult 227 | let linenr += 1 228 | endwhile 229 | 230 | " auto-align 'hiding comments' 231 | if autoac 232 | call colddeck#AlignHidingComments() 233 | endif 234 | 235 | " restore cursor pos 236 | call setpos('.', curpos) 237 | 238 | " Ignore results insertion for modified status 239 | let &modified = bufmodified 240 | endfun 241 | 242 | 243 | " colddeck#RemoveResults() 244 | " 245 | " Remove results from buffer (text after rcol) 246 | " 247 | function! colddeck#RemoveResults() abort 248 | let bufmodified = &modified 249 | let curpos = getcurpos() 250 | let rcol = get(b:, 'cdeck_rcol', get(g:, 'cdeck_rcol', s:def_rcol)) 251 | silent exe '%s/\v^.*\S\zs\s*%(%'.rcol.'v.*\S.*)$//e' 252 | call setpos('.', curpos) 253 | let &modified = bufmodified 254 | endfun 255 | 256 | 257 | " colddeck#MoveRcol() 258 | " 259 | " Move result column 260 | " 261 | " Args: 262 | " - number (absolute position), with '+/-' prefix for relative motion 263 | " 264 | function! colddeck#MoveRcol(col) abort 265 | call colddeck#RemoveResults() 266 | if a:col[0] =~ '[+-]' 267 | " relative motion 268 | let cur_rcol = get(b:, 'cdeck_rcol', get(g:, 'cdeck_rcol', s:def_rcol)) 269 | let b:cdeck_rcol = cur_rcol + str2nr(a:col) 270 | else 271 | let b:cdeck_rcol = a:col 272 | endif 273 | call colddeck#CalcBuffer() 274 | endfun 275 | 276 | 277 | " colddeck#AlignHidingComments() 278 | " 279 | " Right-align 'hiding comments' near results 280 | " 281 | function! colddeck#AlignHidingComments() abort 282 | let bufmodified = &modified 283 | let rcol = get(b:, 'cdeck_rcol', get(g:, 'cdeck_rcol', s:def_rcol)) 284 | silent exe '%s/\v(##.*\S)(\s+)\ze%'.rcol.'v./\2\1/e' 285 | let &modified = bufmodified 286 | endfun 287 | 288 | 289 | " Autocmds {{{2 290 | "--------------- 291 | 292 | " colddeck#SetAutoCalc() 293 | " 294 | " Add events to insert results automatically 295 | " (currently, only on InsertLeave) 296 | " 297 | function! colddeck#SetAutoCalc() abort 298 | if !get(b:, 'cdeck_auto_', 0) 299 | autocmd InsertLeave call colddeck#CalcBuffer() 300 | let b:cdeck_auto_ = 1 301 | endif 302 | endfun 303 | 304 | 305 | " colddeck#UnsetAutoCalc() 306 | " 307 | " Delete events that inserted results automatically 308 | " 309 | function! colddeck#UnsetAutoCalc() abort 310 | if get(b:, 'cdeck_auto_', 0) 311 | autocmd! InsertLeave 312 | let b:cdeck_auto_ = 0 313 | endif 314 | endfun 315 | 316 | 317 | " Debug {{{2 318 | "------------ 319 | function! s:Dbg(msg, ...) abort 320 | if g:cdeck_debug 321 | let m = a:msg 322 | if a:0 323 | let m .= " [".join(a:000, "] [")."]" 324 | endif 325 | echom m 326 | endif 327 | endfun 328 | 329 | 330 | let &cpo = s:save_cpo 331 | -------------------------------------------------------------------------------- /doc/colddeck.txt: -------------------------------------------------------------------------------- 1 | *colddeck.txt* Column dc *colddeck* 2 | 3 | Colddeck MANUAL 4 | 5 | 1. About colddeck |colddeck-about| 6 | 2. Quick Start |colddeck-quickstart| 7 | 3. Syntax |colddeck-syntax| 8 | 4. Default Mappings |colddeck-default-mappings| 9 | 5. Commands |colddeck-commands| 10 | 6. Options |colddeck-options| 11 | 7. Changelog |colddeck-changelog| 12 | 8. Contribute |colddeck-contribute| 13 | 9. License |colddeck-license| 14 | 15 | ============================================================================= 16 | ABOUT COLDDECK *colddeck-about* 17 | 18 | Colddeck turns Vim into a simple column-based spreadsheet, ala instacalc.com. 19 | 20 | All lines are fed into the `dc` program, that must be installed on your system. 21 | 22 | Features: 23 | 24 | - RPN-based computations 25 | - References to other rows 26 | - Ranges 27 | - Aggregates (sum, min/max, average...) 28 | - Vim expressions (experimental) 29 | - Value references (experimental) 30 | 31 | ============================================================================= 32 | QUICK START *colddeck-quickstart* 33 | 34 | 1. Install the plugin Eg. with Pathogen: 35 | > 36 | cd ~/.vim/bundle && git clone https://github.com/fcpg/vim-colddeck 37 | < 38 | or using vim8 package management: 39 | > 40 | cd ~/.vim/pack/std/start && git clone https://github.com/fcpg/vim-colddeck 41 | < 42 | 2. Open a file with the `.cdeck` extension: 43 | > 44 | vim budget.cdeck 45 | < 46 | 3. Insert some lines on top (comments included): 47 | > 48 | 300 # food 49 | 800 # rent 50 | 50 # bills 51 | 250 # misc 52 | R1:R4@sum ## Total 53 | R5 12* ## Yearly 54 | < 55 | ============================================================================= 56 | SYNTAX *colddeck-syntax* 57 | 58 | Each line is a `dc` command, that will be fed directly to `dc`, from top to 59 | bottom. Each command is run on an empty stack. Once the command is run, the 60 | result inserted into the buffer is the one at the top of the stack. 61 | 62 | Lines can include comments, starting with `#`. They are not passed to `dc`. 63 | 64 | Comments with double hash (`##`) hide the command part, and the comment text 65 | becomes right-aligned by default. Delete one hash to edit the command again. 66 | 67 | Commands can reference other lines with the `R+num` syntax, eg. `R1`, `R3` etc. 68 | Internally, commands are stored as macros, and they are executed each time 69 | they are referenced. 70 | 71 | Relative references are in the form `R+1` and `R-2`, to refer to the next row 72 | or the second row above, respectively. 73 | 74 | Several references can be used with ranges, using the syntax `ref:ref`, eg. 75 | `R1:R3`. This will insert the values from the range, with the total number 76 | of inserted elements at the top of the stack (so, `R1:R3` will insert the 77 | value of `R1`, `R2` and `R3`, with an extra `3` on top of the stack. 78 | 79 | A few aggregates are available, implemented internally with `dc` macros: 80 | - `@sum` 81 | - `@prod` 82 | - `@avg` 83 | - `@min` 84 | - `@max` 85 | 86 | They expected values on the stack, with the number of elements on top. 87 | This makes it easy to work with ranges: 88 | > 89 | R1:R3 @sum 90 | < 91 | will compute the sum from `R1` to `R3`. 92 | 93 | Experimental: vim expressions can be inserted on the line, before feeding 94 | the line to `dc`. It is thus a kind of vim preprocessor: 95 | > 96 | `log(2)` 2* 97 | < 98 | will double the natural log of 2. 99 | 100 | Experimental: the result of another line can be referenced with the `$+num` 101 | syntax eg. `$2`. This means the result must already be availble, ie. 102 | computations have at least be run once. This allows things like: 103 | > 104 | `sin($2)` 105 | < 106 | which can be convenient since good old `dc` does not offer much maths 107 | functions. 108 | 109 | A few notes: 110 | - dc registers under chr(48) are reserved for internal purposes. 111 | - The `?` register contains the string `True`, allowing things like `0 0=?` . 112 | This is for mere convenience, and can be overridden if need be. 113 | - Commands can return several values; only the last one will be shown on 114 | result, but all values will be used by other references. 115 | 116 | ============================================================================= 117 | DEFAULT MAPPINGS *colddeck-default-mappings* 118 | 119 | x 120 | Compute results and insert them into buffer. 121 | 122 | c 123 | Clear results from buffer. 124 | 125 | a 126 | Toggle automatic insertion/updates of results. 127 | 128 | A 129 | Toggle automatic right-alignment of "hiding comments" (`## comment`). 130 | 131 | h 132 | Toggle normal and "hiding" comments (`## comment`). 133 | 134 | $ 135 | Move cursor to end of line, ignoring the results part. 136 | 137 | < 138 | Move all results five chars to the left (also takes numeric argument). 139 | 140 | > 141 | Move all results five chars to the right (also takes numeric argument). 142 | 143 | ============================================================================= 144 | COMMANDS *colddeck-commands* 145 | 146 | :CDCalc *:CDCalc* 147 | Compute results and insert them into buffer. 148 | 149 | :CDClear *:CDClear* 150 | Clear results from buffer. 151 | 152 | :CDToggleAutocalc *:CDToggleAutocalc* 153 | Toggle automatic insertion/updates of results. 154 | 155 | :CDAlignHidingComments *:CDAlignHidingComments* 156 | Toggle automatic right-alignment of "hiding comments" (`## comment`). 157 | 158 | :CDToggleHidingComments *:CDToggleHidingComments* 159 | Toggle norma / "hiding" comments" (`## comment`). 160 | 161 | :CDMoveRCol {col} *:CDMoveRCol* 162 | Move all results to the {col} column. 163 | If {col} starts with a -/+, it moves all results of that many columns 164 | to the left/right. 165 | 166 | ============================================================================= 167 | OPTIONS *colddeck-options* 168 | 169 | g:cdeck_autocalc *g:cdeck_autocalc* 170 | Set to 0 to disable automatic computation and insertion 171 | of results. 172 | Default: 1 173 | 174 | g:cdeck_rcol *g:cdeck_rcol* 175 | Column where results will be inserted. 176 | Global or buffer-local. 177 | Default: 78 178 | 179 | g:cdeck_prec *g:cdeck_prec* 180 | Precision, for floats. 181 | Global or buffer-local. 182 | Default: 2 183 | 184 | g:cdeck_precmd *g:cdeck_precmd* 185 | User-defined dc commands to run at each invocation. 186 | Global or buffer-local. 187 | Default: none 188 | 189 | g:cdeck_autoahc *g:cdeck_autoahc* 190 | Set to 0 to disable automatic 'hidden comments' alignement. 191 | Global or buffer-local. 192 | Default: 1 193 | 194 | g:cdeck_rchar *g:cdeck_rchar* 195 | Char separating buffer content from results. 196 | Global or buffer-local. 197 | Default: `>` 198 | 199 | g:cdeck_saveresults *g:cdeck_saveresults* 200 | Set to 1 to include results when saving buffer. 201 | Global or buffer-local. 202 | Default: 0 203 | 204 | g:cdeck_nomaps *g:cdeck_nomaps* 205 | Set to 1 to disable buffer-local mappings creation in 206 | colddeck buffers. 207 | Default: 0 208 | 209 | g:cdeck_dcerr *g:cdeck_dcerr* 210 | Set to 1 to show dc error messages for debugging purposes. 211 | Warning: will mess with results. 212 | Global or buffer-local. 213 | Default: 0 214 | 215 | ============================================================================= 216 | CHANGELOG *colddeck-changelog* 217 | 218 | [1.0] - 2019-03-19 219 | - Initial release 220 | 221 | ============================================================================= 222 | CONTRIBUTE *colddeck-contribute* 223 | 224 | Contribute on [Github](https://github.com/fcpg/vim-colddeck) 225 | 226 | ============================================================================= 227 | LICENSE *colddeck-license* 228 | 229 | [Attribution-ShareAlike 4.0 Int.](https://creativecommons.org/licenses/by-sa/4.0/) 230 | 231 | vim: set expandtab sts=2 ts=2 sw=2 tw=78 ft=help norl: 232 | -------------------------------------------------------------------------------- /ftdetect/colddeck.vim: -------------------------------------------------------------------------------- 1 | autocmd BufNewFile,BufRead *.cdeck set filetype=colddeck 2 | -------------------------------------------------------------------------------- /ftplugin/colddeck.vim: -------------------------------------------------------------------------------- 1 | " Vim filetype plugin file 2 | " Language: colddeck 3 | 4 | if exists("b:did_ftplugin") 5 | finish 6 | endif 7 | let b:did_ftplugin = 1 8 | 9 | let b:undo_ftplugin = "setl cc< nu< | unlet! b:cdeck_results" 10 | 11 | let &l:cc = get(g:, 'cdeck_rcol', 78) 12 | setl nu 13 | 14 | let b:cdeck_results = {} 15 | 16 | if get(b:, 'cdeck_autocalc', get(g:, 'cdeck_autocalc', 1)) 17 | call colddeck#SetAutoCalc() 18 | endif 19 | 20 | "--------------- 21 | " Mappings {{{1 22 | "--------------- 23 | 24 | if !get(g:, 'cdeck_nomaps', 0) 25 | nnoremap x :CDCalc 26 | nnoremap c :CDClear 27 | nnoremap a :CDToggleAutocalc 28 | nnoremap A :CDAlignHidingComments 29 | 30 | nnoremap h :CDToggleHidingComments 31 | nnoremap < 32 | \ :CDMoveRCol =empty(v:count)? "-5" : v:count 33 | nnoremap > 34 | \ :CDMoveRCol =empty(v:count)? "+5" : v:count 35 | nnoremap $ :call search('\v^.*\zs\S\ze%<'. 36 | \ (get(b:, "cdeck_rcol", get(g:, "cdeck_rcol", 78))+1) . 'v.', 37 | \ '', 38 | \ line('.')) 39 | endif 40 | -------------------------------------------------------------------------------- /plugin/colddeck.vim: -------------------------------------------------------------------------------- 1 | " colddeck.vim - column-dc spreadsheet 2 | 3 | let s:save_cpo = &cpo 4 | set cpo&vim 5 | 6 | "--------------- 7 | " Commands {{{1 8 | "--------------- 9 | 10 | " Re-calculate values and insert results 11 | command! -bar CDCalc 12 | \ call colddeck#CalcBuffer() 13 | 14 | " Clear results 15 | command! -bar CDClear 16 | \ call colddeck#RemoveResults() 17 | 18 | " Toggle autocalc (auto-insertion of results when leaving insert mode) 19 | command! -bar CDToggleAutocalc 20 | \ if !get(b:, 'cdeck_auto_', 0) 21 | \| call colddeck#SetAutoCalc() 22 | \| echo "AutoCalc ON" 23 | \| else 24 | \| call colddeck#UnsetAutoCalc() 25 | \| echo "AutoCalc OFF" 26 | \| endif 27 | 28 | " Move the result column (absolute pos, or relative with +/- prefix) 29 | command! -bar -nargs=1 CDMoveRCol 30 | \ call colddeck#MoveRcol() 31 | 32 | " Right-align 'hiding comments' near results 33 | command! -bar CDAlignHidingComments 34 | \ call colddeck#AlignHidingComments() 35 | 36 | " Toggle normal/hiding comments 37 | let s:keeppa = exists(':keeppattern') ? 'keeppa' : '' 38 | command! -bar CDToggleHidingComments 39 | \ if getline('.') =~ '##' 40 | \| silent exe s:keeppa 's/##/# /e' 41 | \| else 42 | \| silent exe s:keeppa 's/# /##/e' 43 | \| endif 44 | 45 | 46 | 47 | "--------------- 48 | " Autocmds {{{1 49 | "--------------- 50 | 51 | " Discard results before saving file, put them back afterwards 52 | " Can be global or buffer-locxl 53 | augroup CDeckSave 54 | au! 55 | autocmd BufWritePre *.cdeck 56 | \ if !get(b:, 'cdeck_saveresults', get(g:, 'cdeck_saveresults', 0)) 57 | \| call colddeck#RemoveResults() 58 | \| endif 59 | autocmd BufWritePost *.cdeck 60 | \ if !get(b:, 'cdeck_saveresults', get(g:, 'cdeck_saveresults', 0)) 61 | \| call colddeck#CalcBuffer() 62 | \| endif 63 | augroup END 64 | 65 | " Activate autocalc for cdeck filetype if option is set 66 | " Global only 67 | augroup CDeckFiletype 68 | au! 69 | if get(g:, 'cdeck_autocalc', 1) 70 | autocmd FileType colddeck call colddeck#CalcBuffer() 71 | endif 72 | augroup END 73 | 74 | 75 | let &cpo = s:save_cpo 76 | -------------------------------------------------------------------------------- /syntax/colddeck.vim: -------------------------------------------------------------------------------- 1 | " Vim syntax file 2 | " FileType: colddeck 3 | " Author: fcpg 4 | " Version: 1.0 5 | " --------------------------------------------------------------------- 6 | 7 | syntax clear 8 | syntax case match 9 | 10 | 11 | " Syntax 12 | 13 | syn match cdeckLine /\v^.+$/ contains=cdeckCommand,cdeckComment 14 | syn match cdeckCommand /\v^[^#]+/ contains=cdeckCmdRef,cdeckCmdFunc,cdeckCmdOp,cdeckCmdStr,cdeckResult contained 15 | syn match cdeckCmdRef /\vR\d+/ contained 16 | syn match cdeckCmdFunc /\v\@%(sum|min|max|avg|prod)/ contained 17 | syn match cdeckCmdOp /[+*/%~|:^;<>=!?]/ contained 18 | syn region cdeckCmdStr matchgroup=cdeckCmdDelim start="\[" end="\]" contained contains=cdeckCmdStr keepend extend oneline 19 | syn match cdeckComment /\v#.*/ contains=cdeckResult contained 20 | 21 | syn match cdeckHiddenLine /\v^.+##.*$/ contains=cdeckHiddenCommand,cdeckHidingComment 22 | syn match cdeckHiddenCommand /\v^[^#]+/ contains=cdeckResult contained 23 | syn match cdeckHidingComment /\v##.*/ contains=cdeckResult,cdeckHidingCommentMark contained 24 | syn match cdeckHidingCommentMark /##/ contained 25 | 26 | exe 'syn match cdeckResult /\V\s\zs'.get(g:, 'cdeck_rchar', '>').'\.\+\$/ contains=cdeckResSep contained' 27 | exe 'syn match cdeckResSep /\V'.get(g:, 'cdeck_rchar', '>').'/ contained' 28 | 29 | 30 | " Highlights 31 | 32 | hi cdeckInvisible guifg=bg guibg=bg ctermbg=bg ctermfg=bg 33 | 34 | hi link cdeckCommand Normal 35 | hi link cdeckCmdRef Identifier 36 | hi link cdeckCmdFunc Function 37 | hi link cdeckCmdOp Operator 38 | hi link cdeckCmdStr String 39 | hi link cdeckCmdDelim Delimiter 40 | hi link cdeckComment Title 41 | hi link cdeckResult Special 42 | hi link cdeckResSep Comment 43 | 44 | hi link cdeckHiddenCommand cdeckInvisible 45 | hi link cdeckHidingComment cdeckComment 46 | hi link cdeckHidingCommentMark Comment 47 | 48 | let b:current_syntax = "colddeck" 49 | --------------------------------------------------------------------------------