Bufferのread_onlyを一時的にOFFにしたいとき - Python
Bufferのread_only
がAlways()
だと、Bufferのtext
とかdocument
とか何も変更できないから、Never()
にする必要がある
form prompt_toolkit.filter import to_filter # read_onlyをONにする right.content.buffer.read_only = to_filter(True) # read_onlyをOFFにする right.content.buffer.read_only = to_filter(False)
使用例
from prompt_toolkit.application import Application from prompt_toolkit.key_binding import KeyBindings from prompt_toolkit.layout.containers import VSplit, Window from prompt_toolkit.layout.controls import BufferControl from prompt_toolkit.layout.layout import Layout from prompt_toolkit.buffer import Buffer from prompt_toolkit.document import Document from prompt_toolkit.filters import to_filter text = '\n'.join([str(i) for i in range(100)]) left = Window(BufferControl(Buffer(document=Document(text), read_only=True))) right = Window(BufferControl(Buffer(document=Document(text), read_only=True))) # ウィンドウ body = VSplit([ left, Window(width=1, char='|'), right, ]) # キーバインディング kb = KeyBindings() @kb.add('tab') def _(event): event.app.layout.focus_next() @kb.add('s-tab') def _(event): event.app.layout.focus_previous() @kb.add('q') def _(event): event.app.exit() @kb.add('c-o') def _(event): ## ここで、一時的にread_onlyをOFFにしている right.content.buffer.read_only = to_filter(False) right.content.buffer.document = Document('hello world!') right.content.buffer.read_only = to_filter(True) app = Application( layout=Layout(body), key_bindings=kb, full_screen=True) app.run()
以下、いろいろ調べたときのメモ
documentを変えるときだけ、read_onlyをFalseにする
Documnet
のコンストラクタを見ると引数でもらったread_onlu
をto_filter()
に渡している
https://github.com/prompt-toolkit/python-prompt-toolkit/blob/master/prompt_toolkit/buffer.py#L196
class Buffer(object): ... def __init__(self, completer=None, auto_suggest=None, history=None, validator=None, tempfile_suffix='', name='', complete_while_typing=False, validate_while_typing=False, enable_history_search=False, document=None, accept_handler=None, read_only=False, multiline=True, on_text_changed=None, on_text_insert=None, on_cursor_position_changed=None, on_completions_changed=None, on_suggestion_set=None): # Accept both filters and booleans as input. enable_history_search = to_filter(enable_history_search) complete_while_typing = to_filter(complete_while_typing) validate_while_typing = to_filter(validate_while_typing) read_only = to_filter(read_only) ...
to_filter()ってなに
prompt_toolkit.filters.utils
にいた
https://github.com/prompt-toolkit/python-prompt-toolkit/blob/master/prompt_toolkit/filters/utils.py
True
を渡すと、prompt_toolkit.filters.base.Always()
が返される。
False
を渡すと、prompt_toolkit.filters.base.Never()
が返される。
from __future__ import unicode_literals from .base import Always, Never, Filter __all__ = [ 'to_filter', 'is_true', ] _always = Always() _never = Never() def to_filter(bool_or_filter): """ Accept both booleans and Filters as input and turn it into a Filter. """ if not isinstance(bool_or_filter, (bool, Filter)): raise TypeError('Expecting a bool or a Filter instance. Got %r' % bool_or_filter) return { True: _always, False: _never, }.get(bool_or_filter, bool_or_filter) def is_true(value): """ Test whether `value` is True. In case of a Filter, call it. :param value: Boolean or `Filter` instance. """ return to_filter(value)()
AlwaysとNeverってなに
prompt_toolkit.filters.base
にいた
class Always(Filter): """ Always enable feature. """ def __call__(self): return True def __invert__(self): return Never() class Never(Filter): """ Never enable feature. """ def __call__(self): return False def __invert__(self): return Always()
__call__
と__invert__
って何
__call__
はインスタンス生成以外で関数っぽく呼び出した時に呼ばれる
Pythonのクラスにおけるcallメソッドの使い方 - Qiita
__invert__
は反転って意味らしい
よくわからなくなってきたけど、こうすればいいってことだ
form prompt_toolkit.filter import to_filter # read_onlyにするとき right.content.buffer.read_only = to_filter(True) # read_onlyを解除するとき right.content.buffer.read_only = to_filter(False)
has_focus(value)で渡したUIControl(Window)にフォーカスがあるか確認する - Python
指定したコントロールにフォーカスがあるかどうか
prompt_toolkit.layout.layout.Layout.has_focus()
で確認できる
has_focus(value)
Check whether the given control has the focus.
:param value: UIControl or Window instance.
Window
かUIControl
を渡す
使い方としてはキーバインディングで
@kb.add('o') def _(event): logger.debug(event.app.layout.has_focus(left_window))
って感じにする
まず、キーが押された時に、現在起動中のApplication
のlayout
を取得する
こんなApplicationだったばあい
from prompt_toolkit.application import Application from prompt_toolkit.key_binding import KeyBindings from prompt_toolkit.layout.layout import Layout from prompt_toolkit.buffer import Buffer from prompt_toolkit.layout.containers import VSplit, Window from prompt_toolkit.layout.controls import BufferControl from prompt_toolkit.document import Document from prompt_toolkit.key_binding.bindings.focus import focus_next, focus_previous from prompt_toolkit.keys import Keys from logging import getLogger, config config.fileConfig("logger.conf") logger = getLogger(__name__) def get_text(): return '\n'.join([chr(i) for i in range(65, 65+26)] * 3) left_window = Window(BufferControl(Buffer(document=Document(get_text(), cursor_position=0), read_only=True))) right_window = Window(BufferControl(Buffer(document=Document(get_text(), cursor_position=0), read_only=True))) split_line = Window(width=1, char='|') body = VSplit([ left_window, split_line, right_window ]) # キーバインディング kb = KeyBindings() kb.add(Keys.Tab)(focus_next) kb.add(Keys.BackTab)(focus_previous) @kb.add('q') def _(event): event.app.exit() @kb.add('o') def _(event): logger.debug(event.app.layout) app = Application( layout=Layout(body), key_bindings=kb, full_screen=True) app.run()
出力されるのは、
2018-11-02 07:39:37:DEBUG Layout(<prompt_toolkit.layout.containers.VSplit object at 0x1017b5be0>, current_window=Window(content=<BufferControl buffer=<Buffer (name='', text='A\nB\nC\nD\nE\nF\n...') at 4319711808> at 4319711640>))
event.app.layout
でApplication()のコンストラクタのlayout
に指定した参照が取得できる。
指定のウィンドウにフォーカスがあるか調べる
左側のウィンドウにフォーカスがあるかどうかはLayout.has_focus()
にleft_window
を渡せばいい
@kb.add('o') def _(event): logger.debug(event.app.layout.has_focus(left_window))
左側にフォーカスがある時にo
を押すとTrue
、右側にあるときはFalse
基本的には、ウィンドウとかはインスタンスを変数に入れておけば良いのかな
このhas_focus()を使えば、特定のウィンドウにフォーカスがあるときのみ、キーバインドを実行するとかできるのかな?
fillterとか使えそう...?
logger.confは以下の通り
;ロガーを使用するときには以下のように記述する ;from logging import getLogger, config ;config.fileConfig("logger.conf") ;_logger = getLogger(__name__) [loggers] keys=root [handlers] keys=fileHandler [formatters] keys=simpleFormatter [logger_root] level=DEBUG handlers=fileHandler [handler_fileHandler] class=FileHandler level=DEBUG ; ハンドラで使用するフォーマッタを指定 formatter=simpleFormatter ; FileHandlerのコンストラクタへの引数 args=("log.log", "a+") [formatter_simpleFormatter] format=%(asctime)s:%(levelname)s %(message)s ; 時間の表示形式を設定 datefmt=%Y-%m-%d %H:%M:%S
参考文献
vimっぽいページスクロール(c-dとc-u)をpython-prompt-toolkitで実装 - Python
python-prompt-toolkitを使って、ページのスクロールを実装したからメモメモ
以下の2つだけとりあえず、実装してみる
handle('c-d')(scroll_half_page_down) handle('c-u')(scroll_half_page_up)
prompt_toolkit.key_binding.bindings.scroll
のscroll_half_page_down
とscroll_half_page_up
の2つだ!
from prompt_toolkit.application import Application from prompt_toolkit.key_binding import KeyBindings from prompt_toolkit.layout.layout import Layout from prompt_toolkit.buffer import Buffer from prompt_toolkit.layout.containers import Window from prompt_toolkit.layout.controls import BufferControl from prompt_toolkit.document import Document # これ from prompt_toolkit.key_binding.bindings.scroll import scroll_half_page_down, scroll_half_page_up def get_text(): return '\n'.join([chr(i) for i in range(65, 65+26)] * 3) body = Window(BufferControl(Buffer(document=Document(get_text(), cursor_position=0), read_only=True))) # キーバインディング kb = KeyBindings() # これ kb.add('c-d')(scroll_half_page_down) kb.add('c-u')(scroll_half_page_up) @kb.add('q') def _(event): event.app.exit() app = Application( layout=Layout(body), key_bindings=kb, full_screen=True) app.run()
できた!!!!!!!
c-d
で半分下にスクロール、c-u
で半分上にスクロール!!
できなかったやーつ
prompt_toolkit.key_binding.bindings.page_navigation
にload_vi_page_navigation_bindings
っていうのがあった
試してみる
以下のようにして、実行したら、c-d
で半分下に移動ができなかった...
ただ呼ぶだけじゃだめなのかな?
from prompt_toolkit.application import Application from prompt_toolkit.key_binding import KeyBindings from prompt_toolkit.layout.layout import Layout from prompt_toolkit.buffer import Buffer from prompt_toolkit.layout.containers import Window from prompt_toolkit.layout.controls import BufferControl from prompt_toolkit.document import Document from prompt_toolkit.key_binding.bindings.page_navigation import load_vi_page_navigation_bindings def get_text(): return '\n'.join([chr(i) for i in range(65, 65+26)] * 3) body = Window(BufferControl(Buffer(document=Document(get_text(), cursor_position=0), read_only=True))) # キーバインディング kb = KeyBindings() load_vi_page_navigation_bindings() @kb.add('q') def _(event): event.app.exit() app = Application( layout=Layout(body), key_bindings=kb, full_screen=True) app.run()
ソースを見ると、ConditionalKeyBindings
のインスタンスを返してるから、それをなんかするのかも?
def load_vi_page_navigation_bindings(): """ Key bindings, for scrolling up and down through pages. This are separate bindings, because GNU readline doesn't have them. """ key_bindings = KeyBindings() handle = key_bindings.add handle('c-f')(scroll_forward) handle('c-b')(scroll_backward) handle('c-d')(scroll_half_page_down) handle('c-u')(scroll_half_page_up) handle('c-e')(scroll_one_line_down) handle('c-y')(scroll_one_line_up) handle('pagedown')(scroll_page_down) handle('pageup')(scroll_page_up) return ConditionalKeyBindings(key_bindings, vi_mode)
prompt_toolkit.key_binding.key_bindings.ContiditionalKeyBindings
だ
viモードのときにしか聞かないのかな?
選択値とは別の値をテキストボックスのvalueに設定する - JQuery
devbridge/JQuery-Autocompleteを使って、Autocompleteを実装したときのメモ
onSelectを使う
suggestionsが以下のようになっていた場合
suggestions: {[ { value: "山田太郎 20歳", data: { name: "山田太郎", age: "20" } }, { value: "山田次郎 18歳", data: { name: "山田次郎", age: "18" } } ]}
やりたいのは「山田太郎 20歳」を選択時、テキストボックスのvalueに「山田太郎」をセットすること
$(function() { $('.autocomplete-horse-name').autocomplete({ serviceUrl: '/api/v1.0/person', dataType: 'json', transformResult: function(response) { return { suggestions: $.map(response, function (item) { return {value: item.name + " " + item.age + "歳", data: item}; }) } }, onSelect: function(suggestion) { this.value = suggestion.data.name; } }) });
onSelect
で選択したときに呼ばれる処理を記述できるため、それを使う。
suggestion
が選択した項目のデータ、this
が入力中のHTMLElementとなっているため、こんな感じで書ける。
参考文献
ghqとpecoとhubを使ったリポジトリの管理
リポジトリをダウンロードして、見たりするときとかいいのかも
ずっとやろうって思ってたのをやっとできたから、メモメモ
それぞれをインストールする
ghq
go get github.com/motemen/ghq
peco
go get github.com/peco/peco/cmd/peco
hub
go get github.com/github/hub
エイリアスの設定
~/.bashrc
に以下を追加
alias gcd='cd $(ghq root)/$(ghq list | peco)' alias gh='hub browse $(ghq list | peco | cut -d "/" -f 2,3)'
gcd
して、検索して矢印キーで移動して、Enterでカレントディレクトリをそれに変更する
gh
して、検索して矢印キーで移動して、EnterでGitHubでそれを開く
ghqの使い方
ghq get {リポジトリのURL}
ghq get https://github.com/requests/requests.git
~/.ghq/github.com/requests/requests
にダウンロードされる
その他のコマンドの説明はmotemen/ghq: Remote repository management made easyで確認する
また、~/.gitconfig
に以下を追加することで、ダウンロード先を変えることもできる(デフォルトでは~/.ghq
にダウンロードされる)
[ghq] root = ~/src/repos
参考文献
複数行で書きたい時 - Python
()
でくくる
s = ('hello' 'world') print(s)
helloworld
print(('hello' 'world'))
helloworld
参考文献
PipenvでImportError: cannot import name 'get_installed_distributions'ってエラー出た
pipenvのgraphしたらエラーが出たから、その時の対処のメモと言うか、いらないと思うけど、メモっとく
$ pipenv graph Traceback (most recent call last): File "/usr/local/lib/python3.6/site-packages/pipenv/vendor/pipdeptree.py", line 17, in <module> from pip._internal import get_installed_distributions ImportError: cannot import name 'get_installed_distributions' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/local/bin/pipenv", line 11, in <module> sys.exit(cli()) File "/usr/local/lib/python3.6/site-packages/pipenv/vendor/click/core.py", line 722, in __call__ return self.main(*args, **kwargs) File "/usr/local/lib/python3.6/site-packages/pipenv/vendor/click/core.py", line 697, in main rv = self.invoke(ctx) File "/usr/local/lib/python3.6/site-packages/pipenv/vendor/click/core.py", line 1066, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) File "/usr/local/lib/python3.6/site-packages/pipenv/vendor/click/core.py", line 895, in invoke return ctx.invoke(self.callback, **ctx.params) File "/usr/local/lib/python3.6/site-packages/pipenv/vendor/click/core.py", line 535, in invoke return callback(*args, **kwargs) File "/usr/local/lib/python3.6/site-packages/pipenv/cli.py", line 922, in graph do_graph(bare=bare, json=json, json_tree=json_tree, reverse=reverse) File "/usr/local/lib/python3.6/site-packages/pipenv/core.py", line 2363, in do_graph import pipdeptree File "/usr/local/lib/python3.6/site-packages/pipenv/vendor/pipdeptree.py", line 20, in <module> from pip import get_installed_distributions, FrozenRequirement ImportError: cannot import name 'get_installed_distributions'
ここに書いてあった
python3 -m pip install --upgrade pip python3 -m pip install --upgrade pipenv
でできた