superxcgm / xcshell Goto Github PK
View Code? Open in Web Editor NEWYour own shell
Your own shell
Add include
dir to cmake, so we can use #include "xcshell/xxx.h"
directly, instead of #include "../include/xcshell/xxx.h"
.
User can use \
on line end to wrap long line to multiple small line
Given: User type
echo hello\
world
When: Press Enter
Then: Output hellowrold
Given: User type
echo hello\
world\
haha
When: Press Enter
Then: Output hellowroldhaha
xcShell should not quit when user press CTRL + C
(SIGINT), the program run by xcShell should handle CTRL + C
(SIGINT) as normal.
Given: User in xcShell prompt
When: User hit <CTRL + C>
Then: No quit xcShell.
Given: User use xcShell to run some program, and program haven't quit yet. (For example: bc)
When: User hit <CTRL + C>
Then: Program should handle CTRL + C
normally, while xcShell do not react anything.
User can use quote "
to indicate single arg that contains space
.
Given: User type echo "hello world"
When: Press Enter
Then: Display hello world
without quote syntax.
Given: User type echo 'hello world'
When: Press Enter
Then: Display hello world
without quote syntax.
Given: User type echo "hello world" 'hi ni'
When: Press Enter
Then: Display hello world hi ni
without quote syntax.
Given: User type echo hello world
When: Press Enter
Then: Display hello world
without quote syntax.
For good user experience, user can add chain commands using pipeline
Given: User type some_command
(For example: echo ab)
When: User hit
Then: Print ab on console.
Given: User type some_command | another_command
(For example:ls -l | grep 'hello'
)
When: User hit
Then: Should use output of first command as input of second command.
Support of multi pipe, like command1 | command2 | command3
Epic:
Process
Description:
User can press Ctrl + D to quit our shell when we wait user to input command.
Writ main to chain three part together(init, process, exit), just skeleton not detail of these parts need.
AC:
If user currently work in repo that manage by git, shell should display current branch name in prompt.
Not in a git repo
Given: User currently in a directory that not manage by git
When: User open xcShell
Then: Display {current_dir} >
as prompt
In repo root directory and master
branch
Given: User currently in a directory that manage by git (For example, in our xcShell repo root directory /xxxx/xcShell
), and currently in master
branch
When: User open xcShell
Then: Display {current_dir} git(master) >
as prompt, git(master)
should display in different color with {current_dir}
.
In repo root directory and not in master
branch
Given: User currently in a directory that directly manage by git (For example, in our xcShell repo root directory /xxxx/xcShell
), and currently inxcShell/issues/54
branch
When: User open xcShell
Then: Display {current_dir} git(xcShell/issues/54) >
as prompt, git(xcShell/issues/54)
should display in different color with {current_dir}
.
In repo sub directory
Given: User currently in a directory that not manage by git, but it's ancestor's dir is manage by git (For example, in our xcShell repo directory /xxxx/xcShell/cmake-build-debug
), and currently inmaster
branch
When: User open xcShell
Then: Display {current_dir} git(master) >
as prompt, git(master)
should display in different color with {current_dir}
.
In repo.git
directory
Given: User currently in .git
directory (For example, in our xcShell repo directory /xxxx/xcShell/.git
), and currently inmaster
branch
When: User open xcShell
Then: Display {current_dir} git(master) >
as prompt, git(master)
should display in different color with {current_dir}
.
User do not install git
Given: User currently in a directory that manage by git (For example, in our xcShell repo root directory /xxxx/xcShell
), and do not install git
When: User open xcShell
Then: Display {current_dir} >
as prompt.
For good user experience, user can add some config to config file, and xcShell should auto load it when init
Given: Do not have config /etc/xcshrc
When: Run xcShell
Then: Auto create with pre-define config
Given: Have config /etc/xcshrc
When: Run xcShell
Then: Load config /etc/xcshrc
and execute
Given: Have config ~/.xcshrc
When: Run xcShell
Then: Load config ~/.xcshrc
and execute. (This should happen after load of /etc/xcshrc
)
alias ls='ls -G'
alias ll='ls -lh'
alias gst='git status'
alias gup='git pull --rebase'
alias gcm='git checkout $(git_main_branch)'
alias gco='git checkout'
AC:
Epic:
Process
Description:
Before execute user command, we usually need to split input line into command and args. The goal of this card is to split user input line into two part: 1. command name 2. arg list. You just need to consider space
as delimiter.
AC:
Given: User input echo hello world
When: Press enter
Then: Line parsed into command echo
, and args ['hello', 'world']
Currently, our code can not compile on Ubuntu 20.04 LTS.(Can not load readline
correctly, some complain on function not found, and etc. ) The goal of this card is to make sure our code can compile successfully on Ubuntu 20.04 LTS.
Given: User download source code
When: User run ./auto/build
Then: Should build successful, and can find executable xcShell
and xcShell_test
in build directory.
Given: Developer make some change in code
When: Developer merge code to github
Then: Pipeline should run compile and test (Make sure test can pass.)
Shell should able to remember some directories that user frequently access, and navigate user to that directory by using j
command. If user quit shell and run shell again, shell should not lost it's memory. You can checkout more information on https://github.com/wting/autojump.
Behave like cd
Given: User current in some directory, for example: foo
, and have sub directories a
, b
When: User type j a
and hit <Enter>
Then: shell should change working directory to directory a
Quick access
Given: User usually go to some directory, for example: foo
, and currently in home directory ~
When: User type j foo
and hit <Enter>
Then: shell should change working directory to directory foo
Quick access with fuzzy match
Given: User usually go to some directory, for example: foo
, and currently in home directory ~
When: User type j fo
and hit <Enter>
Then: shell should change working directory to directory foo
We should let user know where he is by prompting something like > Downloads
.
Given: User in it's home dir
When: N/A
Then: We should prompt > ~
Given: User in some dir name /home/xxxx/Downloads
When: N/A
Then: We should prompt > Downloads
Given: User in root dir /
When: N/A
Then: We should prompt > /
Integrate Sonar Cloud. Add code static analyze(code style, potential security issue, etc.) and test coverage.
After parse user input line to command and args, we need to execute it. We need to search command in PATH env variable, run it with args user input.
Given: User input ls -l
When: Press enter
Then: It should execute and print something like this:
total 9
drwxrwxr-x 34 root admin 1088 Jun 18 08:35 Applications
drwxr-xr-x 65 root wheel 2080 Jun 17 21:45 Library
drwxr-xr-x@ 9 root wheel 288 Jan 1 2020 System
drwxr-xr-x 6 root admin 192 Jan 1 2020 Users
drwxr-xr-x 3 root wheel 96 Jun 17 21:47 Volumes
drwxr-xr-x@ 38 root wheel 1216 Jan 1 2020 bin
...
Given: User execute some command
When: User command output something
Then: Command output should print to same place with xcShell
User can use build-in comand git_current_branch
to get current branch name.
Not in a git repo
Given: User currently in a directory that not manage by git
When: User type git_current_branch
and hit <Enter>
Then: No output, not error.
In repo root directory and master
branch
Given: User currently in a directory that manage by git (For example, in our xcShell repo root directory /xxxx/xcShell
), and currently in master
branch
When: User type git_current_branch
and hit <Enter>
Then: Print master
, no extra \n
.
In repo root directory and not in master
branch
Given: User currently in a directory that directly manage by git (For example, in our xcShell repo root directory /xxxx/xcShell
), and currently inxcShell/issues/54
branch
When: User type git_current_branch
and hit <Enter>
Then: Print xcShell/issues/54
, no extra \n
.
In repo sub directory
Given: User currently in a directory that not manage by git, but it's ancestor's dir is manage by git (For example, in our xcShell repo directory /xxxx/xcShell/cmake-build-debug
), and currently inmaster
branch
When: User type git_current_branch
and hit <Enter>
Then: Print master
, no extra \n
.
In repo.git
directory
Given: User currently in .git
directory (For example, in our xcShell repo directory /xxxx/xcShell/.git
), and currently inmaster
branch
When: User type git_current_branch
and hit <Enter>
Then: Print {current_branch}
, no extra \n
.
User do not install git
Given: User currently in a directory that manage by git (For example, in our xcShell repo root directory /xxxx/xcShell
), and do not install git
When: User type git_current_branch
and hit <Enter>
Then: No output, not error.
For good user experience, user can add chain commands using pipeline
Given: User type command1 | command2 | command3
(For example: cat /etc/passwd | grep sh | less
)
When: User hit <Enter>
Then: Output of first command should be input of second command, and output of second command should be input of third command.
AC:
tab
to auto complete filename (Done by editline)TZ=Pacific/Samoa date
wc -c *
exit
to quit shell
, \t
, \n
, \r
or \a
$?
It's hard to debug and can't know what happened without log.
Given: NA
When: User run xcShell
Then: xcShell will print log to /tmp/xcShell.log
, and will not clear it if we restart xcShell.
Log should contains timestamp.
For good user experience, user can add redirect input/output to other file
Given: User type some_command > tmp.txt
(For example: echo ab > b.txt)
When: User hit <Enter>
Then: Redirect output of command some_command
to tmp.txt
, truncate file before write if tmp.txt
exist.
Given: User type some_command >> tmp.txt
(For example: echo aa >> a.txt)
When: User hit <Enter>
Then: Redirect output of command some_command
to tmp.txt
, append to end of file if tmp.txt
exist.
Given: User type some_command < tmp.txt
(For example: bc < bc.input)
When: User hit <Enter>
Then: Redirect input of command some_command
to tmp.txt
Given: User type some_command < tmp.txt > c.txt
(For example: bc < bc.input > bc.output)
When: User hit <Enter>
Then: Redirect input of command some_command
to tmp.txt
, and redirect output to c.txt.
Currently, user use ./auto/install.sh
to install our program, which looks not so good, we want user use make install
to install xcShell and necessary config.
Given: User already compile our xcShell using make
When: User run make install
Then: Should install xcShell to correct place, like /usr/local/bin
, and write default config file to /etc
if it's not exist.
Shell should able to redirect stderr to other file or same as stdout.
Redirect stderr to other file (override)
Given: User type some-command 2> a.out
(For example: echo '1 / 0' | bc 2> a.out
)
When: User hit <Enter>
Then: shell should clear content of file a.out
redirect stderr to a.out
Redirect stderr to other file (append)
Given: User type some-command 2>> a.out
(For example: echo '1 / 0' | bc 2>> a.out
)
When: User hit <Enter>
Then: shell should not clear content of file a.out
, redirect stderr to end of a.out
Redirect stderr to same as stdout (override)
Given: User type some-command > a.out 2>&1
(For example: echo '1 / 0' | bc > a.out 2>&1
)
When: User hit <Enter>
Then: shell should clear content of file a.out
, redirect stderr and stdout to a.out
Redirect stderr to same as stdout (append)
Given: User type some-command >> a.out 2>&1
(For example: echo '1 / 0' | bc >> a.out 2>&1
)
When: User hit <Enter>
Then: shell should not clear content of file a.out
, redirect stderr and stdout to end of a.out
Redirect stderr to different file as stdout
Given: User type some-command > a.out 2> b.out
When: User hit <Enter>
Then: shell should clear content of file a.out
redirect stdout to a.out
, and clear content of file b.out
redirect stderr to b.out
.
Demo test c code for case 5.
#include <stdio.h>
int main() {
printf("hello world\n");
fprintf(stderr, "fuck the world\n");
return 0;
}
Currently, we implement xcShell by features we used mostly, but we need to know the big picture of bash.
In order to have big picture of bash, you need to investigate what features that GNU bash support, and divided these features into several category, and mark whether we already support it or partial support or do not support it currently. Draw a diagram or write down a document, share with team.
For good user experience,
Given: User input something, and cursor not on left most
When: User hit left arrow key
Then: Move cursor one character to left
Given: User input something, and cursor on left most
When: User hit left arrow key
Then: No move cursor
Given: User input something, and cursor not on right most
When: User hit right arrow key
Then: Move cursor one character to right
Given: User input something, and cursor on right most
When: User hit right arrow key
Then: No move cursor
Given: none
When: User hit up arrow key
Then: Previous input line appear
Given: none
When: User hit down arrow key
Then: Next input line appear
Currently, we do not handle error of system call properly, and maybe errors during execute command. So the goal of this card is to figure out suitable way to handle with errors.
You might have a spike on how other project handle error of system call.
And fix our code to handle error of system call and error during execute command.
Document how should we handle error if necessary.
User can use Ctrl + l
to clear screen.
Given: Screen have some text output
When: User press Ctrl + l
Then: Previous text output disappear.
As a shell, it should read user input and react correctly. For this card, the goal is to read one line of user input and react with print what user input.
should support long line input, not only 1024 or some what.
Before read user input, we should print >
to hint user to input something.
For good user experience, user can add chain commands using pipeline
Plain $ENV with value
Given: Environment variable XXX exist (For example: $HOME
)
When: User type echo $XXX
, and hit <enter>
Then: shell should replace $XXX
with it's value, and pass this argument to command echo.
Plain $ENV with no value
Given: Environment variable XXX not exist (For example: $haha
)
When: User type echo $XXX
, and hit <enter>
Then: shell should replace $XXX with empty string, and pass this argument to command echo.
$ENV enclose with single quotation marks
Given: No matter environment XXX exist or not.
When: User type echo '$XXX'
, and hit <enter>
Then: shell should not replace $XXX with anything, and pass $XXX
as argument to command echo.
$ENV enclose with double quotation marks
Given: Environment variable XXX exist (For example: $HOME
), and environment variable YYY not exist.
When: User type echo "$XXX $YYY"
, and hit <enter>
Then: shell should replace $XXX
with it's value, and replace $YYY
with empty string, and pas argument {some value}
to command echo.
User can add $(command and args)
in double quote string, shell should able to execute it and replace it with it's result.
Single command
Given: echo "$(git_current_branch)"
When:
Then:
Complex command
Given: echo "$(echo '1 + 1' | bc)"
When:
Then:
`
User should can change current working directory to his target.
Given: cd
When: Press Enter
Then: Change shell working directory to current user home.
Given: cd ~
When: Press Enter
Then: Change shell working directory to current user home.
Given: cd xxx
When: Press Enter
Then: Change shell working directory to xxx
Given: cd -
When: Press Enter
Then: Change shell working directory to previous working directory.
Given: cd ..
When: Press Enter
Then: Change shell working directory to parent directory.
Given: cd .
When: Press Enter
Then: No change shell working directory.
For good user experience, user can add some alias to shell and auto replace when execute command.
Given: User type alias
When: User hit
Then: Print all alias
Given: User type alias ls='ls-G'
When: User hit
Then: Save alias to shell
Given: User already have alias ls='ls -G'
saved in our shell
When: User type ls
and hit
Then: Shell execute ls -G
Given: User already have alias ls='ls -G'
and alias ll='ls -lh'
saved in our shell
When: User type ll
and hit
Then: Shell execute ls -G -lh
Our code use system call a lot, which makes it hard to test by unit test, and our code become more and more complex, so we should have some functional test to make sure we will no broken exist logic during development.
I can run a script to run all functional tests before commit change to git, so that I have confident that our existing logic is all good.
Should cover all future we have already implement:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.