Bash การเติมข้อความอัตโนมัติในโหมดเชลล์ Emacs


93

ใน GNOME Terminal Bash จะทำการเติมข้อความอัตโนมัติอย่างชาญฉลาด ตัวอย่างเช่น

apt-get in<TAB>

กลายเป็น

apt-get install

ในโหมดเชลล์ Emacs การเติมอัตโนมัตินี้จะไม่ทำงานแม้ว่าฉันจะระบุแหล่งที่มาอย่างชัดเจน/etc/bash_completionก็ตาม ตัวอย่างด้านบนยึดเป็นinหรือเติมข้อความอัตโนมัติด้วยชื่อไฟล์ในไดเร็กทอรีปัจจุบันแทนที่จะเป็นapt-getตัวเลือกคำสั่งที่ถูกต้อง สันนิษฐานว่าเป็นเพราะ Emacs ขัดขวางการกดแป้น Tab ฉันจะเปิดใช้งานการเติมข้อความอัตโนมัติอย่างชาญฉลาดได้shell-modeอย่างไร?


สำหรับใครที่ยังใหม่กับ emacs ... มีโหมดเชลล์อื่น ๆใน emacs เช่นeshell-modeที่มีแท็บเสร็จ ข้อมูลเพิ่มเติมที่นี่: masteringemacs.org/articles/2010/11/01/…
รอส

3
การเติมข้อความอัตโนมัติของ eshell ใช้งานได้กับไดเร็กทอรีในเครื่องเท่านั้นหากคุณส่งไปยังเครื่องอื่นคุณจะสูญเสียความสามารถนี้ไปในทันที
hajovonta

คำตอบ:


93

ฉันรู้ว่าคำถามนี้มีอายุสามขวบ แต่เป็นสิ่งที่ฉันสนใจที่จะแก้ไข การค้นหาเว็บนำฉันไปสู่ส่วนหนึ่งของ elisp ที่ทำให้ Emacs ใช้ bash เพื่อทำให้เสร็จสมบูรณ์ในโหมดเชลล์ มันเหมาะกับฉันไม่ว่าในกรณีใด ๆ

ตรวจสอบออกที่https://github.com/szermatt/emacs-bash-completion


6
+1 สำหรับการกล้าที่จะตอบคำถามเด็กสามขวบ แต่ยังคงมีความเกี่ยวข้องทั้งหมด ขอบคุณ!
djhaskin987

3
สิ่งนี้มีอยู่แล้วใน melpa melpa.org/#/bash-completionการติดตั้งใช้งานM-x package-list-packagesง่าย แต่ในที่สุดมันก็ไม่ได้ผลสำหรับฉันฉันไม่รู้ว่าทำไมมันอาจเป็น emac ของฉัน (24.3.1) หรือ bash (4.3.30) รุ่น เอกสารระบุว่า "bash-complete.el ค่อนข้างอ่อนไหวต่อระบบปฏิบัติการและเวอร์ชัน BASH ... " จากนั้นเป็นรายการที่ไม่มีเวอร์ชันของฉัน
boclodoa

น่าเสียดายที่ปัญหาที่รอดำเนินการ# 6ดูเหมือนว่าจะไม่เป็นประโยชน์สำหรับการครอบตัดเครื่องมือ CLI ในปัจจุบัน
Jesse Glick

ปัญหาที่ 6 ถูกปิดลงเนื่องจาก <อย่างน้อยส่วนใหญ่คงที่ / ตัวอย่างของมันไม่จำเป็นต้องใช้งานได้>
Matthew Elvey

21

ในเปลือก emacs มันเป็น emac ที่ทำการเติมข้อความอัตโนมัติไม่ใช่ทุบตี หากเชลล์และอีแมคไม่ตรงกัน (เช่นโดยใช้ pushd, popd หรือฟังก์ชันผู้ใช้ bash ที่เปลี่ยนไดเร็กทอรีปัจจุบันของเชลล์) การเติมอัตโนมัติจะหยุดทำงาน

ในการแก้ไขปัญหานี้เพียงพิมพ์ 'dirs' ลงในเชลล์และสิ่งต่างๆจะกลับมาซิงค์กัน

ฉันยังมีสิ่งต่อไปนี้ใน. emac ของฉัน:

