emacsのブラウザスタイルの「タブ」


22

firefoxのようなタブが欲しいのですが、emacs用です。

私はこれを見つけました:http : //emacswiki.org/emacs/TabBarMode

しかし、現在開いているバッファーを表示するバーを各バッファー(Emacs用語ではウィンドウ)に追加するだけです。

タブに複数のバッファー(Emacs teminologyのウィンドウ)を保持できるようにしたいので、必要に応じて分割できます。つまり、各タブは(ウィンドウの状態)に対応する必要がありますwindow-state-get

タスク用のタブ、コード用のタブ、ウェブ閲覧用のタブなどがあります。

これは可能ですか?これを行うためにタブバーを調整できますか?

[編集2]
この質問は、私が予想したよりも多くの注目を集めました。解決策があるように見えますが、少しの調査と調整が必要なものです。今週/来週は私にとって少し忙しいですが、答えを解析し、機能する何かを構築しようとします。そして、この質問を編集して、発見事項を反映させます。しばらくお待ちください=)

[編集]
似たようなもの:https :
//stackoverflow.com/questions/24157754/make-frames-in-emacs-gui-behaves-like-frames-in-terminal

また、単一のGUIセッションで複数のフレームで解決します。


2
「タブに複数のバッファを保持できるようにしたいのですが、必要に応じて分割できます。」複数のウィンドウを意味しますか?
マラバルバ

