2016-05-14 71 views
0

我在emacs上使用evil-mode,最近我開始使用eshell,我真的很喜歡我如何離開插入模式並在eshell緩衝區上移動以複製內容或其他好東西,但是當再次進入插入模式時,它會在光標當前位置,我想要的是,當我進入插入模式時,會自動將currsor移動到提示行(最後一行,行尾)。如何覆蓋僅在eshell上的鍵綁定?

我所做的是:

(add-hook 'eshell-mode-hook 
     (lambda() 
     (define-key evil-normal-state-map (kbd "i") (lambda() (interactive) (evil-goto-line) (evil-append-line nil))))) 

然而,在所有其他緩衝區適用這種映射,我只是想將其激活上ESHELL緩衝。

如何定義在eshell中以不同方式工作的鍵綁定?

+0

此鏈接是否有幫助?:http://stackoverflow.com/a/26587651/2112489也許還有一些其他的邪惡本地地圖可以使用。我不使用邪惡,但這是一般的想法 - 即使用本地的東西。 – lawlist

回答

2

目前accepted answer滿足規定的要求,但有兩個主要的侷限性:

  1. 它只有進入插入模式時觸發。 跳至最後一行IAa或任何自定義函數/鍵綁定都需要額外的腳本。
  2. 如果point已經在最後一行(例如編輯當前命令時),則無法在當前位置進入插入模式; i有效地反彈到A

第一個限制可通過首先鉤在eshell-mode然後第二上evil-insert-state-entry被消除。

  1. 如果point尚未最後一行,那麼它是:

    第二個限制可通過設置第一行號和第二基於所述只讀text-propertypoint的位置來解決轉移到point-max(它總是讀寫)。

  2. 否則,如果point上的文本是隻讀的,則將point移動到只讀文本屬性更改的當前行中的位置。

以下代碼否定了接受答案的限制。

(defun move-point-to-writeable-last-line() 
    "Move the point to a non-read-only part of the last line. 
If point is not on the last line, move point to the maximum position 
in the buffer. Otherwise if the point is in read-only text, move the 
point forward out of the read-only sections." 
    (interactive) 
    (let* ((curline (line-number-at-pos)) 
     (endline (line-number-at-pos (point-max)))) 
    (if (= curline endline) 
     (if (not (eobp)) 
      (let (
        ;; Get text-properties at the current location 
        (plist (text-properties-at (point))) 
        ;; Record next change in text-properties 
        (next-change 
        (or (next-property-change (point) (current-buffer)) 
         (point-max)))) 
       ;; If current text is read-only, go to where that property changes 
       (if (plist-get plist 'read-only) 
        (goto-char next-change)))) 
     (goto-char (point-max))))) 

(defun move-point-on-insert-to-writeable-last-line() 
    "Only edit the current command in insert mode." 
    (add-hook 'evil-insert-state-entry-hook 
     'move-point-to-writeable-last-line 
     nil 
     t)) 

(add-hook 'eshell-mode-hook 
     'move-point-on-insert-to-writeable-last-line) 
+0

但是,有沒有辦法使得在shell提示符中間無法進入插入模式?你有沒有在neovim中使用':term'?這正是我想要的東西,它不會讓你修改你不應該的東西。 –

+0

@ZzAntáres我還沒有找到如何檢測點是否在緩衝區的只讀部分。一旦我發現如何去做,我打算更新我的代碼和我對這個問題的回答。 – lafrenierejm

+0

@ZzAntáres[修訂4](https://stackoverflow.com/posts/46937891/revisions)在shell提示符下輸入插入模式的答案地址。 – lafrenierejm

2

感謝@lawlist指着我在正確的方向,解決的辦法是一樣簡單:

;; Insert at prompt only on eshell 
(add-hook 'eshell-mode-hook 
     '(lambda() 
     (define-key evil-normal-state-local-map (kbd "i") (lambda() (interactive) (evil-goto-line) (evil-append-line nil))))) 

謝謝!

+1

你幾乎從不想引用這樣的lambda表單,因爲它不能被字節編譯。'lambda'是自引用(帶有'function'),所以只需刪除'''。 (也並不是最好的想法是將一個lambda表單放在一個hook變量上,因爲更新這些值通常很尷尬,命名函數更容易維護。) – phils

+0

謝謝!不知道!,所以這不是字節編譯? '(add-hook'after-init-hook#'(lambda()(setq gc-cons-threshold 800000)))' –

+0

'(lambda ...)'和'#'(lambda ...)'是等價的,兩者都用'function'引用(分別隱式和顯式)。 ''(lambda ...)'是不同的,用'quote'引用,因此不能被字節編譯。 – phils