(global-set-key "\M-\r" 'shell-resync-dirs)

จากนั้นเพียงแค่กดปุ่ม Esc-return จะซิงค์การเติมข้อความอัตโนมัติ


9
นี่เป็นคำตอบที่ดีสำหรับคำถามอื่น!
Chris Conway

ขอบคุณ. ฉันใช้ autojump และนั่นเป็นปัญหาว่าทำไม dirs ถึงไม่ซิงค์กัน
Plankalkül

Chris Conway ใช่สำหรับคนนี้: emacs.stackexchange.com/questions/30550/… :-)
unhammer

15

ฉันไม่รู้คำตอบสำหรับเรื่องนี้ แต่สาเหตุที่มันไม่ได้ผลตามที่คุณคาดหวังอาจเป็นเพราะความสมบูรณ์ใน emacs เชลล์ถูกจัดการโดย emacs ภายใน (โดยฟังก์ชัน comint-dynamic-complete) และไม่มีฟังก์ชันการเติมเต็มอัจฉริยะในตัว

ฉันกลัวว่ามันจะไม่ใช่เรื่องง่ายที่จะแก้ไข

แก้ไข: ข้อเสนอแนะของ njsf ในการใช้โหมดระยะยาวอาจจะดีเท่าที่จะเป็นไปได้ เริ่มต้นด้วย

ระยะ Mx
มันรวมอยู่ในการแจกจ่าย emacs มาตรฐาน (และใน emacs21-common หรือ emacs22-common บน Ubuntu และ Debian เป็นอย่างน้อย)


2
M-x termแท็บเสร็จก็ยิ่งแย่ลงด้วย
mcandre

7

โปรดพิจารณาโหมดอื่นM-x termเช่นฉันทำสิ่งนี้เมื่อเกิดปัญหาในปี 2011 ฉันพยายามรวบรวมความพยายามทั้งหมดของ Inet ในเวลานั้นเพื่อให้เชลล์ทำงานร่วมกับ Bash เสร็จสิ้นรวมถึงคำถามนี้ด้วย แต่ตั้งแต่ค้นพบทางเลือกอื่นต่อหน้าterm-modeฉันก็ไม่อยากลองeshellด้วยซ้ำ

เป็นโปรแกรมจำลองเทอร์มินัลแบบเต็มดังนั้นคุณสามารถเรียกใช้โปรแกรมโต้ตอบภายในเช่นผู้บัญชาการเที่ยงคืน หรือเปลี่ยนไปใช้การzshทำให้เสร็จสมบูรณ์เพื่อที่คุณจะได้ไม่เสียเวลาในการกำหนดค่า Emacs

คุณจะได้รับ TAB เสร็จสิ้นใน bash ฟรี แต่สิ่งที่สำคัญกว่าคุณจะได้รับพลัง Readline อย่างเต็มที่เช่นการค้นหาคำสั่งที่เพิ่มขึ้นหรือนำหน้า เพื่อให้การตั้งค่านี้การตรวจสอบที่สะดวกมากขึ้นฉัน.inputrc , .bashrc , .emacs

ส่วนสำคัญของ.inputrc:

# I like this!
set editing-mode emacs

# Don't strip characters to 7 bits when reading.
set input-meta on

# Allow iso-latin1 characters to be inserted rather than converted to
# prefix-meta sequences.
set convert-meta off

# Display characters with the eighth bit set directly rather than as
# meta-prefixed characters.
set output-meta on

# Ignore hidden files.
set match-hidden-files off

# Ignore case (on/off).
set completion-ignore-case on

set completion-query-items 100

# First tab suggests ambiguous variants.
set show-all-if-ambiguous on

# Replace common prefix with ...
set completion-prefix-display-length 1

set skip-completed-text off

# If set to 'on', completed directory names have a slash appended. The default is 'on'.
set mark-directories on
set mark-symlinked-directories on

# If set to 'on', a character denoting a file's type is appended to the
# filename when listing possible completions. The default is 'off'.
set visible-stats on

set horizontal-scroll-mode off

$if Bash
"\C-x\C-e": edit-and-execute-command
$endif

# Define my favorite Emacs key bindings.
"\C-@": set-mark
"\C-w": kill-region
"\M-w": copy-region-as-kill

# Ctrl+Left/Right to move by whole words.
"\e[1;5C": forward-word
"\e[1;5D": backward-word
# Same with Shift pressed.
"\e[1;6C": forward-word
"\e[1;6D": backward-word

# Ctrl+Backspace/Delete to delete whole words.
"\e[3;5~": kill-word
"\C-_": backward-kill-word

