├── .gitignore ├── LICENSE ├── README ├── README.mkd ├── autoload └── pad.vim ├── doc ├── pad.design-notes.txt ├── pad.txt ├── ss-filter-query.png ├── ss-incsearch.png └── ss-vim-pad.png ├── ftplugin └── pad.vim ├── plugin └── pad.vim ├── pythonx └── vim_pad │ ├── __init__.py │ ├── handler.py │ ├── list_local.py │ ├── modelines.py │ ├── pad.py │ ├── pad_local.py │ ├── timestamps.py │ ├── utils.py │ └── vim_globals.py ├── syntax └── pad.vim └── tutorials └── vim-pad.tutor /.gitignore: -------------------------------------------------------------------------------- 1 | /doc/tags 2 | *.pyc 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Felipe Morales 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included 12 | in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 | OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This is a mirror of http://www.vim.org/scripts/script.php?script_id=3753 2 | 3 | There are many notetaking plugins for vim. Most of them depend on your notes 4 | having a certain format for the convenience of highlighting stuff like headers, 5 | lists and links. Also mostly, they don't provide a workflow for your notetaking: 6 | you need to create manually a file to put your notes on and save it somewhere 7 | with a name that hopefully makes sense (ever saved a note and then updated its 8 | contents so the filename no longer applied?). Usually too, taking notes is 9 | disruptive of whatever you are doing: imagine you're coding and have an idea you 10 | think you might use afterwards. Ideally, you could just take the note right 11 | there, without needing to travel to your notes, or cluttering your filesystem. 12 | 13 | *vim-pad* tries to solve those issues, by focusing on a definite workflow. 14 | First, it makes it so you can at any moment (in insert and normal mode): 15 | 16 | - open your notes. 17 | - search in your notes. 18 | - create a new note. 19 | 20 | Also, it keeps the filename issue away by: 21 | 22 | - naming your files after the time you created them. This makes them unique and 23 | allows for easy sorting. The filenames are updated when changes are made in 24 | old files, so the date is always equal to the last time you modified your 25 | notes. 26 | - considering the first line of your document as its title. This is in tune with 27 | the way most markup styles work (e.g., markdown) 28 | 29 | vim-pad doesn't specify a format for your notes. Instead, it uses a default, 30 | which you can configure, and allows the use of modelines. Esentially, this 31 | means your notes can be free-form, and you can adapt them to your needs. 32 | -------------------------------------------------------------------------------- /README.mkd: -------------------------------------------------------------------------------- 1 | # vim-pad 2 | 3 | A quick notetaking plugin for vim. 4 | 5 | It offers a similar way of managing notes to the one made popular by tools like 6 | Notational Velocity, where file management is removed from the notetaking 7 | workflow, being replaced by searching and sorting facilities, and where the creation 8 | and searching of notes is integrated. 9 | 10 | Notes in vim-pad are free-form; in fact it tries to make it easy to use any 11 | format you want. It works great along other plugins like 12 | [VimOutliner](https://github.com/vimoutliner/vimoutliner/) and 13 | [quicktask](https://github.com/aaronbieber/quicktask). 14 | 15 | **IMPORTANT**: `vim-pad` requires `+python` and `+conceal` support from vim. 16 | Check if the flags are enabled in `:version`. Currently, it also requires 17 | either a `grep` with perl regexes support or `ack`, which might not be the case 18 | under OSX. Windows is not supported. 19 | 20 | 21 | ![screen1](https://raw.githubusercontent.com/fmoralesc/vim-pad/devel/doc/ss-vim-pad.png) 22 | 23 | ![screen2](https://raw.githubusercontent.com/fmoralesc/vim-pad/devel/doc/ss-filter-query.png) 24 | 25 | ![screen3](https://raw.githubusercontent.com/fmoralesc/vim-pad/devel/doc/ss-incsearch.png) 26 | 27 | ## Branches 28 | 29 | * `master` contains the released version of the plugin. 30 | 31 | * `devel` contains the development version of the plugin. 32 | 33 | Pull requests are to be done over `devel`. When submitting a bug, please tag 34 | the affected versions. 35 | 36 | ## Configuration and Usage 37 | 38 | **IMPORTANT**: you must set the g:pad#dir variable to a valid path. It is 39 | recommended to use an empty folder for this. 40 | 41 | For the full documentation, please consult 42 | 43 | :help vim-pad 44 | 45 | If you have [vim-tutor-mode](https://github.com/fmoralesc/vim-tutor-mode), you 46 | can read a tutorial on using vim-pad with 47 | 48 | :Tutor vim-pad 49 | -------------------------------------------------------------------------------- /autoload/pad.vim: -------------------------------------------------------------------------------- 1 | " vim: set fdm=marker fdc=2 : 2 | 3 | " Pad Information: {{{1 4 | 5 | " Gets the title of the currently selected pad 6 | function! pad#GetPadTitle() 7 | if getline('.') != "" 8 | try 9 | let retval = split(split(substitute(getline('.'), '↲','\n', "g"), '\n')[0], '\%u2e25 ')[1] 10 | catch /E684/ 11 | let retval "EMPTY" 12 | endtry 13 | return retval 14 | endif 15 | return "" 16 | endfunction 17 | 18 | " Gets the human readable date of the currently selected pad 19 | function! pad#GetPadHumanDate() 20 | if getline('.') != "" 21 | return split(split(getline('.'), ' │')[0], '@')[1] 22 | endif 23 | return "" 24 | endfunction 25 | 26 | " Gets the id of the currently selected pad 27 | function! pad#GetPadId() 28 | if getline('.') != "" 29 | return split(getline('.'))[0] 30 | endif 31 | return "" 32 | endfunction 33 | 34 | " Operations: {{{1 35 | if has("python") 36 | python import vim_pad 37 | 38 | " Global {{{2 39 | 40 | function! pad#PadCmd(args, bang) 41 | let arg_data = split(a:args, ' ') 42 | if arg_data[0] =~ '\(new\|ls\|this\)' 43 | let l:args = join(arg_data[1:], ' ') 44 | if arg_data[0] == 'ls' 45 | execute "python vim_pad.handler.display('".l:args."', '".a:bang."')" 46 | elseif arg_data[0] == 'new' 47 | if a:bang != '!' 48 | execute "python vim_pad.handler.open_pad(first_line='".l:args."')" 49 | else 50 | let pth = expand('%:p:h'). '/' . g:pad#local_dir . "/" 51 | execute "python vim_pad.handler.open_pad(path='".pth."'+vim_pad.timestamps.timestamp())" 52 | " make sure the directory exists when we try to save 53 | exe "au! BufWritePre,FileWritePre call mkdir(fnamemodify('".pth."', ':h'), 'p')" 54 | endif 55 | elseif arg_data[0] == 'this' && g:pad#local_dir != '' "only allow this if g:pad#local_dir is set 56 | let pth = expand('%:p:h'). '/' . g:pad#local_dir . "/" . expand('%:t'). '.txt' 57 | execute "python vim_pad.handler.open_pad(path='".pth."', first_line='".expand('%:t')."')" 58 | " make sure the directory exists when we try to save 59 | exe "au! BufWritePre,FileWritePre call mkdir(fnamemodify('".pth."', ':h'), 'p')" 60 | endif 61 | endif 62 | endfunction 63 | 64 | function! pad#PadCmdComplete(A,L,P) 65 | let cmd_args = split(a:L, ' ', 1)[1:] 66 | echom string(cmd_args) 67 | if len(cmd_args) == 1 68 | let options = "ls\nnew" 69 | if g:pad#local_dir != '' "only complete 'this' is g:pad#local_dir is set 70 | let options .= "\nthis" 71 | endif 72 | return options 73 | else 74 | return "" 75 | endif 76 | endfunction 77 | 78 | function! pad#OpenPad(title) 79 | call pad#PadCmd('new '.a:title, '') 80 | endfunction 81 | 82 | function! pad#ListPads(query, archive) 83 | call pad#PadCmd('ls '.a:query, a:archive) 84 | endfunction 85 | 86 | function! pad#SearchPads() 87 | python vim_pad.handler.search_pads() 88 | endfunction 89 | 90 | function! pad#GlobalIncrementalSearch(open) 91 | python import vim 92 | python vim_pad.handler.global_incremental_search(bool(int(vim.eval('a:open')))) 93 | endfunction 94 | 95 | " Pad local {{{2 96 | 97 | function! pad#UpdatePad() 98 | python vim_pad.pad_local.update() 99 | endfunction 100 | 101 | function! pad#DeleteThis() 102 | python vim_pad.pad_local.delete() 103 | endfunction 104 | 105 | function! pad#AddModeline() 106 | python vim_pad.pad_local.add_modeline() 107 | endfunction 108 | 109 | function! pad#MoveToFolder() 110 | python vim_pad.pad_local.move_to_folder() 111 | endfunction 112 | 113 | function! pad#MoveToSaveDir() 114 | python vim_pad.pad_local.move_to_savedir() 115 | endfunction 116 | 117 | function! pad#Archive() 118 | python vim_pad.pad_local.archive() 119 | endfunction 120 | 121 | function! pad#Unarchive() 122 | python vim_pad.pad_local.unarchive() 123 | endfunction 124 | 125 | " List local {{{2 126 | 127 | function! pad#EditPad() 128 | python vim_pad.list_local.edit_pad() 129 | endfunction 130 | 131 | function! pad#DeletePad() 132 | python vim_pad.list_local.delete_pad() 133 | endfunction 134 | 135 | function! pad#MovePad() 136 | python vim_pad.list_local.move_to_folder() 137 | endfunction 138 | 139 | function! pad#MovePadToSaveDir() 140 | python vim_pad.list_local.move_to_savedir() 141 | endfunction 142 | 143 | function! pad#ArchivePad() 144 | python vim_pad.list_local.archive_pad() 145 | endfunction 146 | 147 | function! pad#UnarchivePad() 148 | python vim_pad.list_local.unarchive_pad() 149 | endfunction 150 | 151 | function! pad#IncrementalSearch() 152 | python vim_pad.list_local.incremental_search() 153 | endfunction 154 | 155 | function! pad#Sort() 156 | let s:sort_type = input("[pad] sort list by (title=1, tags=2, date=3): ", "1") 157 | if s:sort_type != "" 158 | execute "python vim_pad.list_local.sort('".s:sort_type."')" 159 | endif 160 | redraw! 161 | endfunction 162 | 163 | endif 164 | -------------------------------------------------------------------------------- /doc/pad.design-notes.txt: -------------------------------------------------------------------------------- 1 | vim: ft=vo_base: 2 | State 0 3 | User is editing a file, normal or insert mode 4 | * Event:Key: - > State 1 5 | * Event:Key: - > State 2 6 | State 1 7 | Notes list is displayed 8 | * Event:Init 9 | -> Get notes list -> Populate cache 10 | -> Display from cache 11 | * Event:VimResize 12 | - > Display from cache 13 | State 2 14 | New note is displayed 15 | 16 | -------------------------------------------------------------------------------- /doc/pad.txt: -------------------------------------------------------------------------------- 1 | *vim-pad* 2 | 3 | _ 4 | __ _ o _ _ __ ___ __)) 5 | \(/'(( ((`1( -- ((_)((_( ((_( 6 | )) 7 | 8 | 9 | 10 | vim-pad is a quick notetaking plugin for vim. 11 | 12 | It offers a similar way of managing notes to the one made popular by tools like 13 | Notational Velocity, where file management is removed from the notetaking 14 | workflow, being replaced by searching and sorting facilities, and where the creation 15 | and searching of notes is integrated. 16 | 17 | **IMPORTANT**: `vim-pad` requires `+python` and `+conceal` support from vim. 18 | Check if the flags are enabled in `:version`. Currently, it also requires 19 | either a `grep` with perl regexes support or `ack`, which might not be the case 20 | under OSX. Windows is not supported. 21 | 22 | If you have vim-tutor-mode[1] installed, you might want to read vim-pad's tutorial: 23 | > 24 | :Tutor vim-pad 25 | < 26 | 27 | [1]: https://github.com/fmoralesc/vim-tutor-mode 28 | 29 | - Global Commands |vim-pad-global-commands| 30 | - List Commands |vim-pad-list-commands| 31 | - In-Note Commands |vim-pad-note-commands| 32 | - Configuration |vim-pad-configuration| 33 | - Notes Format |vim-pad-notes-format| 34 | - Misc |vim-pad-misc-config| 35 | - Functions |vim-pad-functions| 36 | - Rationale |vim-pad-design-rationale| 37 | 38 | 39 | GLOBAL COMMANDS *vim-pad-global-commands* 40 | --------------- 41 | 42 | - *:Pad* is the main entry to using vim-pad. It can take three forms, as 43 | 44 | *:Pad-ls* 45 | 46 | - `:Pad ls` (``, for the terminal, global: 47 | (pad-list)) which lists the notes. You can pass a string to it if 48 | you want to filter the notes. 49 | 50 | The list of notes should display a series of lines like: 51 | 52 | 2 mins ago | vim-pad is cool.↲ if you let me just say it. 53 | 54 | The part before | should show when the note was last modified. For notes less 55 | than a day old, the timestamp is displayed in a natural format, and after that 56 | the timestamp follows the %Y-%m-%d %H:%M:%S format. 57 | 58 | The first line of the file is taken as a title, and highlighted accordingly. 59 | If the note only spans one line, the text before a dot or a comma is taken as 60 | the title instead. Line breaks are displayed as ↲. 61 | 62 | `ss` in normal mode (default, global: (pad-search)) also calls 63 | `Pad ls`, but asks for a query to filter the notes before presenting the list. 64 | Giving an empty query is equivalent to calling `Pad ls` without arguments. 65 | 66 | By default, `Pad ls` won't show notes from the archive. To list them, you must 67 | pass a bang to the command: 68 | 69 | :Pad! ls 70 | 71 | *:Pad-new* 72 | 73 | - `:Pad new` (``, n in the terminal, global: 74 | (pad-new)) creates a new note. 75 | 76 | If a string is given as its argument, it will insert the text as the first 77 | line in the file. 78 | 79 | If the :Pad command includes a bang (i.e. `:Pad! new`), a local note is created. 80 | 81 | *:Pad-this* 82 | 83 | - `:Pad this` creates a new note in a local dir (defined by *g:pad#local_dir* ), 84 | based on the current file. The created file has a FNAME.txt name. For 85 | example, if |g:pad#local_dir| is "notes", and the user is editing the file 86 | "~/devel/awesome.vim", a note will be created on 87 | "~/devel/notes/awesome.vim.txt". 88 | 89 | LIST COMMANDS *vim-pad-list-commands* 90 | ------------- 91 | 92 | When in the notes list, you can open a note pressing `` and delete it 93 | using `` (`dd` in the terminal ). `` closes the buffer. 94 | 95 | You can start a search among your notes pressing ``in the list. This 96 | will update the buffer in real time. If the query doesn't match any of the 97 | existing files, pressing `Enter` will create a new note with the query inserted 98 | in the first line. 99 | 100 | You can move the selected note to a subfolder by pressing `+f`. 101 | vim.pad will prompt you for the folder name. To move a note to the root 102 | directory (|g:pad#dir|), press `-f`. Likewise, to move a note to 103 | the archive, press `+a`, and `-a` to move it back. 104 | 105 | You can sort the notes in the current view by title, tags or date by pressing 106 | and selecting the mode. 107 | 108 | IN-NOTE COMMANDS *vim-pad-note-commands* 109 | ---------------- 110 | 111 | From a note, you can press `` (`dd` in the 112 | terminal) to delete it. `+m` will ask for a filetype and insert a 113 | modeline in the file accordingly. 114 | 115 | The folder and archive mappings listed above (`+f`and such) also 116 | work inside notes. 117 | 118 | CONFIGURATION *vim-pad-configuration* 119 | ------------- 120 | 121 | NOTE FOR WINDOWS USERS: The plugin will not work correctly unless `encoding` is 122 | set to `utf-8` in your vimrc. Minimal compatibility for latin1 has been 123 | provided, though (the plugin will load, but render incorrectly). 124 | 125 | IMPORTANT 1: set the *g:pad#dir* variable in your .vimrc, to indicate where the 126 | notes will be saved. The default is: 127 | 128 | let g:pad#dir = "~/notes/" 129 | 130 | If the path is invalid (is not writeable or doesn't exist), vim-pad will nag 131 | you to set a valid one. 132 | 133 | NOTE FOR WINDOWS USERS: The pathname escaping is different in Windows. You 134 | might need to escape backward slashes, like so: 135 | 136 | let g:pad#dir = "C:\\Users\\Foo\\Documents\\Notes" 137 | 138 | MAPPINGS *vim-pad-mappings* 139 | 140 | By default, vim-pad sets some global mappings in normal mode. You can disable 141 | those by setting *g:pad#set_mappings* to 0. If you also want to map vim-pad's 142 | functions in insert mode, set this variable to a value of 2. 143 | 144 | Finer grained configuration of the mappings can be done by setting 145 | 146 | *g:pad#maps#list* default = ["", "] 147 | *g:pad#maps#new* = ["n", "] 148 | *g:pad#maps#search* = "ss" 149 | *g:pad#maps#incsearch* = "s" 150 | *g:pad#maps#newsilent* = "s!" 151 | 152 | To set different maps in the terminal and in the GUI, use a list (like in 153 | |g:pad#maps#list| above), where the first item will be used for the terminal 154 | and the second for the GUI. If any of these variables is a string, the same 155 | value will be used for both. 156 | 157 | vim-pad will notice if the mappings have conflicts and warn you. If you want 158 | to disable these messages, set *g:pad#silent_on_mappings_fail* to 1. 159 | 160 | NOTES FORMAT *vim-pad-notes-format* 161 | 162 | The default format for new notes is `markdown`. To change this to other 163 | format, `pandoc` for example, put 164 | 165 | let *g:pad#default_format* = "pandoc" 166 | 167 | in your `.vimrc`. You can also set the individual format of a note by adding 168 | the corresponding modeline. For example, 169 | 170 | 171 | 172 | at the beggining or the end of a file will tell vim to open the file as a 173 | VimOutliner file. The modeline won't be shown in the list view. 174 | 175 | The position modelines are inserted in a file when using pad#AddModeline is 176 | determined by the value of *g:pad#modeline_position* . The default is 177 | `bottom`, which means that it will be inserted at the end of the file. A value 178 | of `top` means that it will be inserted in the first line of the file. 179 | 180 | You can also set the *g:pad#default_file_extension* variable. This will give 181 | all newly saved notes the given file extension (can be useful when 182 | interoperating with apps that don't recognize modelines). 183 | 184 | MISC *vim-pad-misc-config* 185 | 186 | The height of the split windows this plugin uses can be set with 187 | *g:pad#window_height* (the default is 8). 188 | 189 | Notes are opened by default in a split window the same height as the __Pad__ 190 | buffer. If you want to open the notes in the main window, set 191 | *g:pad#open_in_split* to 0. 192 | 193 | vim-pad's list is opened at the bottom by default. If you want to open it at 194 | the right side of the window, you must change the value of 195 | *g:pad#position["list"]* to "right" (the default is "bottom"). You can set the 196 | window width with *g:pad#window_width* (default: 40). When vim-pad is opened 197 | this way, the timestamp is hidden. Likewise, you can tell vim-pad to open the 198 | notes at the right side of the window by setting the value of 199 | *g:pad#position["pads"]* to "right". 200 | 201 | vim-pad can search using either `grep`, `ack`, `ag` (the silver searcher), or 202 | `pt` (the platinum searcher). grep is the default. You can set this using the 203 | *g:pad#search_backend* variable. By default, the search ignores case (adjust 204 | *g:pad#search_ignore_case* as desired). 205 | 206 | NOTE FOR WINDOWS USERS: You will need a GNU grep compatible executable 207 | in your $PATH in order to search. Cygwin's version has been tested succesfully. 208 | 209 | vim-pad can also query directory and filename queries. For the first, it will 210 | add all files in a folder matching the query. The second simply adds files 211 | that match the query; it can be useful when file renaming is disabled (see 212 | |g:pad#rename_files|. You can adjust these behaviors through the 213 | *g:pad#query_dirnames* (default=1) and *g:pad#query_filenames* (default=0). 214 | 215 | When showing the list of notes, vim-pad reads by default 200 chars from the 216 | files, in order to show a summary of the file. You can adjust how many chars 217 | you want vim-pad to read by setting the *g:pad#read_nchars_from_files* variable. 218 | 219 | If you want the notes title to be their first line, you can set 220 | *g:pad#title_first_line* to 1 (default is 0) 221 | 222 | vim-pad renames files to reflect their contents, using a file name similar to 223 | the note title. The renames are done automatically when you leave/close a note. 224 | If you do not want vim-pad to rename the files you can set *g:pad#rename_files* 225 | to 0. 226 | 227 | FUNCTIONS *vim-pad-functions* 228 | --------- 229 | 230 | - *pad#PadCmd(args, bang)* main entry 231 | - *pad#OpenPad(title)* creates a new note. 232 | - *pad#ListPads(query, bang)* displays the list of notes. 233 | - *pad#SearchPads(query)* shows the search note prompt 234 | 235 | - *pad#UpdatePad()* updates the pad file (internal) 236 | - *pad#DeleteThis()* deletes the currently open note 237 | - *pad#AddModeline()* adds a modeline 238 | - *pad#MoveToFolder()* moves a note to a subfolder of |g:pad#dir| 239 | - *pad#MoveToSaveDir* moves a note to |g:pad#dir| 240 | - *pad#Archive* archives a note 241 | - *pad#Unarchive* moves an archived note back to |g:pad#dir| 242 | 243 | - *pad#EditPad()* edit the selected note 244 | - *pad#DeletePad()* delete the selected note 245 | - *pad#MovePad()* move the selected note to a subfolder of |g:pad#dir| 246 | - *pad#MovePadToSaveDir()* move the selected note to |g:pad#dir| 247 | - *pad#ArchivePad()* archive the selected note 248 | - *pad#UnarchivePad()* move the selected note back to |g:pad#dir| 249 | - *pad#IncrementalSearch()* search incrementally. takes an argument, if it is 1, it will create a 250 | new note with the query if enter is pressed, it 0, it will save the 251 | query as a note, but it will not open it. 252 | - *pad#Sort()* sort the displayed entries 253 | 254 | - *pad#GetPadTitle()* retrieve the selected note title 255 | - *pad#GetHumanDate()* retrieve the selected note data 256 | - *pad#GetPadId()* retrieve the selected note id 257 | 258 | RATIONALE *vim-pad-design-rationale* 259 | --------- 260 | 261 | vim-pad has as its goals: 262 | 263 | - Abstract file management away from notetaking. You shouldn't have to think 264 | about where to put your notes and how to name them. 265 | - Make input and retrieval of notes as fast as possible. Searching for a note 266 | should be easy. 267 | - Make notetaking as effortless as possible, trying never to disrupt your 268 | workflow more than necessary. 269 | 270 | vim-pad tries to reach them by setting up a certain (opinionated) workflow for 271 | notetaking. Besides mapping itself so search, listing and creation of notes is 272 | never more than a few keypresses away, it abstracts file management by keeping 273 | your notes in a single place, renaming files when they changed (this way, 274 | filenames should reflect the note content). 275 | 276 | vim-pad doesn't specify a format for your notes. Instead, it uses a default, 277 | which you can configure, and incentives the use of modelines. This means that 278 | your notes can be free-form and adapt to your needs, and also, that you can use 279 | vim-pad as a complement for other note taking plugins (it works great along 280 | other plugins like [VimOutliner](https://github.com/vimoutliner/vimoutliner/) 281 | and [quicktask](https://github.com/aaronbieber/quicktask).) 282 | -------------------------------------------------------------------------------- /doc/ss-filter-query.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vim-scripts/vim-pad/2e441ae00c684079071086172e6dd0c1799fb262/doc/ss-filter-query.png -------------------------------------------------------------------------------- /doc/ss-incsearch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vim-scripts/vim-pad/2e441ae00c684079071086172e6dd0c1799fb262/doc/ss-incsearch.png -------------------------------------------------------------------------------- /doc/ss-vim-pad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vim-scripts/vim-pad/2e441ae00c684079071086172e6dd0c1799fb262/doc/ss-vim-pad.png -------------------------------------------------------------------------------- /ftplugin/pad.vim: -------------------------------------------------------------------------------- 1 | setlocal fileencoding=utf-8 2 | setlocal cursorline 3 | setlocal buftype=nofile 4 | setlocal noswapfile 5 | setlocal nowrap 6 | setlocal nobuflisted 7 | setlocal nomodified 8 | setlocal conceallevel=2 9 | setlocal concealcursor=nc 10 | noremap :call pad#EditPad() 11 | noremap dd :call pad#DeletePad() 12 | noremap +a :call pad#ArchivePad() 13 | noremap -a :call pad#UnarchivePad() 14 | noremap +f :call pad#MovePad() 15 | noremap -f :call pad#MovePadToSaveDir() 16 | noremap q :bw 17 | noremap :call pad#IncrementalSearch() 18 | noremap :call pad#Sort() 19 | if !exists("b:pad_query") 20 | let b:pad_query = '' 21 | endif 22 | -------------------------------------------------------------------------------- /plugin/pad.vim: -------------------------------------------------------------------------------- 1 | " vim: set fdm=marker fdc=2: 2 | 3 | " File: pad.vim 4 | " Description: Quick-notetaking for vim. 5 | " Author: Felipe Morales 6 | " Version: 1.1 7 | 8 | " Must we load? {{{1 9 | if (exists("g:loaded_pad") && g:loaded_pad) || &cp || has("python") == 0 10 | finish 11 | endif 12 | let g:loaded_pad = 1 "}}} 13 | 14 | " Default Settings: {{{1 15 | " 16 | " Dirs: {{{2 17 | if !exists('g:pad#dir') 18 | if exists('g:pad_dir') 19 | let g:pad#dir = g:pad_dir 20 | echom "vim-pad: g:pad_dir was used for g:pad#dir. Please update your configuration." 21 | elseif filewritable(expand("~/notes")) == 2 22 | let g:pad#dir = "~/notes" 23 | else 24 | let g:pad#dir = "" 25 | endif 26 | else 27 | if filewritable(expand(eval("g:pad#dir"))) != 2 28 | let g:pad#dir = "" 29 | endif 30 | endif 31 | if !exists('g:pad#local_dir') 32 | let g:pad#local_dir = 'notes' 33 | endif 34 | " Files: {{{2 35 | if !exists('g:pad#default_format') 36 | let g:pad#default_format = "markdown" 37 | endif 38 | if !exists('g:pad#default_file_extension') 39 | let g:pad#default_file_extension = '' 40 | endif 41 | if !exists('g:pad#rename_files') 42 | let g:pad#rename_files = 1 43 | endif 44 | if !exists('g:pad#title_first_line') 45 | let g:pad#title_first_line = 0 46 | endif 47 | if !exists('g:pad#modeline_position') 48 | let g:pad#modeline_position = 'bottom' 49 | endif 50 | " Window: {{{2 51 | if !exists('g:pad#window_height') 52 | let g:pad#window_height = 5 53 | endif 54 | if !exists('g:pad#window_width') 55 | let g:pad#window_width = 40 56 | endif 57 | if !exists('g:pad#position') 58 | let g:pad#position = { "list" : "bottom", "pads": "bottom" } 59 | endif 60 | if !exists('g:pad#open_in_split') 61 | let g:pad#open_in_split = 1 62 | endif 63 | " Search: {{{2 64 | if !exists('g:pad#search_backend') 65 | let g:pad#search_backend = "grep" 66 | endif 67 | if !exists('g:pad#search_ignorecase') 68 | let g:pad#search_ignorecase = 1 69 | endif 70 | if !exists('g:pad#query_filenames') 71 | let g:pad#query_filenames = 0 72 | endif 73 | if !exists('g:pad#query_dirnames') 74 | let g:pad#query_dirnames = 1 75 | endif 76 | " Display: {{{2 77 | if !exists('g:pad#read_nchars_from_files') 78 | let g:pad#read_nchars_from_files = 200 79 | endif 80 | if !exists('g:pad#highlighting_variant') 81 | let g:pad#highlighting_variant = 0 82 | endif 83 | if !exists('g:pad#highlight_query') 84 | let g:pad#highlight_query = 1 85 | endif 86 | if !exists('g:pad#jumpto_query') 87 | let g:pad#jumpto_query = 1 88 | endif 89 | if !exists('g:pad#show_dir') 90 | let g:pad#show_dir = 1 91 | endif 92 | " Mappings: {{{2 93 | if !exists('g:pad#set_mappings') 94 | let g:pad#set_mappings = 1 95 | endif 96 | if !exists('g:pad#silent_on_mappings_fail') 97 | let g:pad#silent_on_mappings_fail = 0 98 | endif 99 | if !exists('g:pad#maps#list') 100 | let g:pad#maps#list = ["", ""] 101 | endif 102 | if !exists('g:pad#maps#new') 103 | let g:pad#maps#new = ["n", ""] 104 | endif 105 | if !exists('g:pad#maps#search') 106 | let g:pad#maps#search = "ss" 107 | endif 108 | if !exists('g:pad#maps#incsearch') 109 | let g:pad#maps#incsearch = "s" 110 | endif 111 | if !exists('g:pad#maps#newsilent') 112 | let g:pad#maps#newsilent = "s!" 113 | endif 114 | 115 | " Commands: {{{1 116 | " 117 | " Creates a new note 118 | command! -nargs=+ -bang -complete=custom,pad#PadCmdComplete Pad call pad#PadCmd('', '') 119 | 120 | " Key Mappings: {{{1 121 | 122 | " maps: {{{2 123 | noremap (pad-list) :Pad ls 124 | inoremap (pad-list) :Pad ls 125 | noremap (pad-new) :Pad new 126 | inoremap (pad-new) :Pad new 127 | noremap (pad-search) :call pad#SearchPads() 128 | noremap (pad-incremental-search) :call pad#GlobalIncrementalSearch(1) 129 | noremap (pad-incremental-new-note) :call pad#GlobalIncrementalSearch(0) 130 | 131 | " You can set custom bindings by re-mapping the previous ones. 132 | " For example, you can add the following to your vimrc: 133 | " 134 | " nmap ,pl (pad-list) 135 | " 136 | " If you want disable the default_mappings, set 137 | " g:pad#use_default_mappings to 0 138 | 139 | function! s:CreateMapping(key, action, ...) "{{{2 140 | if type(a:key) == type([]) && len(a:key) == 2 141 | let l:key = a:key[has("gui_running")] 142 | else 143 | let l:key = a:key 144 | endif 145 | 146 | " this allows calling this function to create insert-mode only mappings 147 | " call s:CreateMapping(",pl", "pad-list", [2]) 148 | " (this is currently unused) 149 | if a:0 > 0 150 | let l:modes_range = a:1 151 | else 152 | let l:modes_range = range(1, g:pad#set_mappings) 153 | endif 154 | 155 | for l:mode_idx in l:modes_range 156 | let l:mode = l:mode_idx == 1 ? "nmap" : "imap" 157 | try 158 | execute "silent " . l:mode . " " . l:key . " (" . a:action . ")" 159 | catch /E227/ 160 | if g:pad#silent_on_mappings_fail < 1 161 | echom "[vim-pad] " . l:key . " in " . l:mode_idx == 1? "normal" : "insert" . " mode is already mapped." 162 | endif 163 | endtry 164 | endfor 165 | endfunction 166 | 167 | " Set maps, if wanted: {{{2 168 | if g:pad#set_mappings > 0 169 | call s:CreateMapping(g:pad#maps#search, "pad-search") 170 | call s:CreateMapping(g:pad#maps#incsearch, "pad-incremental-search") 171 | call s:CreateMapping(g:pad#maps#newsilent, "pad-incremental-new-note") 172 | call s:CreateMapping(g:pad#maps#list, "pad-list") 173 | call s:CreateMapping(g:pad#maps#new, "pad-new") 174 | endif 175 | -------------------------------------------------------------------------------- /pythonx/vim_pad/__init__.py: -------------------------------------------------------------------------------- 1 | import vim_pad.handler 2 | import vim_pad.list_local 3 | import vim_pad.pad_local 4 | import vim_pad.vim_globals 5 | 6 | vim_pad.vim_globals.set_vim_globals() 7 | -------------------------------------------------------------------------------- /pythonx/vim_pad/handler.py: -------------------------------------------------------------------------------- 1 | # vim: set fdm=marker fdc=2 : 2 | # coding=utf-8 3 | 4 | # imports {{{1 5 | import vim 6 | import re 7 | from glob import glob 8 | from os import walk 9 | from os.path import join, getmtime, isfile, isdir, exists 10 | from subprocess import Popen, PIPE 11 | from vim_pad.utils import get_save_dir 12 | from vim_pad.pad import PadInfo 13 | from vim_pad.timestamps import natural_timestamp 14 | 15 | # globals (caches) {{{1 16 | cached_data = [] 17 | cached_timestamps = [] 18 | cached_filenames = [] 19 | 20 | 21 | def open_pad(path=None, first_line="", query=''): # {{{1 22 | """Creates or opens a note. 23 | 24 | path: a valid path for a note. 25 | 26 | first_line: a string to insert to a new note, if given. 27 | 28 | query: the previous search, if any. 29 | 30 | """ 31 | # we require self.save_dir_set to be set to a valid path 32 | if get_save_dir() == "": 33 | vim.command('echom "vim-pad: IMPORTANT: please set g:pad#dir to a valid path in your vimrc."') 34 | return 35 | 36 | # if no path is provided, we create one using the current time 37 | if not path: 38 | path = join(get_save_dir(), 39 | PadInfo([first_line]).id + vim.eval("g:pad#default_file_extension")) 40 | path = path.replace(" ", "\ ") 41 | 42 | def split_for_pad(): 43 | if vim.eval('g:pad#position["pads"]') == 'right': 44 | vim.command("silent! rightbelow" 45 | + str(vim.eval("g:pad#window_width")) + "vsplit " + path) 46 | else: 47 | vim.command("silent! botright" 48 | + str(vim.eval("g:pad#window_height")) + "split " + path) 49 | 50 | if bool(int(vim.eval("g:pad#open_in_split"))): 51 | split_for_pad() 52 | else: 53 | awa = int(vim.eval("&autowriteall")) 54 | if bool(int(vim.eval("&modified"))): 55 | reply = vim.eval('input("vim-pad: the current file has unsaved changes. do you want to save? [Yn] ", "y")') 56 | if reply == "y": 57 | vim.command("set autowriteall") 58 | vim.command("silent! edit " + path) 59 | if awa == 0: 60 | vim.command("set noautowriteall") 61 | else: 62 | vim.command('echom "vim-pad: will have to open pad in a split"') 63 | split_for_pad() 64 | vim.command("redraw!") 65 | else: 66 | vim.command("silent! edit " + path) 67 | 68 | # we don't keep the buffer when we hide it 69 | vim.command("set bufhidden=wipe") 70 | 71 | # set the filetype to our default 72 | if vim.eval('&filetype') in ('', 'conf'): 73 | vim.command("set filetype=" + vim.eval("g:pad#default_format")) 74 | 75 | # map the local commands 76 | if bool(int(vim.eval('has("gui_running")'))): 77 | vim.command("noremap :call pad#DeleteThis()") 78 | else: 79 | vim.command("noremap dd :call pad#DeleteThis()") 80 | 81 | vim.command("noremap +m :call pad#AddModeline()") 82 | vim.command("noremap +f :call pad#MoveToFolder()") 83 | vim.command("noremap -f :call pad#MoveToSaveDir()") 84 | vim.command("noremap +a :call pad#Archive()") 85 | vim.command("noremap -a :call pad#Unarchive()") 86 | 87 | # insert the text in first_line to the buffer, if provided 88 | if first_line: 89 | vim.current.buffer.append(first_line, 0) 90 | vim.command("normal! j") 91 | 92 | # highlight query and jump to it? 93 | if query != '': 94 | if vim.eval('g:pad#highlight_query') == '1': 95 | vim.command("call matchadd('PadQuery', '\c"+query+"')") 96 | if vim.eval('g:pad#jumpto_query') == '1': 97 | vim.command("call search('\c"+query+"')") 98 | 99 | def new_pad(text=None): #{{{1 100 | path = join(get_save_dir(), PadInfo([text]).id + vim.eval("g:pad#default_file_extension")) 101 | with open(path, 'w') as new_note: 102 | new_note.write(text) 103 | 104 | def listdir_recursive_nohidden(path, archive): # {{{1 105 | matches = [] 106 | for root, dirnames, filenames in walk(path, topdown=True): 107 | for dirname in dirnames: 108 | if dirname.startswith('.'): 109 | dirnames.remove(dirname) 110 | if archive != "!": 111 | if dirname == "archive": 112 | dirnames.remove(dirname) 113 | matches += [join(root, f) for f in filenames if not f.startswith('.')] 114 | return matches 115 | 116 | def listdir_external(path, archive, query): # {{{1 117 | search_backend = vim.eval("g:pad#search_backend") 118 | if search_backend == "grep": 119 | # we use Perl mode for grep (-P), because it is really fast 120 | command = ["grep", "-P", "-n", "-r", "-l", query, path + "/"] 121 | if archive != "!": 122 | command.append("--exclude-dir=archive") 123 | command.append('--exclude=.*') 124 | command.append("--exclude-dir=.git") 125 | elif search_backend == "ack": 126 | if vim.eval("executable('ack')") == "1": 127 | ack_path = "ack" 128 | else: 129 | ack_path = "/usr/bin/vendor_perl/ack" 130 | command = [ack_path, query, path, "--noheading", "-l"] 131 | if archive != "!": 132 | command.append("--ignore-dir=archive") 133 | command.append('--ignore-file=match:/\./') 134 | elif search_backend == "ag": 135 | if vim.eval("executable('ag')") == "1": 136 | command = ["ag", query, path, "--noheading", "-l"] 137 | if archive != "!": 138 | command.append("--ignore-dir=archive") 139 | elif search_backend == "pt": 140 | if vim.eval("executable('pt')") == "1": 141 | command = ["pt", "-l", "--nogroup"] 142 | if archive != "!": 143 | command.append("--ignore=archive") 144 | command.append(query) 145 | command.append(path) 146 | 147 | if bool(int(vim.eval("g:pad#search_ignorecase"))): 148 | command.append("-i") 149 | 150 | command.append("--max-count=1") 151 | 152 | cmd_output = Popen(command, stdout=PIPE, stderr=PIPE).communicate()[0].split("\n") 153 | 154 | return list(filter(lambda i: i != "", cmd_output)) 155 | 156 | def get_filelist(query=None, archive=None): # {{{1 157 | """ __get_filelist(query) -> list_of_notes 158 | 159 | Returns a list of notes. If no query is provided, all the valid filenames 160 | in self.save_dir are returned in a list, otherwise, return the results of 161 | grep or ack search for query in self.save_dir. 162 | """ 163 | local_path = vim.eval("getcwd(). '/'. g:pad#local_dir") 164 | use_local_dir = vim.eval('g:pad#local_dir') != '' and local_path != get_save_dir() 165 | if not query or query == "": 166 | files = listdir_recursive_nohidden(get_save_dir(), archive) 167 | 168 | if use_local_dir: 169 | files.extend(listdir_recursive_nohidden(local_path, archive)) 170 | else: 171 | files = listdir_external(get_save_dir(), archive, query) 172 | 173 | if bool(int(vim.eval("g:pad#query_filenames"))): 174 | matches = filter(lambda i: not isdir(i) and i not in files, glob(join(get_save_dir(), "*"+query+"*"))) 175 | files.extend(matches) 176 | 177 | if bool(int(vim.eval("g:pad#query_dirnames"))): 178 | matching_dirs = filter(isdir, glob(join(get_save_dir(), "*"+ query+"*"))) 179 | for mdir in matching_dirs: 180 | files.extend(filter(lambda x: x not in files, listdir_recursive_nohidden(mdir, archive))) 181 | 182 | if use_local_dir: 183 | files.extend(listdir_external(local_path, archive, query)) 184 | 185 | return files 186 | 187 | def fill_list(files, queried=False, custom_order=False): # {{{1 188 | """ Writes the list of notes to the __pad__ buffer. 189 | 190 | files: a list of files to process. 191 | 192 | queried: whether files is the result of a query or not. 193 | 194 | custom_order: whether we should keep the order of the list given (implies queried=True). 195 | 196 | Keeps a cache so we only read the notes when the files have been modified. 197 | """ 198 | global cached_filenames, cached_timestamps, cached_data 199 | 200 | # we won't want to touch the cache 201 | if custom_order: 202 | queried = True 203 | 204 | files = filter(exists, [join(get_save_dir(), f) for f in files]) 205 | 206 | timestamps = [getmtime(join(get_save_dir(), f)) for f in files] 207 | 208 | # we will have a new list only on the following cases 209 | if queried or files != cached_filenames or timestamps != cached_timestamps: 210 | lines = [] 211 | if not custom_order: 212 | files = reversed(sorted(files, key=lambda i: getmtime(join(get_save_dir(), i)))) 213 | for pad in files: 214 | pad_path = join(get_save_dir(), pad) 215 | if isfile(pad_path): 216 | pad_path = join(get_save_dir(), pad) 217 | with open(pad_path) as pad_file: 218 | info = PadInfo(pad_file) 219 | if info.isEmpty: 220 | if bool(int(vim.eval("g:pad#show_dir"))): 221 | tail = info.folder + u'\u2e25 '.encode('utf-8') + "[EMPTY]" 222 | else: 223 | tail = "[EMPTY]" 224 | else: 225 | if bool(int(vim.eval("g:pad#show_dir"))): 226 | tail = info.folder + u'\u2e25 '.encode('utf-8') + u'\u21b2'.encode('utf-8').join((info.summary, info.body)) 227 | else: 228 | tail = u'\u21b2'.encode('utf-8').join((info.summary, info.body)) 229 | lines.append(pad + " @ " + tail) 230 | else: 231 | pass 232 | 233 | # we only update the cache if we are not queried, to preserve the global cache 234 | if not queried: 235 | cached_data = lines 236 | cached_timestamps = timestamps 237 | cached_filenames = files 238 | 239 | # update natural timestamps 240 | def add_natural_timestamp(matchobj): 241 | id_string = matchobj.group("id") 242 | mtime = str(int(getmtime(join(get_save_dir(), matchobj.group("id")))*1000000)) 243 | return id_string + " @ " + natural_timestamp(mtime).ljust(19) + " │" 244 | 245 | if not queried: # we use the cache 246 | lines = [re.sub("(?P^.*?) @", add_natural_timestamp, line) for line in cached_data] 247 | else: # we use the new values in lines 248 | lines = [re.sub("(?P^.*?) @", add_natural_timestamp, line) for line in lines] 249 | 250 | # we now show the list 251 | if vim.eval('&modifiable') != '1': 252 | vim.current.buffer.options['modifiable'] = True 253 | del vim.current.buffer[:] # clear the buffer 254 | vim.current.buffer.append(list(lines)) 255 | vim.command("normal! dd") 256 | 257 | def display(query, archive): # {{{1 258 | """ Shows a list of notes. 259 | 260 | query: a string representing a regex search. Can be "". 261 | 262 | Builds a list of files for query and then processes it to show the list in the pad format. 263 | """ 264 | if get_save_dir() == "": 265 | vim.command('let tmp = confirm("IMPORTANT:\n'\ 266 | 'Please set g:pad#dir to a valid path in your vimrc.", "OK", 1, "Error")') 267 | return 268 | pad_files = get_filelist(query, archive) 269 | if len(pad_files) > 0: 270 | if vim.eval("bufexists('__pad__')") == "1": 271 | vim.command("bw __pad__") 272 | if vim.eval('g:pad#position["list"]') == "right": 273 | vim.command("silent! rightbelow " + str(vim.eval('g:pad#window_width')) + "vnew __pad__") 274 | else: 275 | vim.command("silent! botright " + str(vim.eval("g:pad#window_height")) + "new __pad__") 276 | fill_list(pad_files, query != "") 277 | if query != "": 278 | vim.command("let b:pad_query = '" + query + "'") 279 | vim.command("set filetype=pad") 280 | vim.command("setlocal nomodifiable") 281 | vim.command("setlocal statusline=%#PreCondit#\ vim-pad%=%#Comment#" + \ 282 | "%#Special#q%#Comment#:close\ %#Special#dd%#Comment#:delete\ " + \ 283 | "%#Special#[-+]a%#Comment#:[un]archive\ %#Special#[-+]f%#Comment#:move\ [from\|to]\ " + \ 284 | "%#Special#%#Comment#:search\ %#Special#%#Comment#:sort\ ") 285 | else: 286 | print "vim-pad: no pads" 287 | 288 | def search_pads(): # {{{1 289 | """ Aks for a query and lists the matching notes. 290 | """ 291 | if get_save_dir() == "": 292 | vim.command('let tmp = confirm("IMPORTANT:\n'\ 293 | 'Please set g:pad#dir to a valid path in your vimrc.", "OK", 1, "Error")') 294 | return 295 | query = vim.eval('input(">>> ")') 296 | display(query, "") 297 | vim.command("redraw!") 298 | 299 | def global_incremental_search(should_open=True): # {{{1 300 | """ Provides incremental search in normal mode without opening the list. 301 | """ 302 | query = "" 303 | should_create_on_enter = False 304 | 305 | vim.command("echohl None") 306 | vim.command('echo ">> "') 307 | while True: 308 | raw_char = vim.eval("getchar()") 309 | if raw_char in ("13", "27"): 310 | if raw_char == "13": 311 | if should_create_on_enter: 312 | if should_open == True: 313 | open_pad(first_line=query) 314 | else: 315 | print "new_pad" 316 | new_pad(text=query) 317 | vim.command("echohl None") 318 | else: 319 | display(query, True) 320 | vim.command("redraw!") 321 | break 322 | else: 323 | try: # if we can convert to an int, we have a regular key 324 | int(raw_char) # we bring up an error on nr2char 325 | last_char = vim.eval("nr2char(" + raw_char + ")") 326 | query = query + last_char 327 | except: # if we don't, we have some special key 328 | keycode = unicode(raw_char, errors="ignore") 329 | if keycode == "kb": # backspace 330 | query = query[:-len(last_char)] 331 | pad_files = get_filelist(query) 332 | if pad_files != []: 333 | info = "" 334 | vim.command("echohl None") 335 | should_create_on_enter = False 336 | else: # we will create a new pad 337 | info = "[NEW] " 338 | vim.command("echohl WarningMsg") 339 | should_create_on_enter = True 340 | vim.command("redraw") 341 | vim.command('echo ">> ' + info + query + '"') 342 | 343 | -------------------------------------------------------------------------------- /pythonx/vim_pad/list_local.py: -------------------------------------------------------------------------------- 1 | # vim: set fdm=marker fdc=2 : 2 | # coding=utf-8 3 | 4 | # imports {{{1 5 | import vim 6 | import re 7 | from os import remove, mkdir 8 | from os.path import join, basename, exists 9 | from shutil import move 10 | from vim_pad.handler import open_pad, get_filelist, fill_list 11 | from vim_pad.utils import get_save_dir, make_sure_dir_is_empty 12 | 13 | 14 | def get_selected_path(): # {{{1 15 | return join(get_save_dir(), vim.current.line.split(" @")[0]) 16 | 17 | 18 | def edit_pad(): # {{{1 19 | """ Opens the currently selected note in the __pad__ buffer. 20 | """ 21 | path = get_selected_path() 22 | query=vim.eval('b:pad_query') 23 | vim.command("bd") 24 | open_pad(path=path, query=query) 25 | 26 | 27 | def delete_pad(): # {{{1 28 | """ Deletes the currently selected note in the __pad__ buffer. 29 | """ 30 | confirm = vim.eval('input("really delete? (y/n): ")') 31 | if confirm in ("y", "Y"): 32 | path = get_selected_path() 33 | remove(path) 34 | make_sure_dir_is_empty(path) 35 | vim.command("ListPads") 36 | vim.command("redraw!") 37 | 38 | 39 | def move_to_folder(path=None): # {{{1 40 | """ Moves the selected pad to a subfolder of g:pad#dir 41 | """ 42 | selected_path = get_selected_path() 43 | if path is None: 44 | path = vim.eval('input("move to: ")') 45 | if not exists(join(get_save_dir(), path)): 46 | mkdir(join(get_save_dir(), path)) 47 | move(selected_path, join(get_save_dir(), path, basename(selected_path))) 48 | make_sure_dir_is_empty(path) 49 | vim.command("ListPads") 50 | if path is None: 51 | vim.command("redraw!") 52 | 53 | 54 | def move_to_savedir(): # {{{1 55 | """ Moves a note to g:pad#dir 56 | """ 57 | move_to_folder("") 58 | 59 | 60 | def archive_pad(): # {{{1 61 | """ Archives the currently selected note 62 | """ 63 | move_to_folder("archive") 64 | 65 | 66 | def unarchive_pad(): # {{{1 67 | """ Unarchives the currently selected note 68 | """ 69 | move_to_savedir() 70 | 71 | 72 | def incremental_search(): # {{{1 73 | """ Provides incremental search within the __pad__ buffer. 74 | """ 75 | query = "" 76 | should_create_on_enter = False 77 | 78 | vim.command("echohl None") 79 | vim.command('echo ">> "') 80 | while True: 81 | raw_char = vim.eval("getchar()") 82 | if raw_char in ("13", "27"): 83 | if raw_char == "13" and should_create_on_enter: 84 | vim.command("bw") 85 | open_pad(first_line=query) 86 | vim.command("echohl None") 87 | vim.command("redraw!") 88 | break 89 | else: 90 | try: # if we can convert to an int, we have a regular key 91 | int(raw_char) # we bring up an error on nr2char 92 | last_char = vim.eval("nr2char(" + raw_char + ")") 93 | query = query + last_char 94 | except: # if we don't, we have some special key 95 | keycode = unicode(raw_char, errors="ignore") 96 | if keycode == "kb": # backspace 97 | query = query[:-len(last_char)] 98 | vim.command("setlocal modifiable") 99 | pad_files = get_filelist(query) 100 | if pad_files != []: 101 | vim.command("let b:pad_query = '"+query+"'") 102 | fill_list(pad_files, query != "") 103 | vim.command("setlocal nomodifiable") 104 | info = "" 105 | vim.command("echohl None") 106 | should_create_on_enter = False 107 | else: # we will create a new pad 108 | del vim.current.buffer[:] 109 | info = "[NEW] " 110 | vim.command("echohl WarningMsg") 111 | should_create_on_enter = True 112 | vim.command("redraw") 113 | vim.command('echo ">> ' + info + query + '"') 114 | # }}}1 115 | # sort types {{{1 116 | SORT_TYPES = { 117 | "1": "title", 118 | "2": "tags", 119 | "3": "date" 120 | } 121 | 122 | 123 | def sort(key="1"): # {{{1 124 | 125 | if key not in SORT_TYPES: 126 | return 127 | 128 | key = SORT_TYPES[key] 129 | if key == "date": 130 | vim.command("ListPads") 131 | return 132 | 133 | tuples = [] 134 | if key == "tags": 135 | view_files = [line.split()[0] for line in vim.current.buffer] 136 | for pad_id in view_files: 137 | with open(pad_id) as fi: 138 | tags = sorted([tag.lower().replace("@", "") 139 | for tag in re.findall("@\w*", fi.read(200))]) 140 | tuples.append((pad_id, tags)) 141 | tuples = sorted(tuples, key=lambda f: f[1]) 142 | tuples = filter(lambda i: i[1] != [], tuples) + \ 143 | filter(lambda i: i[1] == [], tuples) 144 | elif key == "title": 145 | l = 1 146 | for line in vim.current.buffer: 147 | pad_id = line.split()[0] 148 | title = vim.eval('''split(split(substitute(getline(''' + str(l) + '''), '↲','\n', "g"), '\n')[0], ' │ ')[1]''') 149 | tuples.append((pad_id, title)) 150 | l += 1 151 | tuples = sorted(tuples, key=lambda f: f[1]) 152 | 153 | vim.command("setlocal modifiable") 154 | fill_list([f[0] for f in tuples], custom_order=True) 155 | vim.command("setlocal nomodifiable") 156 | -------------------------------------------------------------------------------- /pythonx/vim_pad/modelines.py: -------------------------------------------------------------------------------- 1 | html_style = ("") 2 | vim_style = ('" ', '') 3 | hash_style = ("# ", '') 4 | 5 | comment_style_map = { 6 | "markdown": html_style, 7 | "pandoc": html_style, 8 | "textile": html_style, 9 | "vo_base": html_style, 10 | "quicktask": hash_style 11 | } 12 | 13 | 14 | def format_modeline(filetype): 15 | try: 16 | style = comment_style_map[filetype] 17 | except KeyError: 18 | style = vim_style 19 | return style[0] + "vim: set ft=" + filetype + ":" + style[1] 20 | 21 | -------------------------------------------------------------------------------- /pythonx/vim_pad/pad.py: -------------------------------------------------------------------------------- 1 | import vim 2 | import re 3 | from os.path import abspath, basename, dirname, relpath 4 | from vim_pad.timestamps import timestamp 5 | from vim_pad.utils import get_save_dir 6 | 7 | 8 | class PadInfo(object): 9 | __slots__ = "id", "summary", "body", "isEmpty", "folder" 10 | 11 | def __init__(self, source): 12 | """ 13 | 14 | source can be: 15 | 16 | * a vim buffer 17 | * a file object 18 | * a list of strings, one per line 19 | """ 20 | 21 | nchars = int(vim.eval("g:pad#read_nchars_from_files")) 22 | self.summary = "" 23 | self.body = "" 24 | self.isEmpty = True 25 | self.folder = "" 26 | self.id = timestamp() 27 | 28 | if source is vim.current.buffer: 29 | source = source[:10] 30 | elif source.__class__ == file: 31 | save_dir = get_save_dir() 32 | if abspath(source.name).startswith(save_dir): 33 | pos = len(get_save_dir()), len(basename(source.name)) 34 | self.folder = abspath(source.name)[pos[0]:-pos[1]] 35 | else: 36 | self.folder = dirname(relpath(source.name, vim.eval('getcwd()'))) 37 | if vim.eval("g:pad#title_first_line") == '1': 38 | source = source.readline().split("\n") 39 | else: 40 | source = source.read(nchars).split('\n') 41 | 42 | data = [line.strip() for line in source if line != ""] 43 | 44 | if data != []: 45 | # we discard modelines 46 | if re.match("^.* vim: set .*:.*$", data[0]): 47 | data = data[1:] 48 | 49 | self.summary = data[0].strip() 50 | # vim-orgmode adds tags after whitespace 51 | org_tags_data = re.search("\s+(?P:.*$)", self.summary) 52 | if org_tags_data: 53 | self.summary = re.sub("\s+:.*$", "", self.summary) 54 | if self.summary[0] in ("%", "#"): # pandoc and markdown titles 55 | self.summary = str(self.summary[1:]).strip() 56 | 57 | self.body = u'\u21b2'.encode('utf-8').join(data[1:]).strip() 58 | # if we have orgmode tag data, add it to the body 59 | if org_tags_data: 60 | self.body = ' '.join(\ 61 | [" ".join(\ 62 | map(lambda a: "@" + a, \ 63 | filter(lambda a: a != "", \ 64 | org_tags_data.group("tags").split(":")))), \ 65 | self.body]) 66 | # remove extra spaces in bodies 67 | self.body = re.sub("\s{2,}", "", self.body) 68 | 69 | if self.summary != "": 70 | self.isEmpty = False 71 | self.id = self.summary.lower().replace(" ", "_") 72 | # remove ilegal characters from names (using rules for windows 73 | # systems to err on the side of precaution) 74 | self.id = re.sub("[*:<>/\|^]", "", self.id) 75 | 76 | if self.id.startswith("."): 77 | self.id = re.sub("^\.*", "", self.id) 78 | -------------------------------------------------------------------------------- /pythonx/vim_pad/pad_local.py: -------------------------------------------------------------------------------- 1 | import vim 2 | from shutil import move 3 | from os import remove, mkdir 4 | from os.path import expanduser, exists, join, splitext, isfile, basename, dirname 5 | from vim_pad.pad import PadInfo 6 | from vim_pad.utils import get_save_dir 7 | from vim_pad.modelines import format_modeline 8 | from glob import glob 9 | 10 | 11 | def update(): 12 | """ Moves a note to a new location if its contents are modified. 13 | 14 | Called on the BufLeave event for the notes. 15 | 16 | """ 17 | if not bool(int(vim.eval('exists("b:pad_modified")'))): 18 | return 19 | 20 | modified = bool(int(vim.eval("b:pad_modified"))) 21 | can_rename = bool(int(vim.eval("g:pad#rename_files"))) 22 | if modified and can_rename: 23 | _id = PadInfo(vim.current.buffer).id 24 | old_path = expanduser(vim.current.buffer.name) 25 | 26 | fs = filter(isfile, glob(expanduser(join(dirname(vim.current.buffer.name), _id)) + "*")) 27 | if old_path not in fs: 28 | if fs == []: 29 | new_path = expanduser(join(get_save_dir(), _id)) 30 | else: 31 | exts = map(lambda i: '0' if i == '' else i[1:], 32 | map(lambda i: splitext(i)[1], fs)) 33 | new_path = ".".join([ 34 | expanduser(join(get_save_dir(), _id)), 35 | str(int(max(exts)) + 1)]) 36 | new_path = new_path + vim.eval("g:pad#default_file_extension") 37 | vim.command("bw") 38 | move(old_path, new_path) 39 | 40 | 41 | def delete(): 42 | """ (Local command) Deletes the current note. 43 | """ 44 | path = vim.current.buffer.name 45 | if exists(path): 46 | confirm = vim.eval('input("really delete? (y/n): ")') 47 | if confirm in ("y", "Y"): 48 | remove(path) 49 | vim.command("bd!") 50 | vim.command("redraw!") 51 | 52 | 53 | def add_modeline(): 54 | """ (Local command) Add a modeline to the current note. 55 | """ 56 | mode = vim.eval('input("filetype: ", "", "filetype")') 57 | if mode: 58 | args = [format_modeline(mode)] 59 | if vim.eval('g:pad#modeline_position') == 'top': 60 | args.append(0) 61 | vim.current.buffer.append(*args) 62 | vim.command("set filetype=" + mode) 63 | vim.command("set nomodified") 64 | 65 | 66 | def move_to_folder(path=None): 67 | if path is None: 68 | path = vim.eval("input('move to: ')") 69 | new_path = join(get_save_dir(), path, basename(vim.current.buffer.name)) 70 | if not exists(join(get_save_dir(), path)): 71 | mkdir(join(get_save_dir(), path)) 72 | move(vim.current.buffer.name, new_path) 73 | vim.command("bd") 74 | 75 | 76 | def move_to_savedir(): 77 | move_to_folder("") 78 | 79 | 80 | def archive(): 81 | move_to_folder("archive") 82 | 83 | 84 | def unarchive(): 85 | move_to_savedir() 86 | -------------------------------------------------------------------------------- /pythonx/vim_pad/timestamps.py: -------------------------------------------------------------------------------- 1 | import time 2 | import datetime 3 | from os.path import basename 4 | 5 | 6 | def base36encode(number, alphabet='0123456789abcdefghijklmnopqrstuvxxyz'): 7 | """Convert positive integer to a base36 string.""" 8 | if not isinstance(number, (int, long)): 9 | raise TypeError('number must be an integer') 10 | 11 | # Special case for zero 12 | if number == 0: 13 | return alphabet[0] 14 | 15 | base36 = '' 16 | 17 | sign = '' 18 | if number < 0: 19 | sign = '-' 20 | number = - number 21 | 22 | while number != 0: 23 | number, i = divmod(number, len(alphabet)) 24 | base36 = alphabet[i] + base36 25 | 26 | return sign + base36 27 | 28 | 29 | def protect(id): 30 | """ Prevent filename collisions 31 | """ 32 | return id + "." + base36encode(int(timestamp())) 33 | 34 | 35 | def timestamp(): 36 | """timestamp() -> str:timestamp 37 | 38 | Returns a string of digits representing the current time. 39 | """ 40 | return str(int(time.time() * 1000000)) 41 | 42 | 43 | def natural_timestamp(timestamp): 44 | """natural_timestamp(str:timestamp) -> str:natural_timestamp 45 | 46 | Returns a string representing a datetime object. 47 | 48 | timestamp: a string in the format returned by pad_timestamp. 49 | 50 | The output uses a natural format for timestamps within the previous 51 | 24 hours, and the format %Y-%m-%d %H:%M:%S otherwise. 52 | """ 53 | timestamp = basename(timestamp) 54 | f_timestamp = float(timestamp) / 1000000 55 | tmp_datetime = datetime.datetime.fromtimestamp(f_timestamp) 56 | diff = datetime.datetime.now() - tmp_datetime 57 | days = diff.days 58 | seconds = diff.seconds 59 | minutes = seconds / 60 60 | hours = minutes / 60 61 | 62 | if days > 0: 63 | return tmp_datetime.strftime("%Y-%m-%d %H:%M:%S") 64 | if hours < 1: 65 | if minutes < 1: 66 | return str(seconds) + "s ago" 67 | else: 68 | seconds_diff = seconds - (minutes * 60) 69 | if seconds_diff != 0: 70 | return str(minutes) + "m and " + str(seconds_diff) + "s ago" 71 | else: 72 | return str(minutes) + "m ago" 73 | else: 74 | minutes_diff = minutes - (hours * 60) 75 | if minutes_diff != 0: 76 | return str(hours) + "h and " + str(minutes_diff) + "m ago" 77 | else: 78 | return str(hours) + "h ago" 79 | 80 | -------------------------------------------------------------------------------- /pythonx/vim_pad/utils.py: -------------------------------------------------------------------------------- 1 | import vim 2 | from os import rmdir 3 | from os.path import expanduser, split 4 | 5 | 6 | def get_save_dir(): 7 | return expanduser(vim.eval("g:pad#dir")).replace("\\", "\\\\") 8 | 9 | 10 | def make_sure_dir_is_empty(path): # {{{1 11 | try: 12 | rmdir(split(path)[0]) 13 | except: 14 | pass 15 | 16 | -------------------------------------------------------------------------------- /pythonx/vim_pad/vim_globals.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import vim 3 | from os.path import join 4 | from vim_pad.utils import get_save_dir 5 | 6 | def set_vim_globals(): 7 | """ Sets global vim preferences and commands. 8 | """ 9 | # To update the date when files are modified 10 | if get_save_dir() == "": 11 | vim.command('echom "vim-pad: IMPORTANT: please set g:pad#dir to a valid path in your vimrc."') 12 | vim.command("redraw") 13 | else: 14 | vim.command('execute "au! BufEnter" printf("%s*", g:pad#dir) ":let b:pad_modified = 0"') 15 | vim.command('execute "au! BufWritePre" printf("%s*", g:pad#dir) ":let b:pad_modified = eval(&modified)"') 16 | vim.command('execute "au! BufLeave" printf("%s*", g:pad#dir) ":call pad#UpdatePad()"') 17 | 18 | # vim-pad pollutes the MRU.vim list quite a lot, if let alone. 19 | # This should fix that. 20 | if vim.eval('exists(":MRU")') == "2": 21 | mru_exclude_files = vim.eval("MRU_Exclude_Files") 22 | if mru_exclude_files != '': 23 | tail = "\|" + mru_exclude_files 24 | else: 25 | tail = '' 26 | vim.command("let MRU_Exclude_Files = '^" + 27 | join(get_save_dir(), ".*") + tail + "'") 28 | 29 | # we forbid writing backups of the notes 30 | orig_backupskip = vim.eval("&backupskip") 31 | vim.command("let &backupskip='" + 32 | ",".join([orig_backupskip, join(get_save_dir(), "*")]) + "'") 33 | 34 | -------------------------------------------------------------------------------- /syntax/pad.vim: -------------------------------------------------------------------------------- 1 | if g:pad#position["list"] == "right" 2 | syn match PadTimestamp /^.\{-}│/ conceal 3 | else 4 | syn match PadTimestamp /^.\{-}│/ contains=PadName,PadTimestampDelimiter,PadTimestampTime 5 | endif 6 | syn match PadTimestampTime /\d\d:\d\d:\d\d/ contained 7 | syn match PadTimestampDelimiter /│/ contained 8 | syn match PadName /^.\{-}@/ contained conceal 9 | syn match PadNewLine /\%u21b2/ 10 | syn match PadHashTag /\(@\|#\)\a\+\(\s\|\n\|\%u21b2\)\@=/ 11 | syn match PadEmptyLabel /\[EMPTY\]/ contained 12 | syn match PadFolder / .*\%u2e25/ contained 13 | if g:pad#local_dir != '' 14 | exe 'syn match PadLocal /'.g:pad#local_dir.'/ containedin=PadFolder' 15 | endif 16 | syn match PadFolderStop /\%u2e25/ containedin=PadFolder conceal 17 | syn match PadArchived /\/archive\// containedin=PadFolder 18 | if g:pad#position["list"] == "right" 19 | syn match PadSummaryPad / \//me=e-1 containedin=PadFolder conceal 20 | endif 21 | syn region PadSummary start=/│\@<= /hs=s+1 end=/\(\%u21b2\|$\)\@=/ contains=PadHashTag,PadEmptyLabel,PadFolder 22 | 23 | hi! link PadTimestamp Number 24 | hi! link PadTimestampTime Comment 25 | hi! link PadTimestampDelimiter Delimiter 26 | hi! link PadHashTag Identifier 27 | hi! link PadEmptyLabel Error 28 | hi! link PadSummary Title 29 | hi! link PadNewLine Comment 30 | hi! link PadFolder Directory 31 | hi! link PadLocal Special 32 | hi! link PadArchived Special 33 | hi! link PadQuery Search 34 | 35 | let b:buffer_syntax = "pad" 36 | -------------------------------------------------------------------------------- /tutorials/vim-pad.tutor: -------------------------------------------------------------------------------- 1 | # vim-pad: a tutorial 2 | 3 | vim-pad is a handy note-taking plugin. This document will lead you through its 4 | features and give you some tips. It is also devised as a more hands-on refresher 5 | than [vim-pad's help file](vim-pad), so you can use it as a quick reference. 6 | 7 | To start using vim-pad, you need to point it to the place your notes will be 8 | saved. For this tutorial, we'll use a temp dir. Place your cursor over the 9 | next command and press «>>» 10 | ~~~ viml 11 | :let g:pad#dir = fnamemodify(tempname(), ":h") 12 | ~~~ 13 | IMPORTANT: [g:pad#dir](g:pad#dir) MUST be a full path, vim-pad won't work properly otherwise! 14 | 15 | Table of contents: («zO» to open a section, «zc» to close it) 16 | ## Creating a note 17 | 18 | You should have an empty notes lists now; you need to take note of this! 19 | 20 | To create a new note you can either execute 21 | ~~~ viml 22 | :Pad new 23 | ~~~ 24 | or press . Do so now. 25 | 26 | You'll see a new empty file has opened (with the default settings, it should 27 | open below this [window](window)). Write a note mentioning you didn't have any 28 | notes before and :write the file. You can now close the window with the note. 29 | 30 | EXERCISE: Now, create another note. This time, write something about the sky. 31 | 32 | ## Listing the notes 33 | 34 | You'll want to retrieve your notes now. you can do it by either executing 35 | ~~~ viml 36 | :Pad ls 37 | ~~~ 38 | or pressing . Do it now. You'll see the list show how long ago 39 | you created the notes, and will show you a bit of the notes contents. Press 40 | to open the note in the current line (you'll see this line is 41 | highlighted). 42 | 43 | Before moving on, close any note you could have open. Also, if you want, create 44 | a couple more notes. 45 | 46 | ## Searching 47 | 48 | If you are looking for something in particular within your notes, you'll want to 49 | use vim-pad search utilities. 50 | 51 | Earlier, you created a note about the sky. We'll search for it now. 52 | 53 | Open the notes list and press . You'll see the prompt has changed to 54 | 55 | >> 56 | 57 | You can now type a query. Since we are looking for the note aboout the sky, 58 | type "sky" (let's hope you used the word!). You'll see the list changes when you 59 | type, since it's filtering. Once you have finished searching, press to 60 | finish the query, and then open the note as you've done before. You'll see the 61 | query is highlighted. 62 | 63 | EXERCISE: Try searching for other terms. 64 | 65 | You now know the basics of vim-pad! This should be enough to make good use of 66 | vim-pad as an everyday tool. However, there is still plenty to learn. 67 | 68 | ### Other ways to search 69 | 70 | You can search non interactively, but without opening the notes list, with 71 | []()ss . Pressing after finishing the query will show the 72 | list of matching notes. 73 | 74 | ## More on creating notes 75 | 76 | There is yet another way to search for notes: If you press s in any 77 | window, an interactive search will start. This s pretty similar to ss, 78 | but it will also allow the user to create a new note if the query is not found. 79 | If so, pressing will open a new note with the query pre-appended. This 80 | is a pretty convenient way of creating a new note very quick and keep adding to 81 | it. If you don't need to open the note afterwards, you can use s! 82 | instead (even quicker!). 83 | 84 | EXERCISE: Create a couple notes like this. 85 | 86 | ### Using different types of files for notes 87 | 88 | Have you noticed that sitcky notes come both blank and pre-filled? Well, that is 89 | because not all notes (like people) are born the same! You shouldn't have to 90 | conform to any particular format. vim-pad does not impose any. 91 | 92 | That said, it uses markdown by default, because it is a very good general 93 | purpose format (also because vim comes with support for it by default). You can 94 | change this default to your hearts desire by setting the 95 | [g:pad#default_format](g:pad#default_format) variable. For example, you can make 96 | your notes be LaTeX by default: 97 | ~~~ viml 98 | :let g:pad#default_format = "tex" 99 | ~~~ 100 | To change a particular note's format, you'll have to add a [modeline](modeline). 101 | Doing so by hand is tiresome, so you can press +m to add one. 102 | You'll be prompted for a filetype. Select one and press . Voilá! The 103 | modeline is added, and the filetype is set. 104 | 105 | EXERCISE: Create a new note, add a "html" modeline. Close, open again, check if 106 | the filetype is correct. 107 | 108 | ### Tags 109 | 110 | If you write labels starting with # or @ in your file, they will be treated like 111 | tags when you list the notes. 112 | 113 | EXERCISE: Add the #test tag to some of the notes you've created. Check the list 114 | of notes. 115 | 116 | ### Sorting 117 | 118 | Sometimes you'll want to sort the notes in the list. For example, you might want 119 | to sort alphabetically all the notes you have titled "recipe:...". To do this, 120 | press while the list is open, select the sorting method and press . 121 | 122 | NOTE: Sorting won't undo a query you have previously entered, so you can search 123 | for all notes mentioning "chicken" and then sort them alphabetically. 124 | 125 | ## Deleting notes, using sub-folders and archiving 126 | 127 | If you'be been toying with vim-pad during this tutorial, you'll have a mess of 128 | notes. Let's see what we can do about it... 129 | 130 | ### Deleting notes 131 | 132 | Nuke some! 133 | 134 | From the notes list, select a note you want to delete and then press 135 | dd. You'll be prompted to confirm. 136 | 137 | EXERCISE: Delete the worst of notes. 138 | 139 | If you are editing a note and discover you don't want it anymore (what were you 140 | thinking!), you can press . 141 | 142 | EXERCISE: Open a previously saved note and delete it this way. 143 | 144 | ### Moving into sub-folders 145 | 146 | Perhaps you'll want to organize the notes in groups. One option is to use tags, 147 | which we've seen before, but that requires writing the tags in the files, and 148 | you might not want that. Another option is to place your notes into topic 149 | folders. You can do it manually (and vim-pad will show you the folders when 150 | listing the notes), but there are better ways from within vim. 151 | 152 | From the list, select a note and press «+f» . You'll be prompted for a 153 | folder name to put the note in. If the folder doesn't exist, vim-pad will create 154 | it. 155 | 156 | NOTE: Pressing the same combo within a note, with prepended, does 157 | the same. 158 | 159 | EXERCISE: Create a note and put it in the "test" folder. 160 | 161 | NOTE: you can have subfolders to your subfolders. 162 | 163 | EXERCISE: Move the note in the test folder to the "test/again" folder. 164 | 165 | If you want to move notes back to the root notes dir, you can use 166 | «-f» (-f within the note). 167 | 168 | EXERCISE: Return the note you just created to the root dir. 169 | 170 | ### Archiving 171 | 172 | If you are an avid note-taker, you'll soon have a very large list of notes. But 173 | some notes you simply don't want to have around all the time. For example, you 174 | could have monthly TODO lists, or notes for proyects you've finished already, etc. 175 | You want to keep this stuff, but keep it "away" too. For this, vim-pad features 176 | an archive system. Any note in the special "archive/" folder will be treated as 177 | archived, and won't be shown normaly by :Pad ls. To list the archive, you have 178 | to put a ! after the command, like this 179 | ~~~ viml 180 | :Pad! ls 181 | ~~~ 182 | If you try it now, it won't do anything special, because we haven't archived 183 | anything yet. Let's do it! 184 | 185 | To put things on the archive, you can use «+a» (in both the list and 186 | the notes). 187 | 188 | EXERCISE: Archive a couple of notes, and list the notes with :Pad! ls. 189 | 190 | ## Local notes 191 | 192 | So far, you've seen how to manage a global list of notes. But sometimes when you 193 | work in a project, you want to keep notes about it which are only relevant to 194 | it, and might not want to see them in the global list. For this, vim-pad has the 195 | ability to detect local notes, which are saved in a folder in the current dir. 196 | By default, this folder will be called "notes", but that can be changed by 197 | setting the [g:pad#local_dir](g:pad#local_dir) variable. 198 | 199 | To create a local note, use 200 | ~~~ viml 201 | :Pad! new 202 | ~~~ 203 | (notice the bang !). 204 | 205 | To create a local note about the file you are currently working on, use 206 | ~~~ viml 207 | :Pad this 208 | ~~~ 209 | EXERCISE: Create a local note about this tutorial. List the notes to see it 210 | listed. Delete it. 211 | 212 | ## Conclusion 213 | 214 | I hope this tutorial helps you to use vim-pad more efficiently, and gives you 215 | some ideas about how to handle your notes. If you have suggestions or issues, 216 | please open an issue at https://github.com/fmoralesc/vim-pad/issues or write me 217 | at hel.sheep@gmail.com I try to reply as soon as possible. 218 | 219 | ### Some extras 220 | 221 | For formatting your notes, you might want to check some of these plugins: 222 | 223 | - vimoutliner https://github.com/vimoutliner/vimoutliner 224 | - quicktask https://github.com/aaronbieber/quicktask 225 | - vim-notes https://github.com/xolox/vim-notes 226 | - vim-orgmode https://github.com/jceb/vim-orgmode 227 | - vim-pandoc https://github.com/vim-pandoc/vim-pandoc 228 | 229 | Some of these also have note management utilities, but I think you'll prefer 230 | vim-pad ;) 231 | 232 | vim: set tw=80 foldlevel=1: 233 | 234 | --------------------------------------------------------------------------------