protected virtual LineExecutionResultCode ExecuteLine(string line) { ICommandSeparator commandSeparator = GetSeparator(); if (commandSeparator != null) { StringBuilder lineBuilder = new StringBuilder(line); lineBuilder.Append(Environment.NewLine); commandSeparator.Append(lineBuilder.ToString()); LineExecutionResultCode resultCode = LineExecutionResultCode.Incomplete; while (commandSeparator.MoveNext()) { string completeCommand = commandSeparator.Current; if (HandlesSettings) { completeCommand = Settings.Substitute(completeCommand); } Command c = Commands.GetCommand(completeCommand); if (c == null) { commandSeparator.Consumed(); // do not shadow successful executions with the 'line-empty' // message. Background is: when we consumed a command, that // is complete with a trailing ';', then the following newline // would be considered as empty command. So return only the // 'Empty', if we haven't got a succesfully executed line. if (resultCode != LineExecutionResultCode.Executed) { resultCode = LineExecutionResultCode.Empty; } } else if (!c.IsComplete(completeCommand)) { commandSeparator.Cont(); resultCode = LineExecutionResultCode.Incomplete; } else { Execute(ActiveContext, completeCommand.Trim()); commandSeparator.Consumed(); resultCode = LineExecutionResultCode.Executed; } } return(resultCode); } // if we don't have any separator, we assume it's a complete command Execute(ActiveContext, line); return(LineExecutionResultCode.Executed); }
public void Run() { Initialize(); OnRunning(); running = true; string cmdLine = null; // string displayPrompt = prompt; historyLine = new StringBuilder(); try { while (!terminated) { interrupted = false; // a CTRL-C will not interrupt the current reading // thus it does not make much sense here to interrupt. // WORKAROUND: Write message in the Interrupt() method. // TODO: find out, if we can do something that behaves // like a shell. This requires, that CTRL-C makes // Readline.ReadLine() return. if (IsInterruptable) { Interruption.Push(this as IInterruptable); } try { // cmdLine = (hasTerminal) ? Readline.ReadLine(displayPrompt) : ReadLineFromFile(); cmdLine = Input.ReadLine(); } catch (EndOfStreamException) { // EOF on CTRL-D if (OnTerminated()) { // displayPrompt = prompt; Input.CompleteLine(); continue; } break; } catch (Exception e) { #if DEBUG System.Console.Error.WriteLine(e.Message); System.Console.Error.WriteLine(e.StackTrace); #endif } if (IsInterruptable) { Interruption.Reset(); } // anyone pressed CTRL-C if (interrupted) { if ((cmdLine == null || cmdLine.Trim().Length == 0) && historyLine.Length == 0) { terminated = true; // terminate if we press CTRL on empty line. } historyLine.Length = 0; // displayPrompt = prompt; Input.CompleteLine(); continue; } if (cmdLine == null) { continue; } // if there is already some line in the history, then add // newline. But if the only thing we added was a delimiter (';'), // then this would be annoying. if (historyLine.Length > 0 && !cmdLine.Trim().Equals(dispatcher.CommandSeparator.ToString())) { historyLine.Append(Environment.NewLine); } historyLine.Append(cmdLine); LineExecutionResultCode lineExecState = ExecuteLine(cmdLine); // displayPrompt = lineExecState == LineExecutionResultCode.Incomplete ? emptyPrompt : prompt; if (lineExecState != LineExecutionResultCode.Incomplete) { Input.CompleteLine(); StoreHistoryLine(); historyLine.Length = 0; } } if (IsInterruptable) { Interruption.Reset(); } } catch (Exception e) { #if DEBUG System.Console.Error.WriteLine(e.Message); System.Console.Error.WriteLine(e.StackTrace); #endif Exit(1); } finally { running = false; } }