How to create your own Shell with Python (bottom)

Source: Internet
Author: User
In the previous article, we have created a shell main loop, sliced the command input, and forkAnd execExecutes the command. In this part, we will solve the remaining problems. First of all cd test_dir2The command cannot modify our current directory. Second, we are still unable to gracefully exit from the shell.

Step 4: Built-in commands

The cd test_dir2 phrase "unable to modify our current directory" is correct, but in a sense it is also wrong. After executing the command, we are still in the same directory, in this sense, it is right. However, the directory has actually been modified, except that it was modified in the subprocess.

Remember when we forked (fork) a child process and then executed the command, the process of executing the command did not occur on the parent process. As a result, we just changed the current directory of the child process, not the parent process's directory.

The child process then exits, and the parent process continues to run under the unchanged directory.

Therefore, this type of command, which is related to the shell itself, must be a built-in command. It must be executed in the shell process instead of in the fork (forking).

Cd

Let's start with the cd command.

We first create a builtins directory. Each built-in command is placed into this directory.

yosh_project|--yosh   |--builtins   |   | --__init__.py   |   | --cd.py   |--__init__.py   |--shell.py

In cd.py , we implement our own commands by using system calls os.chdir cd .

Import osfrom yosh.constants import *def CD (args):    os.chdir (args[0])    return Shell_status_run

Note that we will return the shell's running state from the built-in function. So, to be able to continue using constants in the project, we move them to yosh/constants.py .

yosh_project|--yosh   |--builtins   |   | --__init__.py   |   | --cd.py   |--__init__.py   |--constants.py   |--shell.py

In constants.py , we put the state constants here.

Shell_status_stop = 0shell_status_run = 1

Now, our built-in cd is ready. Let's modify shell.py them to handle these built-in functions.

... # # # import constants from yosh.constants import *### use hash map to store built-in function names and their references Built_in_cmds = {}def tokenize (string):    return Shlex.split (String) def execute (cmd_tokens):    # # # # # # # # # # Split command names and parameters from tuples    cmd_name = cmd_tokens[0]    Cmd_args = cmd_ Tokens[1:]    # # # If the command is a built-in command, use parameters to call the function if    cmd_name in Built_in_cmds:        return Built_in_cmds[cmd_name] (cmd_ args)    ...

We use a python dictionary variable built_in_cmds as a hash-mapped hash map to store our built-in functions. We execute extract the name and parameters of the command in the function. If the command is shot in our hash map, the corresponding built-in function is called.

(Hint: built_in_cmds[cmd_name] returns a function reference that can be called directly with a parameter.) )

We're almost ready to use the built-in cd functions. The final step is cd to add the function to the built_in_cmds map.

... # # # import all built-in functions reference from Yosh.builtins Import *...### Register the built-in function to the built-in command hash map shot def register_command (name, func):    built_in_ Cmds[name] = func### Register all built-in commands in Def init ():    Register_command ("CD", CD) def main ():    # # #在开始主循环之前初始化 Shell    Init ()    Shell_loop ()

We defined the register_command function to add a built-in function to our built-in command hash map. Next, we define the init function and register the built-in cd function here.

Pay attention to this line register_command("cd", cd) . The first parameter is the name of the command. The second argument is a function reference. In order to be able to cd refer to yosh/builtins/cd.py the function reference in the second argument cd , we must place the following line in the yosh/builtins/__init__.py file.

From YOSH.BUILTINS.CD Import *

So, in yosh/shell.py , when we import from yosh.builtins * , we can get yosh.builtins a function reference that has been imported cd .

We've got the code ready. Let's try yosh to run our shell as a module in a sibling directory python -m yosh.shell .

Now the cd command can modify our shell directory correctly, and the non-built command will still work. Very good!

Exit

The last piece finally came: gracefully withdrew.

We need a function that can modify the shell state SHELL_STATUS_STOP . This way, the shell loop can end naturally and the shell will reach the end and exit.

And cd , if we fork and execute a function in a subprocess exit , it has no effect on the parent process. Therefore, the exit function needs to be a shell built-in function.

Let's start with this: builtins create a new file named under the directory exit.py .

yosh_project|--yosh   |--builtins   |   | --__init__.py   |   | --cd.py   |   | --exit.py   |--__init__.py   |--constants.py   |--shell.py

exit.pyDefines a exit function that simply returns a state that can exit the main loop.

From yosh.constants import *def exit (args):    return Shell_status_stop

We then import yosh/builtins/__init__.py the function reference that is located in the file exit .

From YOSH.BUILTINS.CD import *from yosh.builtins.exit Import *

Finally, we shell.py register the command in the init() function exit .

# # # # # # # # # # # # here to register all built-in Commands def init ():    Register_command ("CD", CD)    Register_command ("Exit", exit) ...

End

Attempt to execute python -m yosh.shell . Now you can enter exit gracefully to exit the program.

The final idea

I want you to enjoy yosh the process of creating (your own shell) as much as I do. But my yosh version is still in its early stages. I did not deal with some extreme situations that would cause the shell to crash. There are many built-in commands that I don't have covered. To improve performance, some non-built-in commands can also be implemented as built-in commands (avoid new process creation time). At the same time, a large number of functions have not been implemented.

I have provided the source code in the Https://github.com/supasate/yosh. Please feel free to fork and try.

Now it's time to create the Shell you really own.

Happy coding!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.