Closed halueda closed 4 years ago
develop branch で評価版の実装をしてみました。 https://github.com/smzht/fakeymacs/tree/develop
個人設定は、config_personal.py ファイルから取り込みます。サンプルファイルを _config_personal.py として作成しておきましたので、名称を変更してベースファイルとしてお使いください。
config_personal.py には[]で括られたセクション名が定義されており、その単位で config.py の中で exec 関数で取り込みするようにしています。config.py ファイルの exec 関数をコールしているところを検索すると、何のセクションがどこで読み込まれるかが分かると思います。
なお、exec 関数はローカル変数の設定ができないようですので、P class を定義し、変更が必要な変数を P class のクラス変数に移行しています。
以上となりますので、使ってみていただき、ご意見等あればお願いします。
補足します。
config.py に記載されているキーバインドを無効にするためには、P.skip_settings_key 変数と P.emacs_exclusion_key 変数を使うことができます。この機能はすでに master branch に反映済みです。
P.skip_settings_key 変数に設定したキーは define_key 関数内でスキップされます。このため、P.skip_settings_key 変数を参照せずにキーの設定を行う define_key2 関数を新たに作成しています。あるキーの役割を変更する場合には、そのキーを P.skip_settings_key 変数に定義して設定をスキップするようにし、define_key2 関数を使って新たに再定義するようにしてください。
これらの機能により、config.py をいじらずに config_personal.py のみで設定の見直しができるようにしています。
その後テストをしてみていますが、スコープに関する問題が出てきています。全面的に実装方法の見直しが必要そうですが、その良い方法も思いついておりません。
わかったことです。 ・exec で実行されるコードで関数を定義すると、その関数にはその関数の上位で設定したローカル変数の値が渡らない。 関数の引数に指定して渡すことはできますが、これを制約事項とするかどうかは迷うところです。
exec を利用する方針とすることとし、develop branch を master branch に merge しました。
素早い対応ありがとうございます。まだダウンロードしてみているだけですがいくつか気になっている点をフィードバックしておきます。
class FaykeymacsConfig:
pass
P = faykeymacs_config = FaykeymacsConfig()
fc = faykeymacs_config
fc.skip_settings_key = {....}
その後テストをしてみていますが、スコープに関する問題が出てきています。全面的に実装方法の見直しが必要そうですが、その良い方法も思いついておりません。
これは、どういう問題が起きますか?
・exec で実行されるコードで関数を定義すると、その関数にはその関数の上位で設定したローカル変数の値が渡らない。 関数の引数に指定して渡すことはできますが、これを制約事項とするかどうかは迷うところです。
「上位」というのは、config_personal.pyの中で定義したローカル変数という意味でしょうか?もしかして、[]でくくられたセクションが異なると、異なったセクションで定義した変数という意味でしょうか?config.pyの中の configure()関数の中のローカル変数は見えている様子ですが(それはそれで、レキシカルスコープでは見えない変数が参照できてしまって気持ち悪いのだが)
その後テストをしてみていますが、スコープに関する問題が出てきています。全面的に実装方法の見直しが必要そうですが、その良い方法も思いついておりません。
これは、どういう問題が起きますか?
execで実行されるコードには、デフォルトでコールする側のグローバル変数とローカル変数が渡ります。これは、execの第二引数と第三引数にそれぞれ globals() と locals() が渡ることにより実現されているようです(変更も可能)。だたし、テストしてみて分かったのですが、execで実行されるコードの中に関数の定義があると、その関数内部では exec に渡ったローカル変数が使えません。これをスコープに関する問題と表現しました。
・exec で実行されるコードで関数を定義すると、その関数にはその関数の上位で設定したローカル変数の値が渡らない。 関数の引数に指定して渡すことはできますが、これを制約事項とするかどうかは迷うところです。
「上位」というのは、config_personal.pyの中で定義したローカル変数という意味でしょうか?もしかして、[]でくくられたセクションが異なると、異なったセクションで定義した変数という意味でしょうか?config.pyの中の configure()関数の中のローカル変数は見えている様子ですが(それはそれで、レキシカルスコープでは見えない変数が参照できてしまって気持ち悪いのだが)
先に記載したとおり、exec で実行される第一レベルは問題ないのですが、第二レベル以降(関数を定義した中)でローカル変数が使えません。このため、Fakeymacs や P class をグローバルスコープで定義するように変更しました。ただし、configure 関数内で定義されているローカル変数(keymap など)全てをグローバル変数にすることはできないので、関数に引き渡す必要があるものは引数経由で行うこととし、そのサンプルーコードを config_persoal.py の載せることとしました。(emacsclient 関数がそれです。)
- P というクラス名に違和感があります。FaykeymacsConfig クラスにしませんか?
- 設定をクラス変数に入れることに違和感があります。インスタンスを作って、そこに入れませんか?
- config.pyではこんな感じ。Pはconfig.pyの中だけで使う感じ(personalで使ってもよいけど、Ver Upの時に変えるかもしれないからわかって使ってねという位置づけ)
develop branch に反映してみました。 https://github.com/smzht/fakeymacs/tree/develop
P を全て fakeymacs_config にするとくどくなるので、fc で統一してみました。 グローバルスコープで定義しているのは、一つ前の Comment の理由で維持しています。
確認ください。
execで実行されるコードには、デフォルトでコールする側のグローバル変数とローカル変数が渡ります。これは、execの第二引数と第三引数にそれぞれ globals() と locals() が渡ることにより実現されているようです(変更も可能)。だたし、テストしてみて分かったのですが、execで実行されるコードの中に関数の定義があると、その関数内部では exec に渡ったローカル変数が使えません。これをスコープに関する問題と表現しました。
こんなページを見つけました。 https://stackoverflow.com/questions/2904274/globals-and-locals-in-python-exec
トリッキーな対応方法ですが、9番に次のようなやり方が書かれています。
d = dict(locals(), **globals())
exec (code, d, d)
確かにこの方法だとexecで実行するコード内にある関数内でもローカルスコープの変数が参照可能となります。 exec のコード内で定義した変数も関数内で参照可能となるのは理解し難いですが、もう少し調べてみます。
コードを見直し、config_personal.py が config.py とほぼ同じように記載できるようになりました。
https://github.com/smzht/fakeymacs/tree/develop
config.py で exec 関数を次のとおりにコールしています。
exec(read_config_personal("[section-init]"), dict(globals(), **locals()))
exec は第三引数を省略すると第二引数と同じものを参照するようで、config_personal.py の中で変数を定義すると、ローカル変数になると共にグローバル変数としても認識され、サブ関数内でも利用できる変数になるようです。 https://docs.python.org/3/library/functions.html?highlight=exec%20global#exec
If only globals is provided, it must be a dictionary (and not a subclass of dictionary), which will be used for both the global and the local variables.
develop branch を master branch に merge しました。本件もうすこし様子見て、問題ないようであれば close とします。
個人用の設定ファイル(具体的には、基本設定とコメントのあるパートまで)と、Fakeymacsクラスその他(基本設定パート以降)を別ファイルにできるようにして欲しいです。 fakeymacsがバージョンアップした時に、fakeymacsのconfig.pyだけダウンロード・上書きするだけで、個人用の設定は変えないですむようにしたいのです。
実現方法としては、個人設定用の myconfig.py みたいなファイルがあれば、それを基本設定パートに入る直前に読み込んで、デフォルト設定を上書きできるようにして欲しいし、バインディングを上書き設定するためのファイルを、最後に読み込んで欲しい。
一つのファイルに二個の設定用の関数(フック)を定義しておいて、それらがあれば実行するという実装でもよいです。
ちょっと忙しくて実装したりプルリクしたりは当面できそうにありませんが、要望事項だけあげておきます。