1 diantre.txt Simple task runner for vim
  2 
  3        /
  4       ++
  5       $ $        &###@%      %/                       &&                      *@
  6      /& %        %#####%     #*                       %%                      *#
  7      &@ #*       %@+++%#+    /                        %%                      *#
  8     /##+#@       %%    #$                             %%                      *#
  9     $##%##+      %%    #&  +&&+     +&&&&& +&  $$   /&##&   &* /&*    /&&&+   *#
 10 $@@%//$$*/+@@@+  %%    @&  $##*    +###### *# %##@  /####/  @&/###*  /#####+  *#
 11  ##$ $& %+ %#%   %%    @&  +$#*    @#&$$%# *#$#&%#$  $@@$   @&@@$##  %#&$&#@  *#
 12  $#/&#/ +#*+#+   %%    @&    #*    #$   *# *##$  @%   %%    @##/ +#+ #&   $#  *#
 13   &%#$   %#$&    %%    @&    #*   /#+   *# *#@   &@   %%    @#*   &+ #&***&#/ *#
 14   *##+   *##/    %%    @&    #*   /#+   *# *#/   &@   %%    @%      /#######/ *#
 15    %#%   @#&     %%    @&    #*   /#+   @# *#    &@   %%    @&      /#@%%%%%/ +%
 16    +##+ $##      %%    #$    #*   /#*  &## *#    &@   %@    @&       #$
 17     %#@ ##$      %%///&#+   /#$    #@/$#%# *#    &@   $#*/  @&       @@/////
 18     /##@#@       %#####@   $###@   $###&*# *#    &@    ###& @&       *######/ +#
 19      &###*       %####@/   $###@    &#% *# *#    &@    +@#& @$        $#####/ +@
 20       ##@
 21       $#+
 22        &
 23 
 24 ===============================================================================
 25 CONTENTS                                                        DiantreContent
 26 
 27     1. Introduction ................ DiantreIntroduction
 28     2. Usage ....................... DiantreUsage
 29         2.1 Tasks .................. DiantreTasks
 30         2.2 Completion ............. DiantreCompletion
 31         2.3 Groups ................. DiantreGroups
 32         2.4 Contexts ............... DiantreContexts
 33     3. Configuration................ DiantreConfiguration
 34         3.1 Home Directory ......... DiantreHome
 35         3.2 Presets ................ Presets
 36         3.4 Task versions .......... TasksVersions
 37     4. License ..................... DiantreLicense
 38 
 39 ===============================================================================
 40 1. Introduction                                            DiantreIntroduction
 41 
 42 The word "diantre" means devil in old french and is used like "damn!".
 43 The best translation is probably "deuce" in obsolete english.
 44 
 45 Diantre is a task runner for vim. The main purpose is to benefit from vim
 46 capabilities to edit files and run external commands.
 47 The core idea is to automatically tranform vimscript functions into vim
 48 commands, it relies on autoload mecanism.
 49 
 50 Each task is a vimscript function that have a context and a group:
 51     - the context is the name of the directory inside autoload where the file
 52       that contains the function belongs.
 53     - the group is the file where the task is stored.
 54 
 55 This organization prevents name collision, while providing heuristics to build
 56 practical tools.
 57 Some common task you probably use everyday: start a project in some language,
 58 push, test, deploy your code... are made easy with diantre
 59 
 60 ===============================================================================
 61 2. Usage                                                          DiantreUsage
 62 
 63 Diantre transforms functions like python#project#start(name) into commands
 64 like:
 65     :Diantre start python project <name>
 66 
 67 In this example "python" is the context, "project" is the group, and "start"
 68 the task. This function is stored in autoload/python/project.vim
 69 
 70 It may looks verbose, but it permits to memorize easily the available
 71 commands, and autocompletion is automatically built for each function inside
 72 Diantre home directory.
 73 See DiantreConfiguration to set your context and group with autocommand and
 74 reduce the verbosity.
 75 
 76 NOTE: By default diantre context is set to "diantre" so you don't have to type
 77 it like it's shown in this doc.
 78 For example:
 79     :Diantre new diantre task <name> <context> <group> <args> 
 80 If you've not modified configuration, you can just do:
 81     :di new task <name> <context> <group> <args> 
 82 Full command line is shown in this doc to prevent misunderstandings, both are
 83 working, and autocompletion will suggest both.
 84 
 85 The abbreviation ":di " remove the need of writting ":Diantre " each time,
 86 when you type :space after di in command line "di " will be replaced by
 87 "Diantre ".
 88 For more information see :ab
 89 
 90 This syntax enforce learning of commands by enabling to use common methods
 91 of doing things.
 92 For example you would probably use similar method for any programming
 93 languages, and it's made possible to do:
 94     :di start js project <args> 
 95     :di start nodejs project <args> 
 96     :di start ruby project <args> 
 97     ... to name few
 98 
 99 With plugins js, nodejs, ruby... you add features specific to your programming
100 language while sharing similar heuristics for all languages.
101 
102 You can override tasks, without altering the original, by using
103 versionned tasks (see TasksVersions).
104 
105 
106 
107 -------------------------------------------------------------------------------
108 2.1 Tasks                                                 task DiantreTasks
109 
110     new:                                                                 new
111             Create a new task and edit it:
112                 :Diantre new diantre task <name> <context> <group> <args> 
113             It will create a function <context>#<group>#<name>(<args>) inside
114             <group>.vim file in autoload/<context> directory with parameters
115             <args> and position the cursor inside the function. If task exists
116             it will add a versionned task by adding "__<version>" after the
117             function <name>. see TasksVersions
118             Version is found by getting the highest version of task and
119             adding 1 to it.
120 
121     edit:                                                               edit
122             Open autoload/<context>/<group>.vim and position the cursor inside
123             task <name>:
124                 :Diantre edit diantre task <name> <context> <group>
125 
126             NOTE: markers 's and 'e are added to the start and end of
127             function if task is found and true is returned if function
128             exists, false otherwise
129 
130    close:                                                              close
131             Save and close the group buffer:
132                 :Diantre close diantre task <context> <group>
133 
134   remove:                                                             remove
135             Delete task and group if it's the last task, It returns true if
136             task was found, false otherwise. You can get the deleted code
137             from the unnamed register "":
138                 :Diantre remove diantre task <name> <context> <group>
139 
140     yank:                                                               yank
141             Fill unnamed register "", with the code of the function of the
142             given task. Used internally for task copy:
143                 :Diantre yank diantre task <name> <context> <group>
144 
145   rename:                                                             rename
146             Change task name. If a __complete function was set for this task
147             you can rename it with the task by passing a last argument
148             different than v:false.
149             :Diantre rename diantre task <name> <context> <group> <newname>
150            Renaming completion function with task for example:
151            :Diantre rename diantre task <name> <context> <group> <newname> 1
152 
153    chgrp:                                                              chgrp
154             Change task group, by moving the entire task function and its
155             __complete related function to the new group file if optionnal
156             last argument is given.
157             :Diantre chgrp diantre task <name> <context> <group> <newgroup>
158             [<complete>!= v:false]
159 
160    chdir:                                                              chdir
161             Change task context, by moving the entire task function and its
162             __complete related function to the new context directory if
163             optionnal last argument is given.
164             :Diantre chdir diantre task <name> <context> <group> <newcontext>
165             [<complete>!= v:false]
166 
167     move:                                                               move
168             Move the task and related __complete function to a new context,
169             new group and/or new task name. This function is used for chgrp
170             and chdir, if last optionnal argument is different than v:false
171             it moves __complete function too:
172             :Diantre move diantre task <name> <context> <group> <newname>
173             <newcontext> <newgroup> [<complete>!= v:false]
174 
175     copy:                                                               copy
176             Copy the task and related __complete function to a new context,
177             new group and/or new task name. Like move if a last optionnal
178             argument is given __complete function is copied too
179             :Diantre copy diantre task <name> <context> <group> <newname>
180             <newcontext> <newgroup> [<complete>!= v:false]
181 
182 NOTE: rename, chgrp, move, copy do not erase the destination task if
183 it exists, instead it versions the new task. See TasksVersions for more
184 information.
185 
186 -------------------------------------------------------------------------------
187 2.2 Completion                                 __complete DiantreCompletion
188 
189 The completion system of diantre, is able to look at DiantreHome directory and
190 find all tasks, contexts and groups it contains. It also uses environment
191 variables for preset contexts (PresetContexts) and groups (PresetGroups).
192 
193 Tasks often require parameters and to provide completion for it, the
194 completion system will call the function with task name ended by "__complete".
195 If the function doesn't exists nothing is returned. Diantre "complete" group
196 gives methods similar to tasks to manipulate complete functions.
197 
198 Diantre completion functions receive 3 parameters: words, cursor position, and
199 previous result. It's quite similar to vim default completion system, except,
200 words is a list, cursor position is the index in this list where the cursor is
201 located and result is an array with already found completions. The function
202 should return an array with all possible completions, this array is
203 automatically formatted to suit vim completion system, which will get rid of
204 partial words. You have an example of such function in:
205     test/taskcontext/taskgroup.vim
206 
207      new:                                                       complete-new
208             Create new completion function for task named <name>:
209                 :Diantre new diantre complete <name> <context> <group>
210            NOTE: previous result is passed as optionnal argument, and for
211            compatibility reasons, it's set with variables arguments. New
212            complete functions, will have a line to get this argument.
213 
214     edit:                                                      complete-edit
215             Open autoload/<context>/<group>.vim and position the cursor inside
216             task <name> completion function if it exists:
217                 :Diantre edit diantre complete <name> <context> <group>
218 
219             NOTE: Like for tasks markers 's and 'e are added to the start and
220             end of function if it's found and true is returned if function
221             exists, false otherwise
222 
223    close:                                                     complete-close
224             Save and close the group buffer similarly to tasks:
225                 :Diantre close diantre complete <context> <group>
226 
227   remove:                                                    complete-remove
228             Delete completion function for task <name>. It returns true if
229             function was found, false otherwise. You can get the deleted code
230             from the unnamed register "":
231                 :Diantre remove diantre complete <name> <context> <group>
232 
233     yank:                                                      complete-yank
234             Fill unnamed register "", with the code of the completion function
235             of the given task. Similar to task yank:
236                 :Diantre yank diantre complete <name> <context> <group>
237 
238   rename:                                                    complete-rename
239             Change task complete function name. Similar to task rename:
240             :Diantre rename diantre complete <name> <context> <group> <newname>
241 
242    chgrp:                                                     complete-chgrp
243             Change task complete function group. Similar to task chgrp:
244             :Diantre chgrp diantre complete <name> <context> <group> <newgroup>
245 
246    chdir:                                                     complete-chdir
247             Change task complete function context. Similar to task chdir:
248             :Diantre chdir diantre complete <name> <context> <group> <newcontext>
249 
250     move:                                                      complete-move
251             Move the task complete function to a new context, new group and/or
252             new task name. Similar to task move:
253             :Diantre move diantre complete <name> <context> <group> <newname>
254             <newcontext> <newgroup>
255 
256     copy:                                                      complete-copy
257             Copy the task complete function to a new context, new group and/or
258             new task name. Similar to task copy:
259             :Diantre copy diantre complete <name> <context> <group> <newname>
260             <newcontext> <newgroup>
261 -------------------------------------------------------------------------------
262 2.3 Groups                                                      DiantreGroups
263 
264      new:                                                           group-new
265             Make the file DiantreHome/<context>/<group>.vim to create a new
266             group and open it:
267                 :Diantre new diantre group <context> <group>
268 
269   remove:                                                        group-remove
270             Delete permanently the file DiantreHome/<context>/<group>.vim if
271             context is empty delete the directory too:
272                 :Diantre remove diantre group <context> <group>
273 
274   rename:                                                        group-rename
275             Rename the group <group> to <newgroup> and the tasks it contains.
276             It uses group-move and support an optional parameter <complete>
277             to disable the renaming of completion tasks. This paramater should
278             be strictly equal to v:false otherwise it's considered to be true:
279                 :Diantre rename diantre group <context> <group> <newgroup>
280                 [<complete>]
281 
282    chdir:                                                         group-chdir
283             Move the group from <context> directory to <newcontext>. Like
284             group-rename it uses group-move and support an optional
285             parameter <complete> to disable the move of completion tasks. This
286             paramater should strictly be equal to v:false otherwise it's
287             considered to be true:
288                 :Diantre chdir diantre group <context> <group> <newcontext>
289                 [<complete>]
290 
291     move:                                                          group-move
292             Move all tasks from group <group> to <newgroup> from context
293             <context> to <newcontext>. If the optional parameter <complete> is
294             given and strictly equals to v:false then tasks complete
295             functions are not moved, they'll be deleted with group file:
296                 :Diantre move diantre group <context> <group> <newcontext>
297                 <newgroup> [<complete>]
298 
299     copy:                                                          group-copy
300             Like group-move but don't delete the group file after moving
301             tasks from group <group> to <newgroup> from context <context> to
302             <newcontext>. If the optional parameter <complete> is given and
303             strictly equals to v:false then tasks complete functions are not
304             moved:
305                 :Diantre copy diantre group <context> <group> <newcontext>
306                 <newgroup> [<complete>]
307 
308    merge:                                                         group-chdir
309             It renames a list of groups given as variables arguments, each
310             task completion function is renamed too.
311                 :Diantre merge diantre group <context> <group> <var-args>
312 
313 Note: group-rename, group-chdir, group-move, group-copy, group-merge
314 will rename tasks to versionned tasks if they already exists in the
315 destination group. see TasksVersions for mor information.
316 
317 -------------------------------------------------------------------------------
318 Tasks related to PresetGroups :
319 
320      set:                                                            group-set
321             Set global variable g:diantre_groups which is used to preset
322             groups when looking for a task.
323                 :Diantre set diantre group <var-args>
324            Example:
325                 :Diantre set diantre group task group context
326                 :Diantre merge diantre group0 group1 group2
327                 :Diantre new diantre context1 group1 task1
328           Because "task" group was set first, the last command will call:
329                 :Diantre new diantre task context1 group1 task1
330           The second command will find "merge" task inside diantre#group only
331           and merge group1 and group2 with group0.
332 
333           Note: except if you know what you're doing it's not recommanded to set
334           global groups for diantre itself. The example above, alter the
335           behaviour of task resolver and will corrupt some diantre commands,
336           included those to restore group variables. In case it happens you
337           can restart vim or use internal function defined in
338           plugin/diantre.vim:
339                 :call Diantre_set_groups()
340                 :echo Diantre_groups() 
341 
342     bset:                                                           group-bset
343             Set buffer variable b:diantre_groups which is used to preset
344             groups when looking for a task only for the current buffer.
345                 :Diantre bset diantre group <var-args>
346 
347   insert:                                                         group-insert
348  binsert:                                                        group-binsert
349             Prepend list of global (insert) or buffer (binsert) group preset
350             variables.
351                 :Diantre insert diantre group <var-args>
352                 :Diantre binsert diantre group <var-args>
353 
354   append:                                                         group-append
355  bappend:                                                        group-bappend
356             Append at the end of the list global (append) or buffer (bappend)
357             group preset variables.
358                 :Diantre append diantre group <var-args>
359                 :Diantre bappend diantre group <var-args>
360 
361    unset:                                                          group-unset
362   bunset:                                                         group-bunset
363             If no parameter is given it will empty global (unset) or buffer
364             (bunset) group preset variables. With <var-args> it removes only
365             the given groups:
366                 :Diantre unset diantre group [<var-args>]
367                 :Diantre bunset diantre group [<var-args>]
368 
369 -------------------------------------------------------------------------------
370 2.4 Contexts                                                  DiantreContexts
371 
372 new:                                                               context-new
373             Create a new directory <context> in DiantreHome/autoload with
374             the given name. The directory is made recursively.
375                 :Diantre new diantre context <context>
376 
377 remove:                                                         context-remove
378 remove_empty:                                             context-remove_empty
379             Delete the directory DiantreHome/autoload/<context> and all its
380             content. Use context-remove_empty to remove this directory only
381             if it contains no vim files (other type of file are not detected)
382                 :Diantre remove diantre context <context>
383                 :Diantre remove_empty diantre context <context>
384 
385 move:                                                             context-move
386             Call group-chdir for each group inside <context> to move them to
387             <newcontext>:
388                 :Diantre move diantre context <context> <newcontext>
389 
390 copy:                                                             context-copy
391             Call group-copy for each group inside <context> to copy them to
392             <newcontext>:
393                 :Diantre copy diantre context <context> <newcontext>
394 
395 -------------------------------------------------------------------------------
396 Tasks related to PresetContexts :
397 
398      set:                                                          context-set
399             Set global variable g:diantre_contexts which is used to preset
400             contexts when looking for a task.
401                 :Diantre set diantre context <var-args>
402 
403             Note: By default 'diantre' is set as a context, which remove the
404             necessity to type it for each command shown in this documentation.
405             For example previous command can be done with:
406                 :Diantre set context <var-args>
407 
408     bset:                                                         context-bset
409             Set buffer variable b:diantre_contexts which is used to preset
410             contexts when looking for a task only for the current buffer.
411                 :Diantre bset diantre context <var-args>
412 
413   insert:                                                       context-insert
414  binsert:                                                      context-binsert
415             Prepend list of global (insert) or buffer (binsert) context preset
416             variables.
417                 :Diantre insert diantre context <var-args>
418                 :Diantre binsert diantre context <var-args>
419 
420   append:                                                       context-append
421  bappend:                                                      context-bappend
422             Append at the end of the list global (append) or buffer (bappend)
423             context preset variables.
424                 :Diantre append diantre context <var-args>
425                 :Diantre bappend diantre context <var-args>
426 
427    unset:                                                        context-unset
428   bunset:                                                       context-bunset
429             If no parameter is given it will empty global (unset) or buffer
430             (bunset) context preset variables. With <var-args> it removes only
431             the given contexts:
432                 :Diantre unset diantre context [<var-args>]
433                 :Diantre bunset diantre context [<var-args>]
434 
435 ===============================================================================
436 3. Configuration                                         DiantreConfiguration
437 -------------------------------------------------------------------------------
438 3.1 Home Directory                                                DiantreHome
439 
440 Diantre uses the function DiantreHome() to get the directory where tasks are
441 stored. This function returns by default the directory of $VIMRC appended by
442 ".vim/autoload" on unix systems and "vimfiles\autoload" on windows systems.
443 If the global variable g:diantre_home is set, it's returned instead.
444 This solution is probably going to change in the future, where tasks should be
445 necessary to add your settings to runtime paths and also to manage
446 configuration, installation, documentation and autoload directory differently.
447 
448 -------------------------------------------------------------------------------
449 3.2 Presets contexts and groups                                        Presets
450 
451 Diantre able to predefine contexts and groups to shorter commands with
452 presets. See related tasks at PresetContexts and PresetGroups.
453 This is the case for diantre itself which is listed in default contexts
454 presets, and permit to do:
455     :Diantre new task taskname taskcontext taskgroup
456 instead of:
457     :Diantre new diantre task taskname taskcontext taskgroup
458 
459 This feature was made to be used with autocommand.
460 It's recommanded to use autocommand groups (augroup) and buffer version of
461 diantre presets.
462 
463 A typic example of setting context is the following:
464     augroup python
465         autocmd!
466         autocmd FileType python Diantre binsert context python
467     augroup END
468 
469 You can check defined contexts with internal method Diantre_all_contexts():
470     :echo Diantre_all_contexts()
471 It will show ['python', 'diantre'] if the active buffer is a python file and
472 only ['diantre'] if it's another type of file. The '_all_' method indicate
473 buffer and global presets are merged and this is the function used internally
474 to resolve task names.
475 
476 You can do the same for groups here a complete example, if you have a context
477 "vim", a group "test" with for example task "run" then by defining this:
478     augroup vimspec
479         autocmd!
480         autocmd FileType vimspec Diantre binsert context vim
481         autocmd FileType vimspec Diantre binsert group test
482     augroup END
483 Instead of typing:
484     :Diantre run vim test
485 You'll be able to do the same with:
486     :Diantre run
487 
488 You can check defined groups with internal method Diantre_all_groups():
489     :echo Diantre_all_groups()
490 
491 It will show ['test'] if the active buffer is a vimspec file and an empty list
492 if it's another type of file like vimscript. The '_all_' method has the same
493 purpose than for contexts.
494 
495 -------------------------------------------------------------------------------
496 3.4 Task versions                                               TasksVersions
497 
498 When you're moving, copying... tasks or groups, sometimes the destination task
499 function already exists, or you may want to have 2 differents behaviours for
500 the same task name, this is why task versions exists. It prevents name
501 collision during some operations by adding double underscore followed by the
502 last version of the task. An example is more explicit.
503 
504 Imagine you have a context "ruby" and a group "test" which contains a task
505 "run". Ruby has a lot of testing frameworks, you can eventually add parameters
506 to specify which one you want to pick, but it means you'll have to test the
507 parameter inside your task function, and modify the task everytime you want to
508 add a new framework.
509 So a better solution is to have versioned tasks, let's say your favorite test
510 framework is rspec, but occasionely you use test-unit. You write a function
511 ruby#test#run() which launch rspec runner, and a versionned version
512 ruby#test#run__1() which is going to launch test-unit.
513 This command will call rspec runner:
514     :Diantre run ruby test
515 This one will call test-unit runner:
516     :Diantre run__1 ruby test
517 
518 The task name 'run__1' is not really explicit and having a separate group for
519 rspec and test-unit is definitly a better option, but this option doesn't
520 exclude having a generic test group with versionned tasks that call the run
521 task in specifics groups, because task versions provide an abstraction
522 comparable to polymorphism. You can choose which version to launch by defining
523 a global variable with the name of the task, followed by "#version" and so if
524 you set g:ruby#test#run#version to 1, unit-test runner will be used by
525 default:
526     :let g:ruby#test#run#version=1
527     :Diantre run ruby test
528 Is equivalent to:
529     :Diantre run__1 ruby test
530 
531 This feature is particularly usefull when you combine tasks together, for
532 example if you have a deploy process which consists in testing first then
533 send your code on a server, the task "deploy" in "production" group can call
534 the generic task "run" without worrying about the test framework you're using.
535 
536     function! ruby#production#deploy(server)
537         Diantre run ruby test
538         Diantre push remote rsync a:server
539     endfunction
540 
541 If you want to call the function directly to get the result for example, you
542 can use DiantreFunctionName:
543 
544     function! ruby#production#deploy(server)
545         let l:testrunner = DiantreFunctionName('ruby', 'test', 'run')
546         if call(l:testrunner, [])
547             Diantre push remote rsync a:server
548         endif
549     endfunction
550 
551 ===============================================================================
552 4. License                                                     DiantreLicense
553 
554 MIT License
555 
556 Copyright (c) 2020 Grégory Salvan apieum[at]gmail.com
557 
558 Permission is hereby granted, free of charge, to any person obtaining a copy
559 of this software and associated documentation files (the "Software"), to deal
560 in the Software without restriction, including without limitation the rights
561 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
562 copies of the Software, and to permit persons to whom the Software is
563 furnished to do so, subject to the following conditions:
564 
565 The above copyright notice and this permission notice (including the next
566 paragraph) shall be included in all copies or substantial portions of the
567 Software.
568 
569 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
570 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
571 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
572 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
573 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
574 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
575 SOFTWARE.