1 /* 2 ------------------------------------------------------------------- 3 4 Copyright (C) 2014, Edwin van Leeuwen 5 6 This file is part of todod todo list manager. 7 8 Todod is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 Todod is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with Todod. If not, see <http://www.gnu.org/licenses/>. 20 21 ------------------------------------------------------------------- 22 */ 23 24 module todod.commandline; 25 26 import std.algorithm; 27 import std.string; 28 29 import colorize; 30 31 /// Manage command line arguments 32 struct Commands(COMMAND) { 33 alias Completion = string[] delegate( string, string ); 34 35 /// Create commands using the introduction when printing help 36 this( string introduction ) { 37 myintroduction = introduction; 38 } 39 40 /// 41 unittest { 42 auto cmds = Commands!( string delegate( string ) )( "Usage: myprogram [OPTION]" ); 43 44 cmds.add( "world", delegate( string parameter ) { return parameter ~ " world"; }, 45 "Append world to the given parameter" ); 46 cmds.add( "help", delegate( string parameter ) { cmds.toString; return parameter; }, 47 "Print this help message." ); 48 assert( cmds["world"]( "Hello" ) == "Hello world" ); 49 assert( equal( ["world", "help"], cmds.commands() ) ); 50 } 51 52 /// Add a new command given de name, the action to perform and a description 53 void add( string command, COMMAND action, string description ) { 54 addition_order ~= command; 55 mycommands[command] = action; 56 myhelp[command] = description; 57 } 58 59 /// Create help message 60 string toString() { 61 string description = myintroduction ~ "\n"; 62 foreach( comm; addition_order ) { 63 description ~= 64 color( " " ~ comm.leftJustify( 15 ) ~ " ", fg.red ) 65 ~ myhelp[comm] ~ "\n\n"; 66 } 67 return description; 68 } 69 70 /// Return COMMAND associated with command. If command does not exist then call return COMMAND associated with help. If neither exist fail. 71 COMMAND opIndex( const string command ) { 72 if ( exists( command )) 73 return mycommands[command]; 74 else if ( exists( "help" ) ) 75 return mycommands[ "help" ]; 76 import std.stdio; 77 writeln( toString ); 78 assert( 0, "Command does not exist: " ~ command ); 79 } 80 81 /// Return an array with all possible commands 82 string[] commands() { 83 return mycommands.keys; 84 } 85 86 /// Is this command provided? 87 bool exists( const string cmd ) { 88 if (cmd in mycommands) 89 return true; 90 else 91 return false; 92 } 93 94 /// Add completion option for this specific command 95 void addCompletion( string cmd, Completion completion ) { 96 completions[cmd] = completion; 97 } 98 99 /// Set default completion function 100 void defaultCompletion( Completion completion ) { 101 defaulCompletionInitialized = true; 102 myDefaultCompletion = completion; 103 } 104 105 /// Return completion options 106 string[] completionOptions( string cmd, string parameter ) { 107 if ( cmd in completions ) 108 return completions[cmd]( cmd, parameter ); 109 else if ( defaulCompletionInitialized ) 110 return myDefaultCompletion( cmd, parameter ); 111 string[] emptyResult; 112 return emptyResult; 113 } 114 115 private: 116 string[] addition_order; 117 118 string myintroduction; 119 COMMAND[string] mycommands; 120 string[string] myhelp; 121 Completion[string] completions; 122 123 bool defaulCompletionInitialized = false; 124 Completion myDefaultCompletion; 125 } 126 127 unittest { 128 auto cmd = Commands!int( "Intro" ); 129 cmd.add( "cmd1", 1, "help1" ); 130 cmd.add( "cmd2", 2, "help2" ); 131 assert( cmd["cmd1"] == 1 ); 132 assert( cmd["cmd2"] == 2 ); 133 } 134 135 unittest { 136 auto cmd = Commands!int( "" ); 137 assert( cmd.completionOptions( "bla", "" ).length == 0 ); 138 }