Hoàn thành các thư mục giả mạo avfs trong zsh


37

Làm cách nào tôi có thể điều chỉnh hệ thống hoàn thành của zsh để hoàn thành các tập tin giả mạo trong một số trường hợp?

Chính xác hơn, hệ thống tập tin AVFS trưng bày các tài liệu lưu trữ dưới dạng các thư mục bằng cách tạo một thư mục giả mạo của hồi giáo bên cạnh mỗi kho lưu trữ. Theo mặc định, nó sao chép toàn bộ hệ thống phân cấp thư mục dưới điểm gắn kết của nó ~/.avfs. Hơn nữa, bên dưới ~/.avfs, đối với mọi tệp lưu trữ, chẳng hạn như /tmp/foo.zip, ngoài tệp lưu trữ ~/.avfs/tmp/foo.zip, có một thư mục được gọi là ~/.avfs/tmp/foo.zip#hiển thị nội dung của tệp lưu trữ. Tuy nhiên thư mục bổ sung này không xuất hiện trong danh sách ~/.avfs/tmp: nó chỉ tồn tại khi được yêu cầu rõ ràng. (Điều này tương tự như cách một số máy tự động hoạt động.)

mountavfs
cd ~/.avfs/tmp/foo.zip\#

Khi tôi gõ một lệnh như lệnh trên, foo.zip#sẽ không xuất hiện dưới dạng hoàn thành ~/.avfs/tmp/, vì không có thư mục như vậy. Làm thế nào tôi có thể nói với zsh rằng bất cứ khi nào có một tệp có đường dẫn đầy đủ $arckhớp với ~/.avfs/**/*.(tgz|zip), thì nên giả vờ rằng có một thư mục được gọi ${arc}#?

(Lưu ý rằng tôi muốn hoàn thành hoạt động với mọi cuộc gọi đến _fileshoặc _dirs, không chỉ cho cdlệnh. Tôi không muốn phải sao chép mã của _fileshàm, nếu có thể.)

¹ và tất cả các phần còn lại của các phần mở rộng


~ / .Avfs có chứa một "bản sao" của toàn bộ hệ thống tệp không?
ctrl-alt-delor

@richard Có, mọi thứ đều /path/to/foohiển thị như ~/.avfs/path/to/foo.
Gilles 'SO- đừng trở nên xấu xa'

Điều này có thể được cố định dễ dàng hơn trong avfs. Nếu nó trình bày #mục nhập thư mục mặc định cho bất kỳ tệp nào khớp với chuỗi mà nó hỗ trợ hoặc thậm chí ma thuật đã kiểm tra các tệp trong thư mục để biết mục nào cần có #, thì việc hoàn thành sẽ chỉ hoạt động. Tôi đoán sẽ có một cú đánh hiệu suất cho một cái gì đó giống findnhư bây giờ sẽ đi qua các tệp nén.
Matt

Câu trả lời:


1

Một câu trả lời giả xuất hiện không đủ cho câu hỏi giả mạo này; hỗ trợ dựng sẵn zsh cho các thư mục automount hoạt động trên các thư mục ( fake-files dir:names) chứ không phải trên các mẫu tệp trong đó. Điều này rất hữu ích để thêm các tệp được đặt tên cụ thể vào một thư mục, có thể phù hợp automounthoặc sshfshoặc .snapshotthiết lập loại NetApp trong đó thư mục được gắn kết là một tên tĩnh đã biết , ALAS.

autoload -U compinit
compinit
zstyle ':completion:*' fake-files $HOME/.avfs:'ALAS POOR YORICK'

