Tạo tập lệnh hoàn thành bash để tự động hoàn thành các đường dẫn sau dấu bằng?


11

Tôi muốn tạo một tập lệnh hoàn thành bash để nhận ra các đối số của biểu mẫu --arg--some-arg=file.

Sau khi đọc hướng dẫn này và một số ví dụ trong /usr/share/bash_completion/completions/, tôi đã viết đoạn mã sau (để tiết kiệm thời gian khi nhập một số cờ bằng Chromium):

_chromium() 
{
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"

    # Some interesting options
    opts="
--disable-web-security
--easy-off-store-extension-install
--incognito
--load-extension=
--pack-extension=
--pack-extension-key=
--user-data-dir=
"
    # Handle --xxxxxx=file
    if [[ ${cur} == "--"*"=" ]] ; then
        # Removed failures (is my logic OK?)
        return 0
    fi

    # Handle other options
    if [[ ${cur} == -* ]] ; then
        COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
        return 0
    fi
}
complete -F _chromium chromium

Tôi đã lưu nó vào ~/bash_completions/chromiumvà tạo một liên kết tượng trưng bằng cách sử dụng sudo ln -s ~/bash_completions/chromium /usr/share/bash_completion/completions/chromium.
Sau đó tôi tải nó bằng cách sử dụng . /usr/share/bash_completions/completions/chromium.

Bây giờ, tôi đang gặp hai vấn đề:

  • chromium --u<TAB>mở rộng đến chromium --user-data-dir=<SPACE>(tôi không muốn không gian).
  • Đường dẫn (thư mục và tệp) không được hoàn thành nữa.

Làm thế nào tôi có thể giải quyết những vấn đề này?


Là chuyển sang zsh một tùy chọn?
Gilles 'SO- ngừng trở nên xấu xa'

Câu trả lời:


11

Tôi đã tìm ra giải pháp cho cả hai vấn đề!

  1. Để không thêm một khoảng trắng, sử dụng nospacetùy chọn. Điều này có thể được thực hiện theo hai cách:

    • Vượt qua nó để complete:
      complete -o nospace -F _chromium chromium
    • Sử dụng tích compopthợp:
      compopt -o nospace(để bật tùy chọn)
      compopt +o nospace(để tắt tùy chọn)

    Tôi đã tìm thấy nó trong tài liệu Bash tại gnu.org, 8.7 Các chương trình xây dựng hoàn thành có thể lập trình .

  2. Hoàn thành các tập tin.
    • peterph đề nghị sử dụng -fcờ với compgen. Tôi làm theo lời khuyên đó, và thực hiện nó như COMPREPLY=( $(compgen -f "$cur") ). Điều này hoạt động tốt, cho đến khi tôi cố gắng hoàn thành một con đường chứa khoảng trắng.
      Trên Stack Overflow, tôi đã tìm thấy câu trả lời này trong đó khuyến nghị tạo thủ công danh sách hoàn thành (không sử dụng compgen). Cách tiếp cận này hoạt động tốt.
    • Sử dụng filenamestùy chọn để cho Readline biết rằng compspec tạo tên tệp, vì vậy nó có thể:
      • thực hiện bất kỳ xử lý cụ thể nào cho tên tệp (như thêm dấu gạch chéo vào tên thư mục, trích dẫn các ký tự đặc biệt hoặc bỏ qua khoảng trắng ở cuối)
      • sử dụng các màu khác nhau để chỉ ra loại tệp ( colored-statsđã bật)

Với sự trợ giúp của thao tác chuỗi của Bash (để mở rộng ~và xử lý các khoảng trắng), tôi đã xây dựng một tập lệnh hoàn thành bash đáp ứng tất cả các tiêu chí được nêu trong câu hỏi.

_chromium() 
{
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"

    # Some interesting options
    opts="
--disable-web-security
--easy-off-store-extension-install
--incognito
--load-extension=
--pack-extension=
--pack-extension-key=
--user-data-dir=
"
    # Handle --xxxxxx=
    if [[ ${prev} == "--"* && ${cur} == "=" ]] ; then
        compopt -o filenames
        COMPREPLY=(*)
        return 0
    fi
    # Handle --xxxxx=path
    if [[ ${prev} == '=' ]] ; then
        # Unescape space
        cur=${cur//\\ / }
        # Expand tilder to $HOME
        [[ ${cur} == "~/"* ]] && cur=${cur/\~/$HOME}
        # Show completion if path exist (and escape spaces)
        compopt -o filenames
        local files=("${cur}"*)
        [[ -e ${files[0]} ]] && COMPREPLY=( "${files[@]// /\ }" )
        return 0
    fi

    # Handle other options
    COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
    if [[ ${#COMPREPLY[@]} == 1 && ${COMPREPLY[0]} != "--"*"=" ]] ; then
        # If there's only one option, without =, then allow a space
        compopt +o nospace
    fi
    return 0
}
complete -o nospace -F _chromium chromium

Câu trả lời tuyệt vời, cảm ơn rất nhiều. Bạn đã tiết kiệm rất nhiều thời gian của tôi. Tôi đã sử dụng -fchuyển đổi để hoàn thành đường dẫn tệp, nhưng nó không hoàn thành /char nếu nó là một thư mục ... mặc dù đó là một việc nhỏ.
Jiri Kremser

1

Để tên tập tin hoàn thành thử đi -ftới compgen.

Tôi e rằng bạn sẽ không thể thoát khỏi các khoảng trống sau các tùy chọn, vì đó là cách hoàn thành hoạt động - một khi nó tìm thấy một kết quả khớp duy nhất, nó sẽ hoàn thành nó.


Cảm ơn lời đề nghị của -f. Tôi đã thử nó, nhưng nó không xử lý chính xác các khoảng trắng: Đường dẫn dẫn /tmp/foo barđến hai mục hoàn thành /tmp/foobar. Về điều không mong muốn --arg=<SPACE>: Tôi đã tìm ra giải pháp cho điều đó, và đăng nó trong câu trả lời dưới đây .
Rob W
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.