返回

40 行代码实现 mini-readline 🦄

前端

创建自己的命令行解释器:使用 Python 构建一个强大的迷你 readline

前言

在计算机科学的浩瀚世界中,命令行界面(CLI)一直是与计算机交互和执行任务的重要工具。CLI 使我们能够直接与操作系统通信,执行脚本和程序,并访问各种工具和实用程序。对于开发人员、系统管理员和任何希望充分利用计算机的人员来说,掌握 CLI 至关重要。

什么是 readline?

readline 是一个强大的库,用于在交互式应用程序中处理用户输入。它提供了一系列功能,包括命令行编辑、命令历史记录和命令补全。有了 readline,我们可以轻松创建用户友好的命令行界面,让用户可以轻松高效地执行任务。

构建一个迷你 readline

在这篇文章中,我们将踏上创建自己的迷你 readline 的旅程。我们将从头开始构建,逐步添加功能,最终创建一个功能齐全且实用的命令行解释器。

步骤 1:安装 readline 库

首先,我们需要安装 readline 库。在大多数 Linux 发行版中,readline 通常是预安装的。如果您尚未安装它,可以使用以下命令:

sudo apt-get install libreadline-dev

步骤 2:导入必要的模块

在我们的 Python 脚本中,我们需要导入 readline 和其他一些必需的模块:

import readline
import rlcompleter
import atexit
import os

步骤 3:定义一个命令补全器

命令补全器是 readline 的核心组件之一。它负责根据用户输入提供可能的命令完成。我们创建一个 Completer 类来处理命令补全:

class Completer(rlcompleter.Completer):

    def complete(self, text, state):
        """
        Return a list of possible completions for the given text.
        """
        # Get a list of all possible completions.
        completions = [c for c in self.completions if c.startswith(text)]

        # Return the state-th completion.
        if state < len(completions):
            return completions[state]
        else:
            return None

步骤 4:定义一个 MiniReadline 类

现在,我们将定义一个 MiniReadline 类来处理命令行输入和执行:

class MiniReadline:

    def __init__(self):
        """
        Initialize the MiniReadline object.
        """
        # The current working directory.
        self.cwd = os.getcwd()

        # The command history.
        self.history = []

        # The current command line.
        self.cmdline = ""

        # The command completer.
        self.completer = Completer()

        # Register the completer with readline.
        readline.set_completer(self.completer)

        # Enable readline.
        readline.parse_and_bind("tab: complete")

        # Register the exit handler.
        atexit.register(self.exit_handler)

步骤 5:处理命令行输入和执行

在 MiniReadline 类中,我们需要定义 get_command() 和 execute_command() 方法来处理命令行输入和执行:

    def get_command(self):
        """
        Get the next command from the user.
        """
        # Get the command line from the user.
        self.cmdline = input(f"{self.cwd}> ")

        # Add the command line to the history.
        self.history.append(self.cmdline)

        # Return the command line.
        return self.cmdline

    def execute_command(self, command):
        """
        Execute the given command.
        """
        # Split the command into a list of arguments.
        args = command.split()

        # Check if the command is a built-in command.
        if args[0] in self.builtins:
            # Execute the built-in command.
            self.builtins[args[0]](args)
        else:
            # Check if the command is a valid external command.
            if os.path.isfile(args[0]):
                # Execute the external command.
                os.system(command)
            else:
                # The command is not a built-in command or a valid external command.
                print(f"{args[0]}: command not found")

步骤 6:定义内置命令

我们可以定义一些内置命令来扩展我们迷你 readline 的功能。例如,我们可以定义一个“cd”命令来更改当前工作目录,一个“ls”命令来列出文件和目录,以及一个“exit”命令来退出解释器:

    def cd(self, args):
        """
        Change the current working directory.
        """
        if len(args) < 2:
            print("Usage: cd <directory>")
        else:
            try:
                os.chdir(args[1])
            except FileNotFoundError:
                print(f"{args[1]}: no such directory")

    def ls(self, args):
        """
        List the files and directories in the current working directory.
        """
        print("\n".join(os.listdir()))

    def exit(self, args):
        """
        Exit the interpreter.
        """
        print("Exiting...")
        exit(0)

步骤 7:启动迷你 readline

最后,我们将创建一个 main() 函数来启动我们的迷你 readline 解释器:

def main():
    """
    Start the MiniReadline command line interpreter.
    """
    # Create a MiniReadline object.
    mini_readline = MiniReadline()

    # Start the command line interpreter.
    while True:
        # Get the next command from the user.
        command = mini_readline.get_command()

        # Execute the command.
        mini_readline.execute_command(command)

if __name__ == "__main__":
    main()

运行迷你 readline

现在,我们可以运行我们的迷你 readline 脚本:

python mini_readline.py

这将启动一个命令行解释器,提示符为当前工作目录。我们可以输入命令,例如“cd”, “ls”或“exit”来与解释器交互。

总结

通过遵循这些步骤,我们已经创建了一个功能齐全的迷你 readline 解释器,支持命令行编辑、命令历史记录和命令补全。虽然这是一个简单的实现,但它为理解 readline 库的强大功能和创建自定义命令行界面的基础提供了坚实的基础。

常见问题解答

1. 如何扩展迷你 readline 以支持更多的内置命令?

您可以通过在 MiniReadline 类的内置命令字典(self.builtins)中添加更多条目来扩展迷你 readline 以支持更多的内置命令。

2. 如何添加自定义命令补全?

您可以通过向 Completer 类的补全列表(self.completions)添加更多条目来添加自定义命令补全。

3. 如何处理命令行选项和参数?

您可以使用 Python 的 argparse 模块来处理命令行选项和参数,并为内置命令添加对它们的解析支持。

4. 如何将迷你 readline 集成到现有的 Python 应用程序中?

您可以将 MiniReadline 类实例化并将其作为现有 Python 应用程序的命令行界面。

5. 如何使用迷你 readline 创建更复杂的命令行界面?

您可以利用 readline 的高级功能,例如多行编辑和历史搜索,创建更复杂的命令行界面。