Giter Site home page Giter Site logo

dotnet-shell / shell Goto Github PK

View Code? Open in Web Editor NEW
50.0 2.0 5.0 618 KB

The C# script compatible shell

Home Page: https://dotnet-shell.github.io/

License: MIT License

C# 99.90% NSIS 0.10%
dotnet unix shell bash net5 commandline interactive script dotnetscript linux

shell's Introduction

Welcome to dotnet-shell the C# script compatible shell

Version License: MIT Twitter: therealshodan

dotnet-shell is a replacement for your *Unix shell (bash,sh,dash etc) that brings C#/Dotnet to the command line in a familiar and Bash-like syntax. It combines the best of C# with the shell commands you already know. If you've used dotnetscript or nake you will feel right at home. Best of all it is easy to take your existing Unix shell scripts and port them to dotnet-shell format.

dotnet-shell acts as a meta shell that sits on top of your system shell (Bash/PowerShell etc). It replaces hard to remember loop/if syntax with C# and enables you to use the shell constructs that you know and can't unlearn! It works in both interactive and script modes allowing you to build variables and arguments in C# and use them easily in shell commands.

It is fully featured, supporting:

  • Bash-style tab completion augmented with C# autocompletion
  • Advanced history searching with an improved UX (helped by tmux if desired)
  • Support for loading Nugets, DLLs and other scripts
  • Powerline, command aliasing

Comparison to other projects / check these out too

Since the dotnet runtime enabled REPL (Read Evaluate Print Loop) support there have been a few different projects that have evolved to use it, some of the best are:

  • dotnet-script - A great scripting environment which we use internally to run commands. The UX however is not designed for everyday use and the command line environment lacks an easy way to run system commands.
  • Nake - Another great project focused on build scripts instead of interactive shell environments.
  • Orbital Shell - A great project but focused on being cross platform, supporting the same commands on multiple platforms, as such 'OS' commands have been reimplemented. We took the view of keeping existing logic/syntax similar enough to aid porting.

How to install

First you need to install the .NET6. runtime. this is usually easiest via your OS' package manager. Next run:

dotnet --info

If you see a lot of .NET version information that starts with 6.0 then you have a working copy of the .NET runtime. dotnet-shell is a dotnet tool. It is installed by:

dotnet tool install -g dotnet-shell
OS Status
Linux Stable
Windows In-Testing
Mac Should work untested
BSD Unsupported

There is now initial support for Windows execution via PowerShell. Executing commands works as does variable capture.

Syntax cheatsheet

In general dotnet-shell uses the same syntax of dotnetscript. To make some operations easier this has been extended so that:

  • shell commands are created from any line that doesn't end with a ';' or part of existing C# syntax - just like in Bash
  • backtick characters allow you to execute a command and capture its stdout (rather than letting it go to the screen)
  • nake style variables $...$ allow you to take variables from C# and include these in your system commands

A key point to note is that in generally a line needs to end with a ';' to be interpreted as C# (unless it is part of loop, class etc)

File extension Usage
CSX File contains dotnetscript syntax - no dotnet-shell extension can be used
nsh CSX script syntax with our extensions
CS Can be loaded and executed with #load
DLL Can be loaded with #r

The ExampleScripts repo is a good place to see what you can do.

#!/usr/bin/env dotnet-shell
#r "System.Xml.Linq"                    // reference assemblies                                      
#r "nuget: Newtonsoft.Json"             // and nuget packages is fully supported
#load "Other.csx"                       // You can load other script files
#load ~/ExampleScripts/CmdSyntax.nsh   // (both absolute and relative paths are fine)

using System;                           // many namespaces are loaded by default
using System.Collections.Generic;
using System.Data;
using System.Xml;
using System.Xml.Linq;
using Microsoft.CSharp;

using static System.Console;            // static members smake your scripts shorter
WriteLine("Are you ready? Y/N:");

// You can run a system command just like in Bash
echo "Hello world"

// Wrapping a command in ``(backticks) allows you to capture the output
var x = `ps`; // but default this is a string
// You can also create more complex objects
DirectoryInfo dir = `/bin/echo /bin/`;
FileInfo file = `/bin/echo /bin/ls`;
int aNumber=`/bin/echo 500`;

// You can combine these into something quite powerful
List<string> z=`dmesg`; z.Distinct().Count();

var variable = "Lets say you have a variable";
// This is how you pass it into a system command
echo $variable$

Useful tips and tricks

Escaping input automatically - the following one liner will print escaped C#. Great for copy and pasting into your codebase.

Console.ReadLine();

