简体   繁体   English

如何在终端中制作 Python 脚本“tab-complete”目录?

[英]How to make a Python script "tab-complete" directories in terminal?

I have a Shell Script, let's say run.sh , which reads a user input from keyboard and then does some specific tasks.我有一个 Shell 脚本,比如说run.sh ,它从键盘读取用户输入,然后执行一些特定任务。 For some technical reasons I'm migrating this script to Python, eg run.py , in order to achieve the exact same goal.出于某些技术原因,我将此脚本迁移到 Python,例如run.py ,以实现完全相同的目标。

In the run.sh file I ask the user a input, which is typically a file in the file system, so I gave the option of "tab-completing" it and I achieved it simply through the line:run.sh文件中,我询问用户一个输入,它通常是文件系统中的一个文件,所以我提供了“tab-completing”它的选项,我只是通过以下行实现它:

read -e -p "Choose a file: " file

The -e flag does the job of tab-completing users input. -e标志完成选项卡完成用户输入的工作。 For example, if user's current directory is project , which follows the structure:例如,如果用户的当前目录是project ,其结构如下:

project
-- src
-- shared
   -- lib
   -- imgs
      -- image.png
-- include
-- README.txt

and the input file is image.png they could proceed as follow:并且输入文件是image.png他们可以如下进行:

sh<tab>i<tab><tab>

the result would be shared/imgs/image.png .结果将是shared/imgs/image.png

Now how do I achieve it inside a Python script?现在我如何在 Python 脚本中实现它? You may believe there are tons of related questions but I haven't been able to reproduce this exact same result in run.py .您可能认为有大量相关问题,但我无法在run.py重现完全相同的结果。

What I have tried so far:到目前为止我尝试过的:

1. Python's os module: 1. Python 的os模块:

import os

os.system("read -e -p 'Choose a file:'")

Output: sh: 1: read: Illegal option -e输出: sh: 1: read: Illegal option -e

2. Python's subprocess module 2. Python 的subprocess模块

import subprocess

subprocess.run(['read', '-e', '-p', 'Choose a file'])

Output:输出:

Traceback (most recent call last):
  File "run.py", line 26, in <module>
    subprocess.run(['read', '-e', '-p', 'Choose a file'])
  File "/usr/lib/python3.7/subprocess.py", line 453, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/usr/lib/python3.7/subprocess.py", line 756, in __init__
    restore_signals, start_new_session)
  File "/usr/lib/python3.7/subprocess.py", line 1499, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'read': 'read'

3. Python's readline module 3. Python 的readline模块

import readline

readline.parse_and_bind("tab:complete")
file = input("Choose a file: ")

This one almost seems to work, but there is one big issue: it completes only the files in user's current directory.这个看起来几乎可以工作,但有一个大问题:它只完成用户当前目录中的文件。 If user hit s<tab> then src and shared show up, but if they hit sh<tab> the lib and imgs directory do not show up.如果用户点击s<tab>然后srcshared出现,但如果他们点击sh<tab> libimgs目录不显示。

I'd like some elegant and simple way to achieve this, but I am convinced this might be a little more difficult than expected.我想要一些优雅而简单的方法来实现这一点,但我相信这可能比预期的要困难一些。 Are there any other approaches that can solve this problem?有没有其他方法可以解决这个问题?

Set sensible completion delimiters:设置合理的完成分隔符:

import readline

readline.set_completer_delims(' \t\n=')
readline.parse_and_bind("tab: complete")
option = input("Tab complete a file: ")

By default, readline will delimit based on any of the following:默认情况下, readline将基于以下任何一项进行分隔:

>>> import readline
>>> readline.get_completer_delims()
' \t\n`~!@#$%^&*()-=+[{]}\\|;:\'",<>/?'

Since / is part of this set, anything after a / will be completed independently of anything before it.由于/是此集合的一部分,因此/之后的任何内容都将独立于其之前的任何内容完成。 This obviously makes no sense when you're trying to complete a file path.当您尝试完成文件路径时,这显然没有意义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM