-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCommandLine.cs
180 lines (152 loc) · 5.6 KB
/
CommandLine.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text.RegularExpressions;
namespace TermSim
{
public class CommandFlags
{
public string Flag { get; set; }
public string Argument { get; set; }
}
class CommandLine
{
public List<string> Arguments { get; set; } //command-line argument list
public List<CommandFlags> Flags { get; set; } //command-line flag list
//parser state variables
readonly string _cmd;
int _pos;
//main constructor method
public CommandLine(string commandLine)
{
//initialize parser variables
Arguments = new List<string>();
Flags = new List<CommandFlags>();
_cmd = commandLine;
_pos = 0;
//loop until all characters processed
while (!EOL)
{
while (Char.IsWhiteSpace(CurrentChar())) //skip whitespace
AdvancePos();
//check if 'flag'
if (CurrentChar() == '/' || CurrentChar() == '-')
{
AdvancePos();
var start = _pos;
while (Char.IsLetterOrDigit(CurrentChar()))
AdvancePos();
if (_pos <= start) continue;
var flag = new CommandFlags {Flag = _cmd.Substring(start, _pos - start)}; //construct parsed flag
if (CurrentChar() == ':') //check for flag argument delimiter
{
AdvancePos();
flag.Argument = ParseArgument(); //parse flag value (argument)
}
Flags.Add(flag);
}
else
{
var arg = ParseArgument(); //parse command-line argument
if (arg.Length > 0)
Arguments.Add(arg);
}
}
}
///<summary> Returns true if the current position is end of string. </summary>
protected bool EOL
{
get { return (_pos >= _cmd.Length); }
}
///<summary> Returns the character at the current position. </summary>
protected char CurrentChar()
{
return (_pos < _cmd.Length) ? _cmd[_pos] : (char)0;
}
///<summary> Advances current position to next character. </summary>
protected char AdvancePos()
{
var c = CurrentChar();
_pos = Math.Min(_pos + 1, _cmd.Length);
return c;
}
///<summary> Parses a command-line argument. Supports arguments enclosed in double or single quotation marks.
/// If no argument can be parsed, an empty string is returned. </summary>
protected string ParseArgument()
{
string result;
if (CurrentChar() == '"' || CurrentChar() == '\'')
{
//parse quoted argument
var quote = AdvancePos();
var start = _pos;
//ReSharper disable once LoopVariableIsNeverChangedInsideLoop (re-sharper doesn't realize MoveAhead() increments loop control variable)
while (!EOL && CurrentChar() != quote)
AdvancePos();
result = _cmd.Substring(start, _pos - start);
AdvancePos(); //skip closing quote
}
else
{
var start = _pos; //parse argument
while (!EOL && !Char.IsWhiteSpace(CurrentChar()) && CurrentChar() != '/' && CurrentChar() != '-')
AdvancePos();
result = _cmd.Substring(start, _pos - start);
}
//return parsed argument
return result;
}
///<summary> Process command line string and route arguments to the proper method. </summary>
internal static void ProcessArguments(CommandLine cmd)
{
var args = cmd.Arguments.ToArray(); //convert argument list to array.
//format checks
if (!args.Any()) //no commands present
return;
if (args.Count() > 1) //more than one command used. TODO: change the way commands are parsed to allow for non-flag arguments
{
FrmMain.Instance.TerminalWriteLine("Error", "Invalid Syntax: Multiple Commands present!", true, Color.Red);
return;
}
//determine which method to use with the passed arguments
switch (args[0])
{
case "clear":
Components.ClearConsole(); //clear console window (0 arguments)
break;
case "exit":
FrmMain.Instance.Dispose(); //close program (0 arguments)
break;
case "savelog":
Components.SaveConsoleLog(); //save the contents of the console to the logs folder (0 arguments)
break;
//file system navigation
case "pwd":
Components.PresentWorkingDirectory(); //print present working directory (0 arguments)
break;
case "cd":
Components.ChangeDirectory(cmd.Flags); //change present working directory (2 arguments; -i:[x], -help)
break;
case "ls":
Components.ListFiles(cmd.Flags); //list files in present working directory (1 argument; -help)
break;
//misc
case "ontop":
Components.StayOnTop(); //toggle stay on top (0 arguments)
break;
default:
FrmMain.Instance.TerminalWriteLine("Error", "Undefined Command!", true, Color.Red);
break;
}
}
///<summary> Split command strings (at 'pipe' characters) into a string array and process each string sequentially. </summary>
public static void InputCommand(string cmdString)
{
var cmdArray = Regex.Split(cmdString, @"\s\|\s"); //split commands at pipes
//process each command sequentially
foreach (var cmd in cmdArray)
ProcessArguments(new CommandLine(cmd));
}
}
}