static int Main(string[] args) { // Create a shell command based on the arguments. The CreateShellCommand method will catch any command line errors // and print error details and usage information on the console, so we don't have to worry about that here. CreateShellCommandOptions options = new CreateShellCommandOptions(); options.UsageOptions.IncludeDefaultValueInDescription = true; options.UsageOptions.IncludeAliasInDescription = true; ShellCommand command = ShellCommand.CreateShellCommand(Assembly.GetExecutingAssembly(), args, 0, options); if (command != null) { // The command line arguments were successfully parsed, so run the command. command.Run(); // When using shell commands, it's good practice to return the value of the ExitStatus property to the operating system. // The application or script that invoked your application can check the exit code from your application to // see if you were successful or not. Error codes are completely application specific, but usually 0 is used to // indicate success, and any other value indicates an error. return(command.ExitCode); } return(1); // Return an error status if the command couldn't be created. }
public void Run(ConsoleContext console, Dictionary <string, object> arguments) { _plexgate.Inject(_shell); console.SlowWrite("Welcome to the Peacegate OS Terminal.\n"); Thread.Sleep(1000); console.SlowWrite("You are currently running the Tutorial Command Interpreter.\n"); Thread.Sleep(1000); console.SlowWrite("This program will show you the basics of using bash, Peacegate OS's command interpreter program.\n"); Thread.Sleep(1000); console.SlowWrite("Bash is a command-line tool used by many Unix-based operating systems. Its ubiquity means it is very important to learn it if you want to be a poweruser.\n"); Thread.Sleep(1000); console.SlowWrite("Since it is used by Peacegate OS, Bash is an essential skill if you want to help save The Peacenet.\n"); Thread.Sleep(1000); console.SlowWrite("Below is the Bash command line. You'll be able to tell when you are in Bash as the command line will end with a '$'. To continue, run the 'help' command to see a list of commands.\n"); string commandInput = null; console.Write("$ "); while (!(commandInput = console.ReadLine()).ToLower().StartsWith("help")) { console.SlowWrite("That wasn't the right command. Please type 'help'."); console.Write("$ "); } _shell.ProcessCommand(console, commandInput); _hasLearnedHelp = true; console.WriteLine(""); console.SlowWrite("Running commands is great, but what if they need extra input from you?\n"); Thread.Sleep(1000); console.SlowWrite("Well, bash has you covered. After you type the name of your command (all one word), everything after it is considered arguments.\n"); Thread.Sleep(1000); console.SlowWrite("Each argument is separated by a space. But if you need to put a space in your argument, you can surround it in double-quotes or put a single back-slash before your space.\n"); Thread.Sleep(1000); console.SlowWrite("For example: '\"This is all one argument\"' and 'This\\ is\\ all\\ one\\ argument' mean the same thing.\n"); Thread.Sleep(1000); console.SlowWrite("You can test this out using the 'echo' command. Try making the Terminal say something using the 'echo' command!\n"); Thread.Sleep(1000); echo: console.Write("$ "); string echoInput = console.ReadLine(); if (!echoInput.ToLower().StartsWith("echo")) { console.SlowWrite("That's not the right command. You need to use the 'echo' command."); goto echo; } var parsed = WatercolorGames.CommandLine.Tokenizer.TokenizeString(echoInput); if (parsed.Length != 2) { console.SlowWrite("You didn't specify the right amount of arguments for the command! Please try again!"); goto echo; } _shell.ProcessCommand(console, echoInput); _hasLearnedArguments = true; console.WriteLine(""); console.SlowWrite("Good work! You're starting to learn the basics. Of course, not all commands will be that simple to use.\n"); Thread.Sleep(1000); console.SlowWrite("Fortunately, as part of the peacegate.coreutils package, there is a special command called 'man'. This command will show you useful information about a given Peacegate command, such as what it does and what arguments it needs.\n"); Thread.Sleep(1000); console.SlowWrite("'man' will come in handy as you find more and more programs for your Peacegate OS. Luckily, it is just as easy to use as 'echo', and only takes one argument - the name of the command to get info about.\n"); Thread.Sleep(1000); console.SlowWrite("Why not give it a try? Check out the manual entry for the 'themeconf' command. This is the command-line utility that was used by Peacegate OS Setup to set your wallpaper and accent color.\n"); Thread.Sleep(1000); man: console.Write("$ "); string manInput = console.ReadLine(); if (!manInput.ToLower().StartsWith("man")) { console.SlowWrite("That wasn't the man command! Try again."); goto man; } var manparsed = WatercolorGames.CommandLine.Tokenizer.TokenizeString(manInput); if (manparsed.Length != 2) { console.SlowWrite("You didn't specify the right amount of arguments for the 'man' command! Try again."); goto man; } if (manparsed[1] != "themeconf") { console.SlowWrite("You didn't request info for the 'themeconf' command! Try again."); goto man; } _shell.ProcessCommand(console, manInput); console.WriteLine(""); console.SlowWrite("As you can see, 'help' and 'man' are both very useful for learning the different commands and programs you can run in Peacegate OS.\n"); Thread.Sleep(1000); console.SlowWrite("'help' will show you a list of all available commands, and 'man' will tell you more information about a single command.\n"); Thread.Sleep(1000); console.SlowWrite("Use them together, and you'll be a Peacegate power user in no time.\n"); Thread.Sleep(5000); _hasLearnedManPages = true; console.Clear(); console.SlowWrite("The next thing you need to know before you can start being a Bash pro is Unix console redirection and piping.\n"); Thread.Sleep(5000); console.SlowWrite("Piping allows you to string a bunch of commands together, having the output of one command used as the input for the next, and so on, until the final output is displayed to your screen.\n"); Thread.Sleep(1000); console.SlowWrite("You'd be surprised how handy this will come in your adventures.\n"); Thread.Sleep(1000); console.SlowWrite("Console redirection allows you to save the final output of a single command or a sequence of piped commands to a file.\n"); Thread.Sleep(1000); console.SlowWrite("You can have the final output either appended to an existing file or have it overwrite a file. In either case, if the file doesn't exist, it will be created and filled with the final command output.\n"); Thread.Sleep(1000); console.SlowWrite("First, let's cover piping. You can pipe two or more commands together by separating each command with a '|' character.\n"); Thread.Sleep(1000); console.SlowWrite("The '|' character tells Bash to take the output of the previous command and use it as input for the next command, as if you manually typed it in.\n"); Thread.Sleep(1000); console.SlowWrite("Give it a try! Try piping a command into the 'cowsay' command and see what it does.\n"); Thread.Sleep(1000); console.SlowWrite("(Side-note: You have unlocked the full bash shell. Remember that you can type 'help' for a list of commands! The shell will automatically exit when you complete the objective.)\n"); Thread.Sleep(1000); _shell.AllowExit = false; _shell.CommandRun = (command) => { return(command.Commands.Length > 1 && command.Commands.Last() == "cowsay"); }; _shell.Run(console, new Dictionary <string, object>()); console.SlowWrite("Good job. I hope that cow looks cute enough. Anyway, now that you know how to pipe, let's learn redirection - so you can save that cow to disk.\n"); Thread.Sleep(1000); console.SlowWrite("First, let's talk about file paths in Peacegate OS.\n"); Thread.Sleep(1000); console.SlowWrite("In Peacegate OS, your hard drive is split into files and directories.\n"); Thread.Sleep(1000); console.SlowWrite("It is a hierarchial filesystem, meaning you can store directories inside directories.\n"); Thread.Sleep(1000); console.SlowWrite("Directories contain files, and files contain data that can be read into programs or written by programs.\n"); Thread.Sleep(1000); console.SlowWrite("Paths are a way to tell Peacegate OS where to find a file.\n"); Thread.Sleep(1000); console.SlowWrite("Paths can either be absolute or relative. Absolute paths always start with the '/' character, because '/' is the root directory of your hard drive and you can't go any higher in the hierarchy than /.\n"); Thread.Sleep(1000); console.SlowWrite("Relative paths do not start with '/', and they are usually relative to a 'working' directory. Bash has its own working directory, which you can change using the 'cd' command.\n"); Thread.Sleep(1000); console.SlowWrite("Each directory also has a '..' and a '.' directory inside it (except for '/', it doesn't have '..'). The '..' directory points to the parent directory in the hierarchy, and the '.' directory just loops back into the directory it's in.\n"); Thread.Sleep(1000); console.SlowWrite("So, in bash, running 'cd ..' means \"Take me up one level in the file hierarchy and set that as my working directory.\"\n"); Thread.Sleep(1000); console.SlowWrite("To see a list of directories and files in the current working directory, you can use 'ls'. Use 'ls -a' to show hidden files and directories (including '.' and '..'). Any file or directory with a name that starts with '.' is hidden.\n"); Thread.Sleep(1000); console.SlowWrite("With console redirection, you can specify an absolute or relative path to where your file should be written. So, if I wanted to write to a file called 'hello.txt' in my working directory, I would simply set my output path to 'hello.txt'. But if I wanted to write to a file somewhere else, I would specify an absolute path like '/home/Documents/readme.txt'.\n"); Thread.Sleep(1000); console.SlowWrite("The output path for console redirection can be set by adding a '>' at the end of the command sequence, followed by a file path.\n"); Thread.Sleep(1000); console.SlowWrite("If you want bash to append the console output to the end of an existing file, simply replace the '>' with a '>>', then specify the path.\n"); Thread.Sleep(1000); console.SlowWrite("Give it a try! Try making the cowsay cow say something and write it to a file!\n"); Thread.Sleep(1000); _shell.CommandRun = (command) => { return((command.Commands.Length > 1 && command.Commands.Last() == "cowsay") && command.OutputFile != null); }; _shell.Run(console, new Dictionary <string, object>()); console.SlowWrite("Great! Now, if you ever want to see the output of those commands, you can just read the file you just saved!\n"); Thread.Sleep(1000); console.SlowWrite("See how useful those features are once you know how to use them?\n"); Thread.Sleep(1000); console.SlowWrite("The next thing you need to learn is how to secure your system for use in The Peacenet...but that's for another time.\n"); Thread.Sleep(1000); console.SlowWrite("For now, this concludes the Peacegate OS Terminal Tutorial. Explore the OS with your new-found skills, and check back when you're ready to learn some more.\n"); Thread.Sleep(5000); _hasLearnedUnixRedirection = true; }