source: trunk/UTerminal.pas

Last change on this file was 1, checked in by chronos, 4 years ago
  • Added: Initial version.
File size: 5.7 KB
Line 
1unit UTerminal;
2
3{$mode delphi}
4
5interface
6
7uses
8 Classes, SysUtils, UDevice;
9
10type
11
12 { TTerminal }
13
14 TTerminal = class
15 private
16 function GetCommandLine: string;
17 procedure SetCommandLine(AValue: string);
18 public
19 Output: string;
20 Device: TDevice;
21 User: string;
22 Context: TContext;
23 CommandLines: TStringList;
24 CommandLineIndex: Integer;
25 CommandHistory: TStringList;
26 function ExecuteCommand(CommandText: string): string;
27 function ContextHelp: string;
28 function Prompt: string;
29 procedure Write(Text: string);
30 procedure WriteLn(Text: string);
31 procedure KeyPress(Key: Char);
32 procedure KeyPressCode(Key: Word);
33 procedure Run;
34 constructor Create;
35 destructor Destroy; override;
36 property CommandLine: string read GetCommandLine write SetCommandLine;
37 end;
38
39implementation
40
41function TTerminal.GetCommandLine: string;
42begin
43 Result := CommandLines[CommandLineIndex];
44end;
45
46procedure TTerminal.SetCommandLine(AValue: string);
47begin
48 CommandLines[CommandLineIndex] := AValue;
49end;
50
51function TTerminal.ExecuteCommand(CommandText: string): string;
52var
53 Index: Integer;
54 CommandName: string;
55 Commands: TCommands;
56 Command: TCommand;
57 CommandOutput: string;
58begin
59 CommandLine := Trim(CommandText);
60 if (Length(CommandLine) > 0) and (CommandLine[1] = '/') then begin
61 while Assigned(Context.Parent) do
62 Context := Context.Parent;
63 CommandLine := Trim(Copy(CommandLine, 2, MaxInt));
64 end;
65
66 while True do begin
67 Index := Pos(' ', CommandLine);
68 if Index > 0 then begin
69 CommandName := Copy(CommandLine, 1, Index - 1);
70 CommandLine := Trim(Copy(CommandLine, Length(CommandName) + 1, MaxInt));
71 end else begin
72 CommandName := CommandLine;
73 CommandLine := '';
74 end;
75 if CommandName <> '' then begin
76 Commands := Context.GetCommands;
77 try
78 Command := Commands.SearchByName(CommandName);
79 if Assigned(Command) then begin
80 CommandOutput := Command.Execute(Self, Command);
81 if CommandOutput <> '' then Write(LineEnding + CommandOutput);
82 if Command.IsContext then
83 Continue
84 else Break;
85 end else begin
86 Write(LineEnding + 'bad command name ' + CommandName);
87 Break;
88 end;
89 finally
90 FreeAndNil(Commands);
91 end;
92 end else Break;
93 end;
94end;
95
96function TTerminal.ContextHelp: string;
97var
98 I: Integer;
99 ParentName: string;
100 Commands: TCommands;
101begin
102 Result := LineEnding + LineEnding;
103 Commands := Context.GetCommands;
104 Commands.SortAll;
105 for I := 0 to Commands.Count - 1 do
106 Result := Result + Commands[I].Name + ' -- ' + Commands[I].Description + LineEnding;
107 Commands.Free;
108 Result := Result + LineEnding;
109end;
110
111function TTerminal.Prompt: string;
112begin
113 Result := '[' + User + '@' + Device.Identity + '] ' + Context.GetPath + '> ';
114end;
115
116procedure TTerminal.Write(Text: string);
117begin
118 Output := Output + Text;
119end;
120
121procedure TTerminal.WriteLn(Text: string);
122begin
123 Write(Text + LineEnding);
124end;
125
126procedure TTerminal.KeyPress(Key: Char);
127begin
128 if Key = '?' then begin
129 Write(ContextHelp + Prompt);
130 end else
131 if Key = #8 then begin
132 if Length(CommandLine) > 0 then begin
133 CommandLine := Copy(CommandLine, 1, Length(CommandLine) - 1);
134 Delete(Output, Length(Output), 1);
135 end;
136 end else
137 if Key = #13 then begin
138 CommandHistory.Add(CommandLine);
139 ExecuteCommand(CommandLine);
140
141 // Prepare new command line
142 Write(LineEnding + Prompt);
143 CommandLines.Assign(CommandHistory);
144 CommandLines.Add('');
145 CommandLineIndex := CommandLines.Count - 1;
146 end else begin
147 CommandLine := CommandLine + Key;
148 Write(Key);
149 end;
150end;
151
152procedure TTerminal.KeyPressCode(Key: Word);
153var
154 Commands: TCommands;
155begin
156 if Key = 9 then begin
157 Commands := Context.GetCommandsStartingWith(CommandLine);
158 if Commands.Count = 1 then begin
159 Write(Copy(Commands[0].Name, Length(CommandLine) + 1, Length(Commands[0].Name)));
160 CommandLine := CommandLine + Copy(Commands[0].Name, Length(CommandLine) + 1, Length(Commands[0].Name));
161 end;
162 Commands.Free;
163 end else
164 if Key = 38 then begin
165 if CommandLineIndex > 0 then begin
166 Delete(Output, Length(Output) - Length(CommandLine) + 1, Length(CommandLine));
167 Dec(CommandLineIndex);
168 Write(GetCommandLine);
169 end;
170 end else
171 if Key = 40 then begin
172 if CommandLineIndex < CommandLines.Count - 1 then begin
173 Delete(Output, Length(Output) - Length(CommandLine) + 1, Length(CommandLine));
174 Inc(CommandLineIndex);
175 Write(GetCommandLine);
176 end;
177 end;
178end;
179
180procedure TTerminal.Run;
181begin
182 CommandLines.Add('');
183 CommandLineIndex := 0;
184 User := 'admin';
185 Context := Device.RootContext;
186 WriteLn(Device.Routerboard.Logo.Text);
187 WriteLn('');
188 WriteLn(' ' + Device.Routerboard.Vendor + ' ' + Device.Routerboard.OS + ' ' +
189 Device.Routerboard.Version + ' (c) ' + Device.Routerboard.Copyright + ' ' +
190 Device.Routerboard.Website);
191 WriteLn('');
192 WriteLn('[?] Gives the list of available commands');
193 WriteLn('command [?] Gives help on the command and list of arguments');
194 WriteLn('');
195 WriteLn('[Tab] Completes the command/word. If the input is ambiguous,');
196 WriteLn(' a second [Tab] gives possible options');
197 WriteLn('');
198 WriteLn('/ Move up to base level');
199 WriteLn('.. Move up one level');
200 WriteLn('/command Use command at the base level');
201 Write(Prompt);
202end;
203
204constructor TTerminal.Create;
205begin
206 CommandHistory := TStringList.Create;
207 CommandLines := TStringList.Create;
208end;
209
210destructor TTerminal.Destroy;
211begin
212 FreeAndNil(CommandLines);
213 FreeAndNil(CommandHistory);
214 inherited Destroy;
215end;
216
217end.
218
Note: See TracBrowser for help on using the repository browser.