Command line help

  -v, --verbose               (Default: false) Set output to verbose messages.

  --earlyDebuggerAttach       (Default: false) Enables early debugging for initialization related issues

  --showPreProcessorOutput    (Default: false) Outputs preprocessed scripts and commands to StdOut prior to execution

  -x, --ux                    (Default: Enhanced) The user experience mode the shell starts in

  --profile                   The path to the personal initialization script file (core.nsh)

  -s, --subShell              Path to the sub shell to invoke commands with

  -a, --subShellArgs          Arguments to the provided to the SubShell, this MUST include the format specifier {0}

  -u, --using                 Additional 'using' statements to include

  --popupCmd                  (Default: tmux popup -KER '{0}' -x 60 -y 0 -w 60% -h 100%) Command to run to raise a system popup window, must include {0} format specifier for the dotnet-shell command

  --historyCmd                (Default: dotnet {0} --history --apiport {1} --token {2}) dotnet-shell command line to execute when the history subprocess. Must include {0} format specifier for DLL location, {1} for port and {2} for token parameters

  --additionalHistory         Path to additional OS specific history files

  --historyPath               Path to CSX history file

  --nowizard                  (Default: false) Do not try and run the initial set up wizard

  --help                      Display this help screen.

  --version                   Display version information.

How to build from source

Visual Studio solutions and VS Code projects are published with this repo. Otherwise you can checkout the repo and run:

dotnet build
dotnet src/Shell/bin/Debug/net6.0/dotnet-shell.dll

Author

i-am-shodan

Contributing

Contributions, issues and feature requests are welcome!
Feel free to check issues page.

License

Copyright © 2021 i-am-shodan.
This project is MIT licensed.


This README was generated by readme-md-generator

shell's People

Contributors

i-am-shodan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

shell's Issues

Would it be possible to use an external prompt, such as startship?

Hey again,
I am not sure if you are familiar with the prompt starship, but it's written in rust, cross-platform, and says it should be compatible with most any shell. I am not sure if it would be possible to just pop it in there, though, in a manner similar to other shells? I made a post in their discussions area as well, as I wasn't sure exactly who would be the best to ask. starship/starship#2905

If you have any thoughts on this, I definitely would appreciate it.
Thanks,
-MH

-- Edit
I was looking more through their FAQ and came across this bit:

Basic Implementation

The way Starship is built, it should be possible to add support for virtually any shell. The starship binary is stateless and shell agnostic, so as long as your shell supports prompt customization and shell expansion, Starship can be used.

Here's a small example getting Starship working with bash:

# Get the status code from the last command executed
STATUS=$?

# Get the number of jobs running.
NUM_JOBS=$(jobs -p | wc -l)

# Set the prompt to the output of `starship prompt`
PS1="$(starship prompt --status=$STATUS --jobs=$NUM_JOBS)"

Linux : Pop!_OS 21.04 - Upon install and attempting to run for the first time: "Unhandled exception. System.ComponentModel.Win32Exception (2): No such file or directory"

Hey there,
I just installed this to give it a try, but unfortunately I was greeted with the below error the first time I tried to run it.

Error details
zsh > dotnet tool install -g dotnet-shell
You can invoke the tool using the following command: dotnet-shell
Tool 'dotnet-shell' (version '1.0.0.5') was successfully installed.

~ took 2s
zsh > dotnet-shell
This looks like the first run of dotnet-shell, do you want to run the initial set up wizard (highly recommended)?
Y|N) y

Unhandled exception. System.ComponentModel.Win32Exception (2): No such file or directory
   at System.Diagnostics.Process.ForkAndExecProcess(String filename, String[] argv, String[] envp, String cwd, Boolean redirectStdin, Boolean redirectStdout, Boolean redirectStderr, Boolean setCredentials, UInt32 userId, UInt32 groupId, UInt32[] groups, Int32& stdinFd, Int32& stdoutFd, Int32& stderrFd, Boolean usesTerminal, Boolean throwOnNoExec)
   at System.Diagnostics.Process.StartCore(ProcessStartInfo startInfo)
   at System.Diagnostics.Process.Start()
   at FirstRunWizard.WizardUI.RunAndGetStdOut(String program, String arguments) in D:\Repos\GitHub\dotnet-shell\Shell\src\FirstRunWizard\WizardUI.cs:line 273
   at FirstRunWizard.WizardUI.DoesTmuxSupportPopups() in D:\Repos\GitHub\dotnet-shell\Shell\src\FirstRunWizard\WizardUI.cs:line 224
   at FirstRunWizard.WizardUI.IsSupportedTmuxVersionInstalled() in D:\Repos\GitHub\dotnet-shell\Shell\src\FirstRunWizard\WizardUI.cs:line 204
   at FirstRunWizard.WizardUI.PreRequisitesCheck() in D:\Repos\GitHub\dotnet-shell\Shell\src\FirstRunWizard\WizardUI.cs:line 193
   at FirstRunWizard.WizardUI.StartInteractive() in D:\Repos\GitHub\dotnet-shell\Shell\src\FirstRunWizard\WizardUI.cs:line 40
   at Dotnet.Shell.Program.Main(String[] args) in D:\Repos\GitHub\dotnet-shell\Shell\src\Shell\Program.cs:line 57
   at Dotnet.Shell.Program.<Main>(String[] args)
