10 std::map
<std::string
, command
*>* commands
;
11 std::set
<std::string
> command_stack
;
12 std::map
<std::string
, std::list
<std::string
>> aliases
;
14 function_ptr_command
run_script("run-script", "run file as a script",
15 "Syntax: run-script <file>\nRuns file <file> just as it would have been entered in the command line\n",
16 [](const std::string
& args
) throw(std::bad_alloc
, std::runtime_error
) {
18 throw std::runtime_error("Filename needed");
19 std::istream
* o
= NULL
;
21 o
= &open_file_relative(args
, "");
22 window::out() << "Running '" << args
<< "'" << std::endl
;
24 while(std::getline(*o
, line
))
25 command::invokeC(line
);
27 } catch(std::exception
& e
) {
34 function_ptr_command
show_aliases("show-aliases", "show aliases",
35 "Syntax: show-aliases\nShow expansions of all aliases\n",
36 [](const std::string
& args
) throw(std::bad_alloc
, std::runtime_error
) {
38 throw std::runtime_error("This command does not take parameters");
39 for(auto i
= aliases
.begin(); i
!= aliases
.end(); i
++)
40 for(auto j
= i
->second
.begin(); j
!= i
->second
.end(); j
++)
41 window::out() << "alias " << i
->first
<< " " << *j
<< std::endl
;
44 function_ptr_command
unalias_command("unalias-command", "unalias a command",
45 "Syntax: unalias-command <aliasname>\nClear expansion of alias <aliasname>\n",
46 [](const std::string
& args
) throw(std::bad_alloc
, std::runtime_error
) {
47 tokensplitter
t(args
);
48 std::string aliasname
= t
;
50 throw std::runtime_error("This command only takes one argument");
51 if(aliasname
.length() == 0 || aliasname
[0] == '?' || aliasname
[0] == '*')
52 throw std::runtime_error("Illegal alias name");
53 aliases
[aliasname
].clear();
54 window::out() << "Command '" << aliasname
<< "' unaliased" << std::endl
;
57 function_ptr_command
alias_command("alias-command", "alias a command",
58 "Syntax: alias-command <aliasname> <command>\nAppend <command> to expansion of alias <aliasname>\n"
59 "Valid alias names can't be empty nor start with '*' or '?'\n",
60 [](const std::string
& args
) throw(std::bad_alloc
, std::runtime_error
) {
61 tokensplitter
t(args
);
62 std::string aliasname
= t
;
63 std::string command
= t
.tail();
65 throw std::runtime_error("Alias name and command needed");
66 if(aliasname
.length() == 0 || aliasname
[0] == '?' || aliasname
[0] == '*')
67 throw std::runtime_error("Illegal alias name");
68 aliases
[aliasname
].push_back(command
);
69 window::out() << "Command '" << aliasname
<< "' aliased to '" << command
<< "'" << std::endl
;
73 command::command(const std::string
& cmd
) throw(std::bad_alloc
)
76 commands
= new std::map
<std::string
, command
*>();
77 if(commands
->count(cmd
))
78 std::cerr
<< "WARNING: Command collision for " << cmd
<< "!" << std::endl
;
79 (*commands
)[commandname
= cmd
] = this;
82 command::~command() throw()
86 commands
->erase(commandname
);
89 void command::invokeC(const std::string
& cmd
) throw()
92 if(command_stack
.count(cmd
)) {
93 window::out() << "Can not invoke recursively: " << cmd
<< std::endl
;
96 command_stack
.insert(cmd
);
97 std::string cmd2
= cmd
;
99 //The special ? command.
101 for(auto i
= commands
->begin(); i
!= commands
->end(); ++i
)
102 window::out() << i
->first
<< ": " << i
->second
->get_short_help() << std::endl
;
104 command_stack
.erase(cmd
);
107 if(cmd2
.length() > 1 && cmd2
[0] == '?') {
109 size_t split
= cmd2
.find_first_of(" \t");
111 if(split
>= cmd2
.length())
112 rcmd
= cmd2
.substr(1);
114 rcmd
= cmd2
.substr(1, split
- 1);
115 if(rcmd
.length() > 0 && rcmd
[0] != '*') {
116 //This may be an alias.
117 std::string aname
= cmd2
.substr(1);
118 if(aliases
.count(aname
)) {
120 window::out() << aname
<< " is an alias for: " << std::endl
;
122 for(auto i
= aliases
[aname
].begin(); i
!= aliases
[aname
].end(); ++i
, ++j
)
123 window::out() << "#" + (j
+ 1) << ": " << *i
<< std::endl
;
124 command_stack
.erase(cmd
);
128 if(rcmd
.length() > 0 && rcmd
[0] == '*')
129 rcmd
= rcmd
.substr(1);
130 if(!commands
|| !commands
->count(rcmd
)) {
132 window::out() << "Unknown command '" << rcmd
<< "'" << std::endl
;
133 command_stack
.erase(cmd
);
136 window::out() << (*commands
)[rcmd
]->get_long_help() << std::endl
;
137 command_stack
.erase(cmd
);
140 bool may_be_alias_expanded
= true;
141 if(cmd2
.length() > 0 && cmd2
[0] == '*') {
142 may_be_alias_expanded
= false;
143 cmd2
= cmd2
.substr(1);
145 if(may_be_alias_expanded
&& aliases
.count(cmd2
)) {
146 for(auto i
= aliases
[cmd2
].begin(); i
!= aliases
[cmd2
].end(); ++i
)
148 command_stack
.erase(cmd
);
152 size_t split
= cmd2
.find_first_of(" \t");
154 if(split
>= cmd2
.length())
157 rcmd
= cmd2
.substr(0, split
);
158 split
= cmd2
.find_first_not_of(" \t", split
);
160 if(split
< cmd2
.length())
161 args
= cmd2
.substr(split
);
162 command
* cmdh
= NULL
;
163 if(commands
&& commands
->count(rcmd
))
164 cmdh
= (*commands
)[rcmd
];
166 window::out() << "Unknown command '" << rcmd
<< "'" << std::endl
;
167 command_stack
.erase(cmd
);
171 command_stack
.erase(cmd
);
173 } catch(std::bad_alloc
& e
) {
175 } catch(std::exception
& e
) {
176 window::out() << "Error: " << e
.what() << std::endl
;
177 command_stack
.erase(cmd
);
180 } catch(std::bad_alloc
& e
) {
185 std::string
command::get_short_help() throw(std::bad_alloc
)
187 return "No description available";
190 std::string
command::get_long_help() throw(std::bad_alloc
)
192 return "No help available on command " + commandname
;
195 tokensplitter::tokensplitter(const std::string
& _line
) throw(std::bad_alloc
)
201 tokensplitter::operator bool() throw()
203 return (position
< line
.length());
206 tokensplitter::operator std::string() throw(std::bad_alloc
)
208 size_t nextp
, oldp
= position
;
209 nextp
= line
.find_first_of(" \t", position
);
210 if(nextp
> line
.length()) {
211 position
= line
.length();
212 return line
.substr(oldp
);
215 while(position
< line
.length() && (line
[position
] == ' ' || line
[position
] == '\t'))
217 return line
.substr(oldp
, nextp
- oldp
);
221 std::string
tokensplitter::tail() throw(std::bad_alloc
)
223 return line
.substr(position
);
226 function_ptr_command::function_ptr_command(const std::string
& name
, const std::string
& _description
,
227 const std::string
& _help
, void (*_fn
)(const std::string
& arguments
)) throw(std::bad_alloc
)
230 description
= _description
;
235 void function_ptr_command::invoke(const std::string
& args
) throw(std::bad_alloc
, std::runtime_error
)
240 std::string
function_ptr_command::get_short_help() throw(std::bad_alloc
)
245 std::string
function_ptr_command::get_long_help() throw(std::bad_alloc
)
250 function_ptr_command::~function_ptr_command() throw()