zshall(1)nói "tên" là các chuỗi và các thử nghiệm chỉ ra các ký tự đại diện (ví dụ #hoặc \#hoặc '*(e:"echo hi":)') "không hoạt động" theo nhiều cách khác nhau, vì vậy không có cách nào tôi biết để lén một quả cầu vào phần tên của fake-filestuyên bố. (Việc lướt qua Src/Zle/computil.ccó thể tiết lộ chính xác tên có thể là gì, nhưng đó sẽ là công việc nhiều hơn.) (Ngoài ra, sử dụng các khoảng trống đệ quy ở vị trí thư mục để đặt tên tệp lưu trữ không bay, nhưng một lần nữa, C sẽ lặn để xem có bao nhiêu fake-filescho phép bạn đi với.)

Với compdef, người ta có thể liệt kê các .avfshoàn thành thư mục:

compdef '_files -g $HOME/.avfs/\*' -p \^
function andthehash {
  reply=($REPLY $REPLY\#)
}
compdef "_files -g $HOME/.avfs/'*(+andthehash)'" -p \^

Ngoại trừ điều này không thành công, vì nó sẽ chỉ hiển thị các #tệp khi nó không quan trọng, và do đó không thể hoàn thành trên chúng. (Có những cách sử dụng hiệu quả cho hình thức này, mặc dù không phải trong trường hợp này.)

Sử dụng zstylegiúp bạn gần gũi hơn, với những điều sau đây .zshrc:

autoload -U compinit
compinit

function UnderAVFS {
  local pdir
  [[ -z $1 ]] && return 1
  pdir=$1:a
  [[ ! -d $pdir ]] && pdir=$pdir:h
  [[ ! -d $pdir || $pdir == . ]] && return 1
  while [[ $pdir != / ]]; do
    [[ $pdir == $HOME/.avfs ]] && return 0
    pdir=$pdir:h
  done
  return 1
}

function AVFSExtras {
  if UnderAVFS $REPLY; then
    reply=($REPLY)
    # TODO embiggen list of archive suffixes
    [[ $REPLY == *.(bz2|tbz2) ]] && reply+=($REPLY\#)
  fi
}

# Try to match avfs, otherwise the default pattern. Probably could greatly
# benefit from caching, to avoid hits on UnderAVFS function.
zstyle ':completion:*' file-patterns '*(+AVFSExtras):avfs-files' '%p:all-files'

Tuy nhiên, nó chỉ có thể hoàn thành tối đa \#/bit (trên debian bóp tài với thiết lập avfs mặc định), nhưng không thể vào hệ thống tệp ảo để lưu trữ, do đó, công việc bổ sung sẽ là cần thiết để hoàn thành tab vào kho lưu trữ. Tôi đoán thông qua _call_program ... lshoặc một cái gì đó dọc theo những dòng đó để hoàn thành \#, trừ khi có một cách thanh lịch hơn để zshtin rằng các thư mục không tồn tại.

Tin xấu! Việc hoàn thành không thông qua _path_filescác thư mục giả mạo; Tôi nghi ngờ đây là zsh continbing liên quan. Cả zsh 4. một cái gì đó trên và zsh 5.0.8 đều có vấn đề. Vì vậy, tôi nghi ngờ rằng một bản sửa lỗi hoàn chỉnh sẽ yêu cầu các bản vá lỗi _path_files, hoặc để viết một cái gì đó khác mà hoàn thành trên các thư mục giả mạo này. Một dấu vết gỡ lỗi hoàn thành có thể được tạo ra bằng cách nhập vào ls /root/.avfs/root/sometar.gz\#/và sau đó kết thúc quá trình gõ control-xđó ?, giả sử bindkey -evà đó _complete_debuglà ràng buộc với keycombo, nếu ai đó muốn tìm hiểu tại sao điều này lại thất bại.


0

Trong zsh, bạn có thể sử dụng compctl -Kđể đăng ký chức năng của riêng mình để tạo các tùy chọn hoàn thành. Ví dụ:

compctl -f -c -u -r -K myAVFScompletion "*" -tn

Sau đó, bạn cần xác định chức năng của riêng bạn:

myAVFScompletion () {
    read -c COMMAND ARGS

    # Decide what paths you want to suggest completion for
    # by looking inside the ~/.avfs folder.

    # Place your suggestions into an array:
    reply=( a_path b_path ... )
}

Rõ ràng những điều trên cần thêm một số công việc, nhưng đó là một cái gì đó để bắt đầu.

Một chức năng hoàn thành tùy chỉnh tương tự (nhưng khác nhau) có thể được đăng ký cho bash.

Dưới đây là một ví dụ với việc triển khai cho bash và zsh . (Nó cung cấp hoàn thành các tùy chọn dòng lệnh bằng cách lấy các tùy chọn ra khỏi trang man của lệnh.)

Và đây là một số dự đoán nhanh về những thứ có thể hoạt động bên trong chức năng hoàn thành của bạn:

if [[ -d "$ARGS#" ]]
then reply=( "$ARGS#" )
else reply=
fi

Hoặc có lẽ thế này:

reply=( $(find ~/.avfs -type f -name "*.tgz" -or -name "*.zip" | sed 's+$+#+') )

Chúc may mắn!


Tôi biết làm thế nào để viết một chức năng hoàn thành, cảm ơn bạn rất nhiều. Vấn đề là làm thế nào để sửa đổi cơ chế hoàn thành hiện có cho các tập tin. Lưu ý rằng tôi sử dụng cơ chế hoàn thành mới của Viking, không compctl, tức là tôi muốn thay đổi những gì _files. Câu trả lời của bạn không hữu ích chút nào.
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles Không bắt đầu một cuộc chiến nảy lửa, và có nguy cơ xảy ra sai lầm, ít nhất là anh ta đã cố gắng ... Điều này đã được đặt trong "căn gác" chưa được trả lời 2 năm cộng với ... +1 đặt lại về 0 cho nỗ lực .
Eyoung100

@ eyoung100 Vui lòng không cung cấp +1 cho nỗ lực (không phải nỗ lực đó là rõ ràng ở đây). Nâng cao các câu trả lời không có ích là bất lợi cho trang web.
Gilles 'SO- đừng trở nên xấu xa'
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.