[1]    2096702 IOT instruction (core dumped)  dotnet-shell
Dotnet info
zsh > dotnet --info 
.NET SDK (reflecting any global.json):
 Version:   5.0.302
 Commit:    c005824e35

Runtime Environment:
 OS Name:     pop
 OS Version:  21.04
 OS Platform: Linux
 RID:         linux-x64
 Base Path:   /usr/share/dotnet/sdk/5.0.302/

Host (useful for support):
  Version: 5.0.8
  Commit:  35964c9215

.NET SDKs installed:
  3.1.405 [/usr/share/dotnet/sdk]
  5.0.103 [/usr/share/dotnet/sdk]
  5.0.302 [/usr/share/dotnet/sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 3.1.11 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.3 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.8 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 3.1.11 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.17 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.3 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.8 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

Thanks,
-MH

Best practice for environment variables / exports?

Hey there,
I tried looking through the API site under Shell and saw Paths, AddCmdAlias, and AddCSAlias, and the like, then I tried to use the search for env / environment but didn't see anything come up. I was wondering if there was a best practice for creating/using env variables / export data?

I tried a few dotnet methods from the shell just to see what may or may not work, such as:

var p = System.Environment.GetEnvironmentVariable("path", System.EnvironmentVariableTarget.User)  
Console.WriteLine(p);

var p = System.Environment.GetEnvironmentVariable("path", System.EnvironmentVariableTarget.Machine)                                 
Console.WriteLine(p); 

But both came up empty. I was able to use var p = `echo $PATH`; and then write that to console just fine, of course, but I wasn't sure if that would be the "proper" way to go about it. Is the overall intention to use the underlying system's data for things like setting default location path for specific things, etc, or maintain that within the dotnet shell itself?

The main reason I ask, is that my prompt shows up as

# -- Typical prompt in zsh
~
zsh > 

# -- Prompt when using dotnet-shell with Starship
%{%}~%{%}
zsh %{%}>%{%}

Starship uses a config file, which you set via export STARSHIP_CONFIG="$HOME/.config/starship/starship.toml", my first thought when it was displaying oddly, was that using it in dotnet shell, it must not know where my config is, but I guess technically starship is just grabbing it from zsh, since var prompt = `starship prompt ..etc`; is being executed on the underlying shell and then returned, and it looks like it technically is using my settings, they just didn't show up right:

That said, I currently have a few starship configs, one for zsh, one for PScore on Linux, then one for Pwsh on Windows which are on a shared drive. For Pwsh, I had to set the env variables within the PSCore profile, as it doesn't just pick them up as is:

if ($IsWindows) {
    $ENV:STARSHIP_CONFIG = "${DOTROOT}/config/starship/starship.toml"
	...
} else {
    $ENV:STARSHIP_CONFIG = "${DOTROOT}/config/starship/starship_linux.toml"
}

That is what lead me to this post, (which has became much longer than I had anticipated sorry about that), I wasn't quite sure if I should be relying on the shell to pick things like that up on it's own, if I should be grabbing them from the existing environment, or if there was a way I just am not seeing to set them specifically for dotnet shell along with Paths and Aliases?

Thanks,
-MH

Using declaration cannot be used as top-level statement or in shell

Expected behavior

IDisposable objects can be declared with using var as top-level statement, or in interactive shell.

Current behavior

C# compiler throws error out. When the same statement is instead compiled with dotnet run, there is no error.

Sample shell output

!yuntian@Yuntian /home/yuntian> using var f = File.Open("/tmp/test", FileMode.OpenOrCreate);
(1,11): error CS1002: ; expected
!yuntian@Yuntian /home/yuntian> if (0 == 0) { using var f = File.Open("/tmp/test", FileMode.OpenOrCreate); }
!yuntian@Yuntian /home/yuntian> var f = File.Open("/tmp/test", FileMode.OpenOrCreate);
!yuntian@Yuntian /home/yuntian> f.Dispose()
!yuntian@Yuntian /home/yuntian>

Reasoning

Although using var is not exactly useful in main() or in interactive shell where variables will be discarded anyway when the process ends, scripts can be reworked into functions and reused elsewhere. Allowing the variable to be properly declared can save debugging effort down the line.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.