# UP/DOWN filter history by typed string as prefix.
"\e[A": history-search-backward
"\C-p": history-search-backward
"\eOA": history-search-backward
"\e[B": history-search-forward
"\C-n": history-search-forward
"\eOB": history-search-forward

# Bind 'Shift+TAB' to complete as in Python TAB was need for another purpose.
"\e[Z": complete
# Cycling possible completion forward and backward in place.
"\e[1;3C": menu-complete                    # M-Right
"\e[1;3D": menu-complete-backward           # M-Left
"\e[1;5I": menu-complete                    # C-TAB

.bashrc(ใช่! มีคำย่อใน Bash จากคำใดก็ได้ใน~/.bash_history):

set -o emacs

if [[ $- == *i* ]]; then
  bind '"\e/": dabbrev-expand'
  bind '"\ee": edit-and-execute-command'
fi

.emacs เพื่อให้การนำทางสะดวกสบายในบัฟเฟอร์ระยะ:

(setq term-buffer-maximum-size (lsh 1 14))

(eval-after-load 'term
  '(progn
    (defun my-term-send-delete-word-forward () (interactive) (term-send-raw-string "\ed"))
    (defun my-term-send-delete-word-backward () (interactive) (term-send-raw-string "\e\C-h"))
    (define-key term-raw-map [C-delete] 'my-term-send-delete-word-forward)
    (define-key term-raw-map [C-backspace] 'my-term-send-delete-word-backward)
    (defun my-term-send-forward-word () (interactive) (term-send-raw-string "\ef"))
    (defun my-term-send-backward-word () (interactive) (term-send-raw-string "\eb"))
    (define-key term-raw-map [C-left] 'my-term-send-backward-word)
    (define-key term-raw-map [C-right] 'my-term-send-forward-word)
    (defun my-term-send-m-right () (interactive) (term-send-raw-string "\e[1;3C"))
    (defun my-term-send-m-left () (interactive) (term-send-raw-string "\e[1;3D"))
    (define-key term-raw-map [M-right] 'my-term-send-m-right)
    (define-key term-raw-map [M-left] 'my-term-send-m-left)
    ))

(defun my-term-mode-hook ()
  (goto-address-mode 1))
(add-hook 'term-mode-hook #'my-term-mode-hook)

ตามคำสั่งC-x oทั่วไปที่ไม่ทำงานในโหมดจำลองเทอร์มินัลฉันขยายคีย์แมปด้วย:

(unless
    (ignore-errors
      (require 'ido)
      (ido-mode 1)
      (global-set-key [?\s-d] #'ido-dired)
      (global-set-key [?\s-f] #'ido-find-file)
      t)
  (global-set-key [?\s-d] #'dired)
  (global-set-key [?\s-f] #'find-file))

(defun my--kill-this-buffer-maybe-switch-to-next ()
  "Kill current buffer. Switch to next buffer if previous command
was switching to next buffer or this command itself allowing
sequential closing of uninteresting buffers."
  (interactive)
  (let ( (cmd last-command) )
    (kill-buffer (current-buffer))
    (when (memq cmd (list 'next-buffer this-command))
      (next-buffer))))
(global-set-key [s-delete] 'my--kill-this-buffer-maybe-switch-to-next)
(defun my--backward-other-window ()
  (interactive)
  (other-window -1))
(global-set-key [s-up] #'my--backward-other-window)
(global-set-key [s-down] #'other-window)
(global-set-key [s-tab] 'other-window)

โปรดทราบว่าฉันใช้superคีย์ดังนั้นterm-raw-mapและอาจเป็นไปได้ว่าคีย์แมปอื่น ๆ จะไม่ขัดแย้งกับการผูกคีย์ของฉัน เพื่อสร้างsuperคีย์จากด้านซ้ายWinคีย์ฉันใช้.xmodmaprc:

! To load this config run:
!   $ xmodmap .xmodmaprc

! Win key.
clear mod3
clear mod4

keycode 133 = Super_L
keycode 134 = Hyper_R
add mod3 = Super_L
add mod4 = Hyper_R

คุณควรจำ 2 คำสั่ง: C-c C-j - เพื่อเข้าสู่โหมดแก้ไข Emacs ปกติ (สำหรับการคัดลอกหรือ grepping ในข้อความบัฟเฟอร์) C-c C-k- เพื่อกลับสู่โหมดจำลองเทอร์มินัล

การเลือกเมาส์และใช้Shift-Insertงานxtermได้


1
ขอบคุณนี่คือทองคำ! โดยเฉพาะ.inputrcส่วน!
cmantas

6

เช่นเดียวกับที่ Matli กล่าวไว้มันไม่ใช่เรื่องง่ายเนื่องจาก bash เริ่มต้นด้วย --noediting และ TAB จะผูกพันกับ comint-dynamic-complete

อาจเป็นไปได้ว่า TAB สามารถ rebind TAB เป็นคำสั่งแทรกตัวเองใน shell-comand-hook ด้วย local-set-key และทำให้โหมดเชลล์ไม่เริ่มต้นด้วย --noediting by Mx ปรับแต่งตัวแปร RET Explicit-bash-args แต่ฉันสงสัยว่า มันจะไม่เหมาะกับการแก้ไขอื่น ๆ ทั้งหมด

คุณอาจต้องการลองใช้ term-mode แต่ก็มีปัญหาอีกชุดหนึ่งเนื่องจากการเชื่อมโยงคีย์ปกติอื่น ๆ บางส่วนถูกครอบงำโดย term-mode

แก้ไข: โดยการเสนอราคาปกติอื่น ๆ ถูกครอบงำโดยโหมดคำฉันหมายถึงทั้งหมดยกเว้น Cc ซึ่งกลายเป็น Escape เพื่อให้สามารถสลับบัฟเฟอร์ได้ ดังนั้นแทนที่จะใช้ Cx k เพื่อฆ่าบัฟเฟอร์คุณต้อง Cc Cx k หรือเพื่อเปลี่ยนเป็นบัฟเฟอร์อื่น 'Cc Cx o' หรือ 'Cc Cx 2'


self-insert-command ไม่ใช่มันแทรกอักขระ TAB แทนที่จะส่งผ่าน TAB กดแป้นไปที่ Bash
Chris Conway

ฉันไม่มีคำสั่ง term-mode และคิดไม่ออกว่าจะหาจากไหน
Chris Conway

2

ฉันรู้ว่าโพสต์นี้มีอายุมากกว่า 11 ปีแล้ว แต่ฉันได้สร้างฟังก์ชันเพื่อให้เสร็จสิ้นเชลล์ดั้งเดิมใน Emacs เพียงแค่ส่งคีย์แท็บไปยังกระบวนการพื้นฐานและสกัดกั้นผลลัพธ์ดังนั้นจึงเหมือนกับที่คุณได้รับในเชลล์

https://github.com/CeleritasCewellery/emacs-native-shell-complete


ว้าว! สุดยอด! (ความประทับใจครั้งแรกตามตัวอย่าง)
Matthew Elvey

1

ฉันใช้ Prelude และเมื่อฉันกด Meta + Tab มันก็เสร็จสมบูรณ์สำหรับฉัน

นอกจากนี้ Ctrl + i ดูเหมือนจะทำสิ่งเดียวกัน



-2

ฉันไม่อ้างว่าเป็นผู้เชี่ยวชาญด้าน emacs แต่สิ่งนี้จะช่วยแก้ปัญหาของคุณได้:

สร้าง: ~ / .emacs

เพิ่มเข้าไป:

(ต้องการ 'เชลล์คำสั่ง) (เชลล์คำสั่งเสร็จสมบูรณ์โหมด)

Emacs เข้ายึดครองเชลล์ดังนั้นการตั้งค่า BASH จึงไม่เกิดขึ้น การดำเนินการนี้จะตั้งค่าการสิ้นสุดอัตโนมัติสำหรับ EMACS เอง


ไม่วิธีนี้ไม่สามารถแก้ปัญหาได้ ใช้งานได้กับเชลล์คำสั่งเท่านั้นไม่ใช่ในโหมดเชลล์ นอกจากนี้ยังไม่เปิดใช้งานการเติมข้อมูลอัจฉริยะที่ร้องขอในคำถาม (จะกรอกเฉพาะคำสั่งและชื่อไฟล์)
matli

1
shell-command-complete-mode ทำให้ชื่อไฟล์สมบูรณ์และเปิดใช้งานโดยค่าเริ่มต้น ฉันต้องการคุณสมบัติการทำให้สมบูรณ์ของ Bash (ซึ่งสามารถขยายได้เช่นคำสั่งย่อยสำหรับ apt-get และ svn)
Chris Conway
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.