kiwanami / emacs-window-manager Goto Github PK
View Code? Open in Web Editor NEWCustomizable window manager for emacs
Customizable window manager for emacs
mainにフォーカスがある時に、subが開くとフォーカスがmainから離れることがあります。
当方の環境は
GNU Emacs 24.3.50.1
e2wm、window-layoutは現時点での先端です。
以下、再現方法です。
調査不足かもしれませんが、Subが開くときに、フォーカスがSubに移らない場合、この現象が発生するような気がします。
e2wm:pst-update-windows 相当の関数を :update
にしたものをすべてのパースペクティブの base class にしてはどうでしょうか。 Monky パースペクティブの問題点があるのですが、それをスマートに解決するのに役立ちます。
Monky パースペクティブを開くと各プラグインの更新に時間がかかり、かなりまったりな動作になってしまいます。 Monky (Magit にも) monky-with-refresh
なるマクロがあってこのマクロ内では画面の更新をせず、一番最後に一回だけ更新をおこなう、みたいなことが出来ます。これを e2wm で試すには、 e2wm:pst-update-windows を以下のように変更すればいけます。
(defun e2wm:pst-update-windows (&optional rebuild-windows)
;;全ウインドウを更新する。rebuild-windowがnon-nilであればウインドウの再構築を行う。
(e2wm:message "#PST-UPDATE")
(e2wm:with-advice
(let* ((instance (e2wm:pst-get-instance))
(wm (e2wm:$pst-wm instance)))
;;(e2wm:debug-windows (e2wm:pst-get-wm))
(unless rebuild-windows
(wlf:wset-fix-windows wm))
(when (or rebuild-windows
(not (wlf:wset-live-p wm)))
(e2wm:message " #PST-UPDATE > REBUILD")
(wlf:refresh wm)
(e2wm:aif (e2wm:$pst-main instance)
(wlf:select wm it)))
(monky-with-refresh ; ← これを追加
;;パースペクティブ固有の処理
(e2wm:pst-method-call e2wm:$pst-class-update instance wm)
;;プラグイン更新実行
(e2wm:plugin-exec-update (selected-frame) wm))
)) t)
これをもうちょっとまともに解決するためには、 e2wm:pst-update-windows 相当の関数を :update
にしたものをすべてのパースペクティブの base class にして、すべてのパースペクティブをその base class から派生させれば良いと思います。そうすれば、こんな感じで monky-with-refresh
が使えるはずです:
(defun e2wm:dp-monky-update (wm)
(monky-with-refresh
(e2wm:$pst-class-super wm)))
同じ buffer を違う window で開いている時に sub を on/off すると位置が変わる問題があります。
Emacs を以下のコードで初期化したとします。
(require 'e2wm-config)
(e2wm:start-management)
(e2wm:dp-two)
ちなみに、以下のコードで問題を再現しようとしたんですが、 sub の toggle なし(open sub 以下をコメントアウト)だとそもそも right に ファイル が表示されないので再現の手順としては不十分っぽいです。
(let ((some-file "~/.emacs.d/el-get/e2wm/e2wm-config.el")
buf)
;; at left win
(e2wm:dp-two-navi-left-command)
(find-file some-file)
;; at right win
(e2wm:dp-two-navi-right-command)
(find-file some-file)
(goto-char (point-min))
;; open sub
(e2wm:pst-window-toggle 'sub t 'left)
)
@kiwanami さんの TODO に入っているかもしれませんが、 構造体 や 表記ルールなどをコピペして簡単なものを作るくらいならばこちらでやらせていただきます。(ソース内を検索するのが面倒になってきたので...。) README を markdown に変更してそこに入れるか、 texinfo で作る方法などがあると思います。 もしこちらでしてもOKだったらフォーマットと一緒に教えてください。
e2wm を有効にした Emacs に emacsclient --tty
で接続して、その後にそのフレームを閉じると e2wm が無効になってしまいます。 debug オプションつけて様子を見ると以下のような感じになっていました。
28 #KILL HOOK
29 #KILL HOOK
30 #KILL HOOK
31 #KILL HOOK
32 ## MAKE FRAME [#<frame F2 0x3a83390>] <- (#<frame *GNU Emacs* - emacs@tkf-lnp2 0xea7da0>)
33 ## PST MM SWITCH [nil] / #<frame F2 0x3a83390>
34 ## PST MM DISABLED
35 #PST-FINISH
また、 emacsclient --tty FILENAME
で接続すると、 emacs も emacsclient もハングするので Emacs 本体を kill するしかなくなります。ただし、 FILENAME が存在しないときはハングしません。 (以前は FILENAME が存在する時もハングしなかった気がしますが、それはどうやっても再現しなくなりました。。。) Emacs 24.0.94.1 で試しました。
そういえば、なんで e2wm:message ってマクロなんですか? デバッグのために e2wm.el をロードしなおすと他のモジュールで定義した pst-class が消えてしまってちょっと面倒です。。。
Hi
When using Emacs built with GTK3 e2wm split windows vertical scrollbar are in the wrong horizontal positions.
Also, the e2wm menu does not display at all (not imenu, the x11 app menu (file edit options etc)).
以下の定義になっているのですが、
(defun e2wm:def-plugin-svn-logs (frame wm winfo)
(e2wm:def-plugin-vcs-with-window
'e2wm:def-plugin-svn-top-dir
(lambda (dir topdir)
(let ((default-directory (file-name-as-directory topdir)))
(svn-log e2wm:def-plugin-svn-log-arg))
(let ((dbuf (get-buffer-create e2wm:def-plugin-svn-logs-buffer-name)))
(with-current-buffer dbuf
(setq buffer-read-only nil)
(buffer-disable-undo buf)
...
(buffer-disable-undo buf)
のbuf
は、
e2wm:def-plugin-vcs-with-window
の中のlet
で宣言されているので動作しますが、
意図されたコードではないのではないかと思ったので、ご報告しておきます。
ちなみに、buffer-disable-undo
は何のためにやっているんでしょうか?
時々、undoができなくなる時があって、e2wmを使っている時に起きているような気がしまして…。
最新のe2wmでは、imenuプラグインのバッファが空になっているようです。
6d07ba2 のコミットまでは、正常に動作しているようなので、それ以降の変更によって起きているようです。
手元のemacsは GNU Emacs 24.1.50.1 (x86_64-unknown-linux-gnu, GTK+ Version 3.4.3) です。
(comint-dynamic-list-completions '("a" "b" "c"))
を実行すると window の配置が壊れてしまいます。元の配置がmain windowの中で繰り返されるような感じになります。set-window-configuration などが comint-dynamic-list-completions から呼ばれているのが原因でしょうか。
Emacs 24.0.94.1 で確認しました。
e2wm:c-recordable-buffer-p に以下のような設定をして使っています。 window 情報 (wm
, wname
) をとるために長々とコードを書かなければいけないので、 window 関連の変数にアクセス可能だと、大変楽になります。
あと、関連していくつか提案があります:
e2wm:pst-get-wm
を呼ぶときにいつでも(e2wm 管理下になくても)エラーが出ないようにして欲しいです。 以下のコードでは e2wm:pst-get-instance で条件分けてますが、これがないと e2wm をスタートするときに、まだe2wm管理下にないので、エラーでこけてしまいます。(setq e2wm:c-recordable-buffer-p
(lambda (buf)
(let* ((name (buffer-name buf))
(wm (when (e2wm:pst-get-instance) (e2wm:pst-get-wm)))
(bufwin (get-buffer-window buf))
(wname (when (and wm bufwin)
(wlf:get-window-name wm bufwin))))
(and
;; record only if shown in "non-sub" window
(not (memq wname '(sub)))
(or
;; specify some recordable buffers
(equal "*Ibuffer*" name)
(string-match "\\*Python\\[.*\\]*" name)
(equal "*IPython*" name)
(equal "*info*" name)
(equal "*Help*" name)
(equal "*Simplenote*" name)
;; specify some recordable major modes
(memq (buffer-local-value 'major-mode buf)
'(dired-mode))
;; support org indirect buffers
(and (equal (buffer-local-value 'major-mode buf) 'org-mode)
(string-match "\\.org-[0-9]*$" name))
(and
;; buffer is associated with a file
(buffer-local-value 'buffer-file-name buf)
;; buffer name is not something like "*BUFFER-NAME*"
(not (string-match "^ *\\*.*\\* *$" name))
;; buffer does not end with ".org_archive"
(not (string-match "\\.org_archive$" name))))))))
run-with-idle-timer でファイルを保存する関数(recentf-save-list など)を呼ぶと、ウィンドウ構成が崩れてしまうようです。以下のファイルを emacs -l file
で読み込んで起動させると、問題を再現できます。例えば、 e2wm:dp-magit を開き、 Magit Logs window で log を前後して、 *magit-commit*
window を表示させ、5秒まつとこの *magit-commit*
window が消え、元の *magit: REPO*
buffer が表示されてしまいます。
my-recentf-auto-save-list-workaround を呼ぶとこの問題は起きないのですが、代わりに warning message が出てしまいます。ちなみに、idleに入る前に e2wm 管理下に無いフレームに居た場合はこの問題は起きません。
(add-to-list 'load-path "~/.emacs.d/el-get/e2wm/")
(add-to-list 'load-path "~/.emacs.d/el-get/window-layout/")
(add-to-list 'load-path "~/.emacs.d/el-get/magit/")
(add-to-list 'load-path "~/.emacs.d/el-get/monky/")
(require 'recentf)
(require 'e2wm-config)
(require 'e2wm-vcs)
(run-with-idle-timer 5 t 'recentf-save-list)
;; (run-with-idle-timer 5 t 'my-recentf-auto-save-list-workaround)
(defun my-recentf-auto-save-list-workaround ()
(flet ((warn (fmt &rest args) (apply 'message fmt args))
;; a hack to make things ignored by e2wm
(e2wm:pst-get-instance (&optional frame) nil))
(recentf-save-list)))
(recentf-mode 1)
(e2wm:start-management)
;; How to reproduce:
;; 1. Open some file (in Git repository)
;; 2. M-x e2wm:dp-magit
;; 3. Open some other buffer in the main window
;; 4. Wait 5 sec, then the default window set appears automatically
;; When my-recentf-auto-save-list-workaround is used, you will see an Error:
;; recentf mode: Wrong type argument: arrayp, nil
間違えて別プロジェクトに投稿していました (kiwanami/emacs-anything-books#4) すいません...。
一応こちらに再投稿しておきます。
現状だと、 e2wm:$pst-class
の要素以外は継承使えないですよね? sub に popup する挙動のみを変えたい場合って結構あると思うので、継承可能だと嬉しいんじゃないでしょうか。(:default-hide
な window がいくつも作れることを考えると、あまり上手い方法じゃないかもですが。かと言って、一般的なクラスシステムを作るのは大変そうです。)
popwin.el をサポートしてそっちに任せても良いかもしれません。こっちのほうが嬉しいって人が多そうです。
masterブランチにe2wm:$pst-class-extendの定義がないようです。
Is there any way to customize buffer sizes in init.el? For instance, I find the dired buffer (under code perspective) too wide by default and wish to make it thinner.
Thanks!
Emacs 24.4 から eww という web ブラウザが付属するようになりましたが、こいつも e2wm:c-document-buffer-p
がデフォルトで t
を返すようにしたほうがいいような気がします。
バッファ名は *eww*
です。
I want to know what kind of the extension of e2wm.el.
For example, there is this page in EmacsWiki about the source of autocomplete.el.
Do you know or have the web page like that about e2wm.el?
BTW,
I'm considering to develop the perspective for handling Gnus.
Do you know the extension like that?
こんにちは。先日の base class を加えた issue #18 ですが、また別の問題が発生しました。
デフォルトで定義されている perspective class の派生クラスを作ると、プラグインが update されなくなります。これは、 e2wm:method-call
が1段階の継承しかサポートしてないことが原因で、 e2wm:dp-base-update
が呼ばれなくなるからです。
コメントに明記されているのでバグとは言い難いですが、カスタマイズのためにクラスシステムがあると思うので、できれば何段階でも継承出来るほうが良いと思いますが、どうでしょうか?
現状のコードで拡張しようとすると、↓のようなコードを書く必要があります。
(e2wm:pst-class-register
(make-e2wm:$pst-class
:name 'code+
:extend 'code
:title "Code+"
:update 'e2wm:dp-base-update ;; ← 強制的にセットする必要がある
:popup 'ne2wm:dp-code+-popup))
(defun ne2wm:dp-code+-popup (buffer)
(flet ((e2wm:dp-code-popup (b) (ne2wm:popup-sub-appropriate-select b)))
(e2wm:$pst-class-super)))
ちなみに、フルのコードは https://github.com/tkf/ne2wm/blob/master/ne2wm-pst-code%2B.el に置いてあります。
デフォルトだと、diff結果はsubに表示されると思うんですけど、
sub窓って大きくないので、大抵の人は使いづらいんじゃないかと思うんですが、
kiwanamiさんはどのようなrecipeで使ってらっしゃいますか?
僕は、他にもfilesやhistoryは、このパースペクティブでは要らないし、
logも、もっと幅があれば良いのになぁと思ってました。
なので、導入当初は使いづらい印象で使ってなかったんですが、
以下のように設定変更したら、現在はコミット作業がすこぶる快適になっています。
;; svn
(setq e2wm:c-svn-recipe
'(| (:left-size-ratio 0.3)
status
(| (:left-size-ratio 0.2)
(- (:upper-size-ratio 0.5)
logs
(- (:upper-size-ratio 0.5)
main sub))
diff)))
(setq e2wm:c-svn-winfo
'((:name status :plugin svn-status)
(:name logs :plugin svn-logs)
(:name diff :buffer "*svn output*" :default-hide t)
(:name main)
(:name sub :buffer nil :default-hide t)))
(setf (e2wm:$pst-class-main (e2wm:pst-class-get 'svn)) 'status)
(defadvice e2wm:dp-svn-popup (around ~e2wm:mng-diff activate)
(if (string= (buffer-name (ad-get-arg 0)) "*svn output*")
(e2wm:with-advice
(e2wm:pst-buffer-set 'diff (ad-get-arg 0) t t))
ad-do-it))
;; git
(setq e2wm:c-magit-recipe
'(| (:left-size-ratio 0.3)
(- (:upper-size-ratio 0.6)
status branches)
(| (:left-size-ratio 0.2)
(- (:upper-size-ratio 0.5)
logs
(- (:upper-size-ratio 0.5)
main sub))
diff)))
(setq e2wm:c-magit-winfo
'((:name status :plugin magit-status)
(:name branches :plugin magit-branches)
(:name logs :plugin magit-logs)
(:name diff :buffer "*magit-diff*" :default-hide t)
(:name main)
(:name sub :buffer nil :default-hide t)))
(setf (e2wm:$pst-class-main (e2wm:pst-class-get 'magit)) 'status)
(defadvice e2wm:dp-magit-popup (around ~e2wm:mng-diff activate)
(if (string= (buffer-name (ad-get-arg 0)) "*magit-diff*")
(e2wm:with-advice
(e2wm:pst-buffer-set 'diff (ad-get-arg 0) t t))
ad-do-it))
デフォルトだと、便利さが半減してしまうんではないかと。
それだと勿体無いなぁと思いまして。
使いやすさは人それぞれだと思うんですが、
diffを見やすく表示する窓は、デフォルトで入れた方が良い気がします。
以下のコードを実行後に magit perspective を開くと、 "wlf:get-winfo: Window name edit is not found." というエラーが出てしまいます。
setq を require の前に書けば一応動くので急ぎではありませんが、時間のある時に直していただけると助かります。
(require 'e2wm-vcs)
(setq
e2wm:c-magit-recipe
'(| (- main (- edit sub))
(- (:upper-size-ratio 0.9)
(- (:upper-size-ratio 0.8) logs branches)
(| files history))))
(setq
e2wm:c-magit-winfo
'((:name main :plugin magit-status)
(:name edit)
(:name files :plugin files)
(:name history :plugin history-list)
(:name sub :buffer nil :default-hide t)
(:name branches :plugin magit-branches)
(:name logs :plugin magit-logs)))
Whenever I run emacsclient -nw,
and try to load e2wm, I get this following error:
"Symbol's function definition is void: internal--before-with-selected-window"
Needless to say, it fails to load all the helpful plugins.
e2wm の拡張集(ne2wm) を作ってみて浮かんできた要望などをまとめてみます。
ここに書くべき内容かどうかは微妙ですが、 ML とかも無いようですし、機能の要望みたいなものなのでここに書かせていただきます。リンクとか楽ですし。
ne2wm:win-ring-push
と ne2wm:win-ring-rotate
コマンドや history-list+ プラグイン は、"main window" (plugin window ではなくコードなどを表示する window) のリストを独自の変数で管理しています。このリストのおかげで、ある window に対しての "other window" を定義することが出来て、 "other window" を操るコマンドを書くことが出来ます。 例えば、このリストが '(left right third)
で現在 left
に居るとすると、 "other window" は right
です。 right
だと third
で、 third
だと一周まわって left
です。
ne2wm:def-plugin-history-list+-forward/back-other-command
は自分が今居る window に対する "other window" のバッファを切り替えるコマンドです。 e2wm:dp-two-right-history-forward/back-command
と違い、3つ以上の "main window" をもつパースペクティブでもきちんと動作が定義できます。 また、 ne2wm:def-plugin-history-list+-forward/back-current-command
は普通に使うと current window のバッファを切り替えるコマンドですが、 numeric argument (M-3
など) を与えることで、その window にフォーカスを移すことなくバッファを切り替えることができます(M-3
が与えられた場合は window list で 3番目の window を切り替える)。 ne2wm:win-ring-push
と ne2wm:win-ring-rotate
コマンドの動作については スクリーンショット を見るのが分り易いと思います。
まとめると、 "main window list" をもつことで以下のご利益があります。
これを e2wm で導入するには、例えば :main
スロットを list も取れるようにする、とか新たに :main-list
スロットを導入する、みたいな方法があると思います。
さらに、 three+ パースペクティブを使ってて気づいたのですが、自分が今居る window や popup する buffer に応じて sub の位置が切り替わって欲しいと感じました。 three+ はデフォルトでは左下に sub があるのですが、一番右端の window を使っていると視線移動が大きくて辛いです。また、 sub のある column は 80 column より大分細くなっているので anything バッファとかを表示するには辛いものがあります。という訳で、動的に sub window を決めるために :sub
スロットを設けてそこに window name ('sub
など) または window name を返す関数を入れられるようにするのはどうでしょうか? :get-sub
みたいなスロットでも良いかもしれません。そうなると、 :get-main
や :get-other
も欲しくなります。
ne2wm:win-ring-push
/ ne2wm:win-ring-rotate
コマンドne2wm:win-ring-push
と ne2wm:win-ring-rotate
コマンド (ne2wm-utils.el) は ne2wm:win-ring
変数に定義された window を次々と巡っていくコマンドです。 ne2wm:win-ring
変数は "main" window のリストで、 three+ パースペクティブ (ne2wm-pst-three+.el) だと '(left right third)
となっています。 two パースペクティブだと '(left right)
とすれば使えるはずです。
また、まったく同じ値を持つ変数に (ne2wm-plugin-history-list+.el) の ne2wm:def-plugin-history-list+-wname-list
があります。これは、 history list に表示する window を決める変数です。また、 ne2wm:def-plugin-history-list+-pointer-list
という変数も使っていて、これは history list に表示する矢印の設定です。ちなみに、これらの変数は frame local な変数ではなく :plugin-args
でもつべきものですよね。書いた後に気づきました...。
これらの変数の使い方については ne2wm-pst-three+.el の ne2wm:dp-three+-start
をご覧ください。
ne2wm-pst-code+.el では、次のようなコードで e2wm:dp-code-popup-sub
を「拡張」しています。この「拡張法」って dirty hack な気がします。書いているうちに、もっと一般的なクラスシステムが欲しくなってきました。。。
(defun ne2wm:dp-code+-popup (buffer)
(flet ((e2wm:dp-code-popup-sub (b) (ne2wm:popup-sub-appropriate-select b)))
(e2wm:$pst-class-super)))
関連:
毎回以下のようなコードを書いているので、マクロが欲しくなりました。自分で作れよという話ですが、拡張集作った後に気づきました。。。
(e2wm:pst-class-register
(make-e2wm:$pst-class ...))
(defun e2wm:dp-PST-NAME ()
(interactive)
(e2wm:pst-change 'PST-NAME))
ちなみに、 e2wm:pst-class-register
が plist を受け取る関数で書かれていれば #22 で backward compatible な e2wm:pst-class-register
を書くときに、 :extend
が nil
の時と指定されていないときで条件が分岐出来て、よりまともな解決法になったと思いました。
noselect 相当のものは e2wm:pst-buffer-set
の selectp
引数を使えば比較的簡単に実装出来たので作ってみました。ただ、バッファを監視して表示する必要が無くなったり C-g
が押された時に sub を隠す機能は実装していません。 @kiwanami さんが popwin と組み合わせを実装してくださるということなので、大いに期待しています!!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.