Có thể cấu hình cách bash hoàn thành tên thư mục?


8

Tôi muốn hướng dẫn bash sử dụng một phương thức đặc biệt để thực hiện hoàn thành trên một số tên thư mục nhất định. Ví dụ, bash sẽ gọi một chương trình của tôi để thực hiện hoàn thành nếu một đường dẫn bắt đầu bằng "$$" và thực hiện hoàn thành bình thường theo cách khác.

Đây có phải là ở tất cả có thể? Làm thế nào bạn sẽ thực hiện nó?

Bounty : Tôi thực sự đánh giá cao câu trả lời cho câu hỏi đó. Mục tiêu là cho phép autojump hoàn thành các đường dẫn cho tất cả các lệnh khi người dùng bắt đầu chúng với một tiền tố nhất định. Vì vậy, ví dụ khi sao chép một tập tin từ một thư mục xa, bạn có thể gõ:

cp $$patern + <Tab>

và autojump sẽ hoàn thành

cp /home/user/CompliCatedDireCTOry/long/path/bla/bla

và bạn sẽ chỉ cần thêm nơi bạn muốn đặt tệp. Tất nhiên tôi có thể sử dụng nhận xét của ott để thêm nó vào một vài lệnh cụ thể, nhưng nếu bất cứ ai có ý tưởng tốt hơn, tôi sẽ rất biết ơn.


Xem phần "Hoàn thành lập trình" trong trang bash man.

Nếu bạn bỏ phiếu để đóng câu hỏi của tôi, xin vui lòng giải thích tại sao.
Peltier

2
"Hoàn thành" hỗ trợ "-G mẫu" để khớp với $$ của bạn một khởi đầu và "-F func" để gọi hàm của riêng bạn, nhưng nó cần một hoặc nhiều tên lệnh để hoạt động.

Tại sao không chỉ sử dụng một biến môi trường? Ví dụ: cp $ tiền tố / tệp / đường dẫn / đến /
mệnh

@Xenoactive: vì autojump hoàn toàn tự động và hoạt động trên nhiều đường dẫn. Sử dụng các biến môi trường được đặt thủ công không giúp ích. Hoặc có thể bạn có một ý tưởng mạnh mẽ mà tôi không hiểu?
Peltier

Câu trả lời:


3

Bạn có thể làm điều này bằng cách ghi đè ràng buộc mặc định cho TAB (^ i). Trước tiên, bạn cần ghi đè liên kết TAB, sau đó bạn cần xây dựng một hàm gọi lệnh của bạn, cuối cùng bạn cần lấy đầu ra từ lệnh đó và cập nhật biến chứa dòng lệnh hiện tại.

Hàm này lấy dòng lệnh hiện tại và thay đổi hai ký tự cuối cùng thành 'huugs'.

function my_awesome_tab_completion_function () {
  set -- $READLINE_LINE
  command="$1"
  shift
  argument="$*"
  argument_length=$(echo -n $argument | wc -c)
  if echo $argument | grep '^$$' >/dev/null 2>&1; then
    new_argument=$(echo $argument | sed 's/..$/huugs/') # put your autojump here
  else
    new_argument=$(compgen -d $argument)
  fi
  new_argument_length=$(echo -n $new_argument | wc -c)
  READLINE_POINT=$(( $new_argument_length - $argument_length + $READLINE_POINT ))
  READLINE_LINE="$command $new_argument"
}

Ví dụ của bạn, có lẽ bạn muốn thay đổi dòng new_argument thành như thế này:

  new_argument=$(autojump $argument)

Bây giờ ghi đè lên ràng buộc ^ i:

$ bind -x '"\C-i"':'my_awesome_tab_completion_function'

Bây giờ kiểm tra rằng nó hoạt động:

$ cd /ro<TAB>
changes my command to:
$ cd /root

để hoàn thành bình thường vẫn hoạt động, bạn có thể kiểm tra phần $$ bằng cách thực hiện cd $$ ... vv

Nếu bạn gặp sự cố, hãy bật chế độ dài dòng:

$ set -x

Nó sẽ in ra mọi thứ mà chức năng đang làm.