1
もっとダイナミックなタブが欲しいみたいです。それらを作成してから、それらにウィンドウを設定します。つまり、タブをフレームにしたいのです。次に、新しいタブ、新しいフレーム。各タブ/フレーム内で、目的のウィンドウ/(バッファ)を開くことができました。これは実行可能ですか?(
つまり

1
特定のウィンドウに関連付けられた変数がありますが、それについて話しているスレッドを見てから1、2か月が経ち、それがオフハンドと呼ばれるものがわかりません。リストがフレームに関連付けられたバッファを保持し、そのリストがフレームパラメータに組み込まれているframe-bufsに似たシステムを使用することに興味があるかもしれません。特定のウィンドウに関連付けられた変数を使用してリストにし、リストにバッファを追加/削除できます。そのリストは、タブバーで使用されるバッファグループになります。これはすべて理論的ですが、うまくいくと思います。
法律家

1
私はあなたがを参照するかもしれないと思う:stackoverflow.com/questions/24157754/... が、そのポストは、固体答えを持っていないようです: - /
レオUfimtsev

1
elscreenパッケージをご覧になることをお勧めします。
-blarghmatey

回答:


8

グループでバッファを分割する

タブバーで可能です。グループ内のグループバッファにルールを追加できます。基本的なスニペットは次のとおりです。

(defun tabbar-buffer-groups ()
  "Returns the list of group names the current buffer belongs to."
  (list
   (cond

    ;; ADD RULES TO SPLIT BUFFERS IN GROUPS HERE!

    ;; if buffer is not grouped by the rules you would add above 
    ;; put it in the "General" group:
    (t
       "General"
     ))))

ルールの例:

  1. バッファ名のリスト:
    ((member (buffer-name)
             '("*scratch*" "*Messages*" "*Help*"))
     "Common" ;; this is a group name
     )
  1. 共通バッファについては、名前がスターで始まる各バッファを「共通」に配置することを好みます。これは、このルールのバッファを作成する例を示します。
    ((string-equal "*" (substring (buffer-name) 0 1))
     "Common"
     )
  1. メジャーモードでバッファをグループ化する例を次に示します。
    ((memq major-mode
           '(org-mode text-mode rst-mode))
     "Text"
     )
  1. 次に、派生元のモードに基づいてバッファをグループ化する例を示します。
    ((or (get-buffer-process (current-buffer))
         ;; Check if the major mode derives from `comint-mode' or
         ;; `compilation-mode'.
         (tabbar-buffer-mode-derived-p
          major-mode '(comint-mode compilation-mode)))
     "Process"
     )
  1. 正規表現でタブをグループ化する例を次に示します。
    ((string-match "^__" (buffer-name))
     "Templates"
     )
  1. メジャーモードでバッファをグループ化します。
    (if (and (stringp mode-name)
                  ;; Take care of preserving the match-data because this
                  ;; function is called when updating the header line.
                  (save-match-data (string-match "[^ ]" mode-name)))
             mode-name
           (symbol-name major-mode))

ルールを作成したら、タブバーのタブ行で+または-を押してグループを切り替えたり、◀と▶を押してバッファーを切り替えたりできます。または、次のdefunをバインドするだけです。

tabbar-forward
tabbar-backward
tabbar-forward-group
tabbar-backward-group

キーボードでタブとタブグループ間を移動します。

個人的にタブをグループ化して、開いているものを確認しますが、でナビゲートしますido-switch-buffer

ルールセットを切り替える

また、バッファグループ化ルールの異なるセットを定義し、これらを切り替えることができます。以下は、2組のバッファグループ化ルールを切り替える例です。

;; tab-groups!
(setq tbbr-md "common")
(defun toggle-tabbar-mode ()
  "Toggles tabbar modes - all buffers vs. defined in the `tabbar-buffer-groups'."
  (interactive)
  (if (string= tbbr-md "groups")
      (progn ;; then
        (setq tabbar-buffer-groups-function 'tabbar-buffer-groups-common)
        (setq tbbr-md "common"))
    (progn ;; else
      (setq tabbar-buffer-groups-function 'tabbar-buffer-groups)
      (setq tbbr-md "groups"))))
;; by default - all tabs:
(setq tabbar-buffer-groups-function 'tabbar-buffer-groups-common)

これによりtabbar-buffer-groups-commontabbar-buffer-groupsタブのグループ化解除と切り替えが行われます。

タブバーバッファーを名前で並べ替える

タブバーバッファを名前で並べ替えることは有益だと思います。取得方法は次のとおりです。

(defun tabbar-add-tab (tabset object &optional append_ignored)
  "Add to TABSET a tab with value OBJECT if there isn't one there yet.
If the tab is added, it is added at the beginning of the tab list,
unless the optional argument APPEND is non-nil, in which case it is
added at the end."
  (let ((tabs (tabbar-tabs tabset)))
    (if (tabbar-get-tab object tabset)
        tabs
      (let ((tab (tabbar-make-tab object tabset)))
        (tabbar-set-template tabset nil)
        (set tabset (sort (cons tab tabs)
                          (lambda (a b) (string< (buffer-name (car a)) (buffer-name (car b))))))))))

詳細な回答ありがとうございます。私は上記を試してみようとし、〜最終的にお知らせします:)
レオUfimtsev

しかし、OPは「ウィンドウごとに1つのタブバー」を必要とせず、フレームごとに1つのタブバーを必要とし、タブバーの各タブはバッファーではなく「ウィンドウ構成」(つまり、複数のウィンドウ)を表す必要があるため、バッファーのグループ化は問題になりません。
ステファン

6

属性:フレームごとのバッファのグループ化は、概念の直接実装であり、ライブラリframe-bufsでAlp Akerが開発/作成したコードの一部を選択します:https : //github.com/alpaker/Frame-Bufs

以下は、でtabbar.elタブ/バッファを追加C-c C-aまたは削除することにより、ライブラリおよびグループタブ/バッファをフレームごとに動的に使用する方法の例ですC-c C-n。現在のフレームに関連付けられている(つまり"A")、および現在のフレームに関連付けられていない(つまり)の2つのグループしかありません"N"。グループはフレームローカルです。つまり、各フレームには独自のグループ化が可能です。カスタムグループはでリセットできますC-c C-r。で関連グループと非関連グループを切り替えますC-tab。で現在のグループの次のタブ/バッファに切り替えますM-s-right。で現在のグループの前のタブ/バッファに切り替えますM-s-left

タブとバッファは、my-add-bufferおよびを使用してプログラムで追加または削除できますmy-remove-buffer。選択したフレームに特定のバッファを開く方法の例については、題した関連スレッドを参照してください、それが開く前に、ファイルを傍受する方法を、どのフレームを決める/programming//a/18371427/2112489 機能はmy-add-bufferする必要がありますユーザーがその機能を実装することを選択した場合、上記のリンクのコードの適切な場所に組み込まれます。

ユーザーはmode-line-format、次のスニペットを組み込むことにより、モード行に現在のタブグループの名前を表示 するカスタムのエントリを作成できます(:eval (when tabbar-mode (format "%s" (tabbar-current-tabset t)))) 。ただし、モード行の詳細なカスタマイズは、この例の範囲外です。

この機能tabbar-add-tabは、タブ/バッファをアルファベット順にするように修正されました。

機能tabbar-line-tabは、状況に応じて4つの異なる顔を提供するように変更されました。タブ/バッファがフレームに関連付けられていて、選択されている場合、tabbar-selected-associated面を使用します。タブ/バッファがフレームに関連付けられていて、選択されていない場合は、tabbar-unselected-associated顔を使用します。タブ/バッファがフレームに関連付けられておらず、選択されている場合、tabbar-selected-unassociated面を使用します。タブ/バッファがフレームに関連付けられておらず、選択されていない場合、tabbar-unselected-unassociated面を使用します。

;; Download tabbar version 2.0.1 by David Ponce:
;;   https://marmalade-repo.org/packages/tabbar
;; or use package-install for marmalade repositories.

;; Place tabbar-2.0.1.el in the `load-path` -- it is okay to rename it to tabbar.el
;; or add the directory (where `tabbar.el` resides) to the `load-path`.
;; EXAMPLE:  (setq load-path (append '("/Users/HOME/.emacs.d/lisp/") load-path))

(require 'tabbar)

(setq tabbar-cycle-scope 'tabs)

(remove-hook 'kill-buffer-hook 'tabbar-buffer-track-killed)

(defun my-buffer-groups ()
  "Function that gives the group names the current buffer belongs to.
It must return a list of group names, or nil if the buffer has no
group.  Notice that it is better that a buffer belongs to one group."
  (list
    (cond
      ((memq (current-buffer) (my-buffer-list (selected-frame)))
        "A")
      (t
        "N"))))

(setq tabbar-buffer-groups-function 'my-buffer-groups) ;; 'tabbar-buffer-groups

;; redefine tabbar-add-tab so that it alphabetizes / sorts the tabs
(defun tabbar-add-tab (tabset object &optional append)
  "Add to TABSET a tab with value OBJECT if there isn't one there yet.
If the tab is added, it is added at the beginning of the tab list,
unless the optional argument APPEND is non-nil, in which case it is
added at the end."
  (let ((tabs (tabbar-tabs tabset)))
    (if (tabbar-get-tab object tabset)
        tabs
      (let* ((tab (tabbar-make-tab object tabset))
             (tentative-new-tabset
               (if append
                 (append tabs (list tab))
                 (cons tab tabs)))
             (new-tabset
               (sort
                  tentative-new-tabset
                  #'(lambda (e1 e2)
                     (string-lessp
                       (format "%s" (car e1)) (format "%s" (car e2)))))))
        (tabbar-set-template tabset nil)
        (set tabset new-tabset)))))

;; AUTHOR:  Alp Aker -- https://github.com/alpaker/Frame-Bufs
;; @lawlist extracted/revised the function(ality) from said library.
(defun my-buffer-list (frame)
  ;; Remove dead buffers.
  (set-frame-parameter frame 'frame-bufs-buffer-list
    (delq nil (mapcar #'(lambda (x) (if (buffer-live-p x) x))
      (frame-parameter frame 'frame-bufs-buffer-list))))
  ;; Return the associated-buffer list.
  (frame-parameter frame 'frame-bufs-buffer-list))

(defun my-kill-buffer-fn ()
"This function is attached to a buffer-local `kill-buffer-hook'."
  (let ((frame (selected-frame))
        (current-buffer (current-buffer)))
    (when (memq current-buffer (my-buffer-list frame))
      (my-remove-buffer current-buffer frame))))

;; AUTHOR:  Alp Aker -- https://github.com/alpaker/Frame-Bufs
;; @lawlist extracted/revised the function(ality) from said library.
(defun my-add-buffer (&optional buf frame)
"Add BUF to FRAME's associated-buffer list if not already present."
(interactive)
  (let* ((buf (if buf buf (current-buffer)))
         (frame (if frame frame (selected-frame)))
         (associated-bufs (frame-parameter frame 'frame-bufs-buffer-list)))
    (unless (bufferp buf)
      (signal 'wrong-type-argument (list 'bufferp buf)))
    (unless (memq buf associated-bufs)
      (set-frame-parameter frame 'frame-bufs-buffer-list (cons buf associated-bufs)))
    (with-current-buffer buf
      (add-hook 'kill-buffer-hook 'my-kill-buffer-fn 'append 'local))
    (when tabbar-mode (tabbar-display-update))))

;; AUTHOR:  Alp Aker -- https://github.com/alpaker/Frame-Bufs
;; @lawlist extracted/revised the function(ality) from said library.
(defun my-remove-buffer (&optional buf frame)
"Remove BUF from FRAME's associated-buffer list."
(interactive)
  (let ((buf (if buf buf (current-buffer)))
        (frame (if frame frame (selected-frame))))
    (set-frame-parameter frame 'frame-bufs-buffer-list
      (delq buf (frame-parameter frame 'frame-bufs-buffer-list)))
    (when tabbar-mode (tabbar-display-update))))

;; AUTHOR:  Alp Aker -- https://github.com/alpaker/Frame-Bufs
;; @lawlist extracted/revised the function(ality) from said library.
(defun my-buffer-list-reset ()
    "Wipe the entire slate clean for the selected frame."
  (interactive)
    (modify-frame-parameters (selected-frame) (list (cons 'frame-bufs-buffer-list nil)))
    (when tabbar-mode (tabbar-display-update)))

(defun my-switch-tab-group ()
"Switch between tab group `A` and `N`."
(interactive)
  (let ((current-group (format "%s" (tabbar-current-tabset t)))
        (tab-buffer-list (mapcar
            #'(lambda (b)
                (with-current-buffer b
                  (list (current-buffer)
                        (buffer-name)
                        (funcall tabbar-buffer-groups-function))))
                 (funcall tabbar-buffer-list-function))))
    (catch 'done
      (mapc
        #'(lambda (group)
            (when (not (equal current-group
                          (format "%s" (car (car (cdr (cdr group)))))))
              (throw 'done (switch-to-buffer (car (cdr group))))))
        tab-buffer-list))))

(defface tabbar-selected-associated
  '((t :background "black" :foreground "yellow" :box (:line-width 2 :color "yellow")))
  "Face used for the selected tab -- associated with the `frame-bufs-buffer-list`."
  :group 'tabbar)

(defface tabbar-unselected-associated
  '((t :background "black" :foreground "white" :box (:line-width 2 :color "white")))
  "Face used for unselected tabs  -- associated with the `frame-bufs-buffer-list`."
  :group 'tabbar)

(defface tabbar-selected-unassociated
  '((t :background "black" :foreground "white" :box (:line-width 2 :color "firebrick")))
  "Face used for the selected tab -- UNassociated with the `frame-bufs-buffer-list`."
  :group 'tabbar)

(defface tabbar-unselected-unassociated
  '((t :background "black" :foreground "white" :box (:line-width 2 :color "blue")))
  "Face used for unselected tabs -- UNassociated with the `frame-bufs-buffer-list`."
  :group 'tabbar)

(setq tabbar-background-color "black")

(defsubst tabbar-line-tab (tab)
  "Return the display representation of tab TAB.
That is, a propertized string used as an `header-line-format' template
element.
Call `tabbar-tab-label-function' to obtain a label for TAB."
  (concat
    (propertize
      (if tabbar-tab-label-function
          (funcall tabbar-tab-label-function tab)
        tab)
      'tabbar-tab tab
      'local-map (tabbar-make-tab-keymap tab)
      'help-echo 'tabbar-help-on-tab
      'mouse-face 'tabbar-highlight
      'face
        (cond
          ((and
              (tabbar-selected-p tab (tabbar-current-tabset))
              (memq (current-buffer) (my-buffer-list (selected-frame))))
            'tabbar-selected-associated)
          ((and
              (not (tabbar-selected-p tab (tabbar-current-tabset)))
              (memq (current-buffer) (my-buffer-list (selected-frame))))
            'tabbar-unselected-associated)
          ((and
              (tabbar-selected-p tab (tabbar-current-tabset))
              (not (memq (current-buffer) (my-buffer-list (selected-frame)))))
            'tabbar-selected-unassociated)
          ((and
              (not (tabbar-selected-p tab (tabbar-current-tabset)))
              (not (memq (current-buffer) (my-buffer-list (selected-frame)))))
            'tabbar-unselected-unassociated))
      'pointer 'hand)
    tabbar-separator-value))

(define-key global-map "\C-c\C-r" 'my-buffer-list-reset)

(define-key global-map "\C-c\C-a" 'my-add-buffer)

(define-key global-map "\C-c\C-n" 'my-remove-buffer)

(define-key global-map (kbd "<M-s-right>") 'tabbar-forward)

(define-key global-map (kbd "<M-s-left>") 'tabbar-backward)

(define-key global-map [C-tab] 'my-switch-tab-group)

(tabbar-mode 1)

次のスクリーンショットは、2つの可能なバッファ/タブのグループ化を示しています。(1)左側は、SYSTEM[黄色と白のタブ] という名前のフレームに関連付けられたバッファ/タブのグループです。モードライン; (2)右側は、[青と赤のタブ] という名前のフレームに関連付けられていないバッファ/タブのグループSYSTEMで、モードラインに大文字の「N」が示されています。

例


しかし、OPは「ウィンドウごとに1つのタブバー」を必要とせず、フレームごとに1つのタブバーを必要とし、タブバーの各タブはバッファーではなく「ウィンドウ構成」(つまり、複数のウィンドウ)を表す必要があります
ステファン

5

実際にはバッファをグループ化しませんが、elscreenをチェックアウトすることを検討してください。

これは、ウィンドウをグループ化し、すばやく移動できる複数のレイアウト(タブ)へのアクセスを提供します。私のワークフローでは、しばしば1つの画面にRubyコードと関連するテストがあり、todoとOrgのメモは別の画面にあり、SQLクエリを作成するためのスクラッチバッファーは3番目にあります。これにより、各画面が同じバッファプールを使用している場合でも、タスクとプロジェクトを簡単に切り替えることができます。


3

私のプラグイン、centaur-tabsはどうですか?多くの設定オプションがあり、本当に機能的で、Kaolin Themesのような非常に人気のあるテーマでサポートされており、全体的に見た目も美観も優れたパッケージです(ユーザーのフィードバックによる)。MELPAで利用でき、次のようになります。

ここに画像の説明を入力してください


これはさらに別の「各タブがバッファを表し、各ウィンドウに独自のタブバーがある」非解決策のようです。
ステファン

タブ名の代わりにタブグループを表示するカスタマイズを追加したため、関数でルールを確立します(つまり、あるグループのグループelispとlisp、別のグループのグループcとc ++など)およびそれらのグループが表示されるタブに追加します。
エマニュエルブストス

フレームごとに(ウィンドウごとではなく)タブバーが1つ存在し、各タブがウィンドウ構成を表しているという質問にはまだ答えていません。
ステファン

わかりませんでした。調査して取り組みます!
エマニュエルブストス

0

価値があるもののために、ここに私の設定があります。機能:

  • (タブ上のマウス操作mouse-2の近くに、ブラウザのようにmouse-3 のように、新しいEmacsのウィンドウで開いているポップするI3
  • キーボードコントロール(M-leftおよびTMux / Screenのような右スイッチタブ)
  • 色(「Moeテーマ/ moe-dark」構成に一致)
  • グループ化(現在、Emacs *buffers*と「通常」)
  • 自動更新(use-package使用

TabBar

(use-package tabbar
  :ensure t
  :bind
  ("<M-left>" . tabbar-backward)
  ("<M-right>" . tabbar-forward)

  :config
  (set-face-attribute
   'tabbar-button nil
   :box '(:line-width 1 :color "gray19"))

  (set-face-attribute
   'tabbar-selected nil
   :foreground "orange"
   :background "gray19"
   :box '(:line-width 1 :color "gray19"))

  (set-face-attribute
   'tabbar-unselected nil
   :foreground "gray75"
   :background "gray25"
   :box '(:line-width 1 :color "gray19"))

  (set-face-attribute
   'tabbar-highlight nil
   :foreground "black"
   :background "orange"
   :underline nil
   :box '(:line-width 1 :color "gray19" :style nil))

  (set-face-attribute
   'tabbar-modified nil
   :foreground "orange red"
   :background "gray25"
   :box '(:line-width 1 :color "gray19"))

  (set-face-attribute
   'tabbar-selected-modified nil
   :foreground "orange red"
   :background "gray19"
   :box '(:line-width 1 :color "gray19"))

  (custom-set-variables
   '(tabbar-separator (quote (0.2))))

  (defun tabbar-buffer-tab-label (tab)
    "Return a label for TAB.
  That is, a string used to represent it on the tab bar."
    (let ((label  (if tabbar--buffer-show-groups
                      (format " [%s] " (tabbar-tab-tabset tab))
                    (format " %s " (tabbar-tab-value tab)))))
      (if tabbar-auto-scroll-flag
          label
        (tabbar-shorten
         label (max 1 (/ (window-width)
                         (length (tabbar-view
                                  (tabbar-current-tabset)))))))))

  (defun px-tabbar-buffer-select-tab (event tab)
    "On mouse EVENT, select TAB."
    (let ((mouse-button (event-basic-type event))
          (buffer (tabbar-tab-value tab)))
      (cond
       ((eq mouse-button 'mouse-2) (with-current-buffer buffer (kill-buffer)))
       ((eq mouse-button 'mouse-3) (pop-to-buffer buffer t))
       (t (switch-to-buffer buffer)))
      (tabbar-buffer-show-groups nil)))

  (defun px-tabbar-buffer-help-on-tab (tab)
    "Return the help string shown when mouse is onto TAB."
    (if tabbar--buffer-show-groups
        (let* ((tabset (tabbar-tab-tabset tab))
               (tab (tabbar-selected-tab tabset)))
          (format "mouse-1: switch to buffer %S in group [%s]"
                  (buffer-name (tabbar-tab-value tab)) tabset))
      (format "\
mouse-1: switch to %S\n\
mouse-2: kill %S\n\
mouse-3: Open %S in another window"
              (buffer-name (tabbar-tab-value tab))
              (buffer-name (tabbar-tab-value tab))
              (buffer-name (tabbar-tab-value tab)))))

  (defun px-tabbar-buffer-groups ()
    "Sort tab groups."
    (list (cond ((or
                  (eq major-mode 'dired-mode)
                  (string-equal "*" (substring (buffer-name) 0 1))) "emacs")
                (t "user"))))
  (setq tabbar-help-on-tab-function 'px-tabbar-buffer-help-on-tab
        tabbar-select-tab-function 'px-tabbar-buffer-select-tab
        tabbar-buffer-groups-function 'px-tabbar-buffer-groups)

  :init
  (tabbar-mode 1))

付録1-萌えテーマ

(use-package moe-theme
  :ensure t
  :config
  (progn
    (load-theme 'moe-dark :no-confirm)
    (set-face-attribute 'fringe nil :background "gray19")))

付録2-最後の2つのバッファーの切り替え(KBマクロ)

(define-key global-map [(control tab)] (kbd "C-x b <return>")) 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.