PageRenderTime 32ms CodeModel.GetById 15ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/console/prompt.d

http://github.com/wilkie/djehuty
D | 298 lines | 191 code | 72 blank | 35 comment | 60 complexity | 187e8f6fb99c08bbf04a90531dc89caf MD5 | raw file
  1module console.prompt;
  2
  3import djehuty;
  4
  5import io.console;
  6
  7import core.definitions;
  8
  9import data.queue;
 10
 11// Section: Console
 12
 13// Description: This class provides a line input field for a console application.  This class can buffer the previous lines much like that of a modern shell.
 14class Prompt {
 15	// TODO: Allow ANSI emulated prompt strings
 16	this() {
 17		_prompt = "";
 18	}
 19
 20	// Description: This will set the prompt string that will precede the input.
 21	// prompt: A string representing the prompt.
 22	void prompt(string prompt) {
 23		_prompt = prompt.dup;
 24	}
 25
 26	// Description: This function will return the current prompt.
 27	// Returns: The current prompt.
 28	string prompt() {
 29		return _prompt.dup;
 30	}
 31
 32	void promptColor(Color fgClr) {
 33		_promptClr = fgClr;
 34	}
 35
 36	void forecolor(Color fgClr) {
 37		_clr = fgClr;
 38	}
 39
 40	// Description: This function will set the amount of lines the line buffer stores.  The line buffer will scroll through the most recent lines inputted by the user.  This function will also turn off the line buffer if the size is 0.
 41	// bufferSize: The number of lines to store.  Setting this to zero will turn off the buffer.  There is a maximum of 5000.
 42	void bufferSize(uint bufferSize) {
 43		if (bufferSize > 5000) {
 44			bufferSize = 5000;
 45		}
 46
 47		if (bufferSize != 0) {
 48			_lineBuffer = new Queue!(string)();
 49		}
 50		else {
 51			_lineBuffer = null;
 52		}
 53
 54		_bufferSize = bufferSize;
 55	}
 56
 57	// Description: This will display the prompt and return the line typed by the user.
 58	// Returns: The line typed by the user.
 59	string line() {
 60		// the current displayed line
 61		string line;
 62
 63		// the 'working' line being edited
 64		string workingLine;
 65
 66		// Print out the prompt string
 67
 68		Console.forecolor = _promptClr;
 69
 70		Console.put(_prompt);
 71
 72		// Go into a key loop, wait for a return
 73		// On any special key, fire the callback and expect a result (for instance, on TAB)
 74		// When we are allowed, up and down can signify the use of the line buffer
 75
 76		dchar chr;
 77
 78		uint code;
 79
 80		line = "";
 81
 82		workingLine = line;
 83		if (_lineBuffer !is null) {
 84			_bufferPos = -1;
 85		}
 86
 87		Console.forecolor = _clr;
 88
 89		for(;;) {
 90			Console.getChar(chr, code);
 91
 92			if (code == Key.Return) {
 93				// enter
 94
 95				_pos = 0;
 96
 97				break;
 98			}
 99			else if (code == Key.Backspace) {
100				// backspace
101
102				if (line.length > 0 && _pos > 0) {
103					Console.put(chr);
104					Console.put(' ');
105					Console.put(chr);
106
107					if (_pos == line.length) {
108						line = line.substring(0, line.length-1);
109					}
110					else {
111						string newLine = line.substring(0, _pos-1);
112						string restLine = line.substring(_pos);
113						newLine ~= restLine;
114
115						Console.put(restLine);
116						Console.put(' ');
117
118						for (uint i=0; i<=restLine.length; i++) {
119							Console.put(cast(char)0x8);
120						}
121
122						line = newLine;
123					}
124
125					if (_lineBuffer !is null) {
126						_bufferPos = -1;
127					}
128					workingLine = line;
129
130					_pos--;
131				}
132			}
133			else if (code == Key.Left) {
134				if (_pos > 0) {
135					Console.put(cast(char)0x8);
136
137					_pos--;
138				}
139			}
140			else if (code == Key.Right) {
141				if (_pos < line.length) {
142					Console.setRelative(1,0);
143
144					_pos++;
145				}
146			}
147			else if (code == Key.Up) {
148				// The current line is still stored
149
150				// And then the line buffer spits out
151				// the previous line submitted
152				if (_lineBuffer !is null) {
153					if (_bufferPos+1 < cast(int)_lineBuffer.length && _lineBuffer.length > 0) {
154						// grab the line from the line buffer
155
156						_bufferPos++;
157						line = _lineBuffer.peekAt(_bufferPos);
158
159						uint i;
160
161						if (line.length < _pos) {
162							for (i=line.length; i<_pos; i++) {
163								Console.put(cast(char)0x8);
164								Console.put(' ');
165								Console.put(cast(char)0x8);
166							}
167
168							_pos = line.length;
169						}
170
171						for (i=0; i<_pos; i++) {
172							Console.put(cast(char)0x8);
173						}
174
175						// print the line
176						Console.put(line);
177
178						_pos = line.length;
179					}
180				}
181			}
182			else if (code == Key.Down) {
183				// The current line is still stored
184
185				// And then the line buffer spits out
186				// the next line submitted
187				if (_lineBuffer !is null) {
188					if (_bufferPos > 0) {
189						// grab the line from the line buffer
190
191						_bufferPos--;
192						line = _lineBuffer.peekAt(_bufferPos);
193					}
194					else {
195						// redisplay the working line
196						_bufferPos = -1;
197						if (workingLine !is null) {
198							line = workingLine;
199						}
200					}
201
202					// goto the front of the current line, and erase the current line
203
204					uint i;
205
206					if (line.length < _pos) {
207						for (i=line.length; i<_pos; i++) {
208							Console.put(cast(char)0x8);
209							Console.put(' ');
210							Console.put(cast(char)0x8);
211						}
212
213						_pos = line.length;
214					}
215
216					for (i=0; i<_pos; i++) {
217						Console.put(cast(char)0x8);
218					}
219
220					// print the line
221					Console.put(line);
222
223					// erase the rest of the previous line
224
225					_pos = line.length;
226				}
227			}
228			else if (chr != 0) {
229				// written character
230
231				if (_pos == line.length) {
232					Console.put(chr);
233					line ~= chr;
234				}
235				else if (_pos == 0) {
236					string newLine = "" ~ Unicode.toUtf8([chr]) ~ line;
237
238					Console.put(newLine);
239
240					for (uint i=1; i<newLine.length; i++) {
241						Console.put(cast(char)0x8);
242					}
243
244					line = newLine;
245				}
246				else {
247					Console.put(chr);
248					string leftLine = line.substring(0, _pos);
249					leftLine ~= chr;
250					string rightLine = line.substring(_pos);
251					leftLine ~= rightLine;
252
253					Console.put(rightLine);
254
255					for (uint i=0; i<rightLine.length; i++) {
256						Console.put(cast(char)0x8);
257					}
258
259					line = leftLine;
260				}
261
262				if (_lineBuffer !is null) {
263					_bufferPos = -1;
264				}
265				workingLine = line;
266
267				_pos++;
268			}
269		}
270
271		Console.putln("");
272
273		// Save line in line buffer
274		if (_lineBuffer !is null) {
275			if (_lineBuffer.length == _bufferSize) {
276				_lineBuffer.remove();
277			}
278			_lineBuffer.add(line);
279
280			_bufferPos = -1;
281		}
282
283		return line;
284	}
285
286protected:
287
288	// the prompt string, for instance "# " or "C:\>"
289	string _prompt;
290	Color _promptClr = Color.Gray;
291	Color _clr = Color.Gray;
292
293	Queue!(string) _lineBuffer;
294	int _bufferSize;
295	int _bufferPos;
296
297	uint _pos;
298}