Tôi đã thử nghiệm điều này trên Ubuntu 11 bằng cách sử dụng bash 4.2.8 (1) (mặc định).


Dường như với tôi rằng điều này chỉ hoạt động trên tham số đầu tiên của lệnh và cũng có thể thực hiện những thứ kỳ lạ nếu tab được sử dụng theo những cách không mong muốn (ví dụ sau $$$ hoặc sau tên lệnh), hoặc tôi sai?
harrymc

Chà, nó đang vượt qua $ * vì vậy nó sẽ 'hoạt động' không chỉ là tham số đầu tiên (tôi hoàn toàn không biết autojump nên tôi không chắc liệu nó có thể đưa ra nhiều đối số không). Bạn có thể chuyển đến cuối và chỉ gửi lần cuối để tự động bật hoặc sử dụng READLINE_POINT để xác định vị trí con trỏ nằm trong số các đối số lệnh và chỉ gửi 'từ' đó để tự động bật.
đa thức

Giải pháp của bạn rất thú vị, nhưng bạn phải thừa nhận rằng việc chiếm lấy phím tab là hơi cực. Không có cách nào bạn có thể lường trước tất cả các trường hợp có thể.
harrymc

Cảm ơn câu trả lời của bạn, đó là một giải pháp thay thế tốt đẹp và nó giải quyết phần "cho tất cả các lệnh" trong câu hỏi của tôi. Tôi đồng ý với harrymc rằng nó hơi cực, mặc dù ... Tôi đoán nếu không ai đưa ra giải pháp tốt hơn tôi sẽ thử và xem nó có khả thi không.
Peltier

Tôi cũng đồng ý với harrymc, nhưng đã cố gắng trả lời câu hỏi khi được hỏi. Cá nhân tôi sẽ chỉ liên kết nó với một khóa điều khiển khác như ^ G hoặc một cái gì đó để tôi có thể để tab một mình nhưng vẫn sử dụng chức năng này.
đa thức

1

Thói quen hoàn thành bash có thể được lập trình như một kịch bản shell.

Dưới đây là một ví dụ về một vỏ kịch bản sẽ dần thay thế trong bất kỳ tham số $$[Tab]bằng cách my replacement string, nhưng chỉ dành cho các lệnh cụ thể mycommandvà chỉ nếu tham số là chính xác "$$":

_mycomplete()
{
        if [ ${COMP_WORDS[COMP_CWORD]} == \$\$ ]
        then
                COMPREPLY='my replacement string'
        fi
}
complete -o default -o bashdefault -F _mycomplete mycommand

Bạn phải lấy tập lệnh để bash thông qua source <file-name>(hoặc lệnh dot) để bắt đầu nó hoạt động, và sau đó:

mycommand $$[Tab] -> mycommand my replacement string
mycommand $$$[Tab] -> mycommand $$$ (beep)
mycommand whatever[Tab] -> (will complete "whatever" in the normal bash manner)

Để luôn có nó hoạt động cho một số hoặc tất cả người dùng, hãy bao gồm điều này trong một trong các thói quen hồ sơ bash .

Vấn đề với completelệnh, là nó sẽ chỉ hoạt động đối với một hoặc nhiều tên lệnh, được chỉ định làm tham số. Người ta có thể chỉ cần cung cấp cho nó danh sách tất cả các lệnh mà người dùng có thể sử dụng hoặc trong trường hợp tuyệt vọng mở rộng /bin/* /usr/bin/* ~/bin/*.

Đã thử nghiệm trên CentOS 5.5.

Kịch bản đơn giản này dựa trên các nguồn mà tôi đã liệt kê trong câu trả lời khác của tôi - kịch bản đã bị xóa bởi studio điều hành. Nếu quan tâm, chỉ cần yêu cầu anh ta phục hồi nó.


Cảm ơn câu trả lời của bạn. Câu hỏi của tôi không thực sự về điều đó vì tôi mới có thể, nhưng sẽ không hoàn thành tất cả các lệnh. Tuy nhiên tôi nghĩ rằng nếu giải pháp của đa thức không thể chấp nhận được, tôi sẽ thực hiện một cái gì đó tương tự và cố gắng nhắm mục tiêu các lệnh phổ biến nhất.
Peltier
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.