http-promptでそれぞれ使っていたため、自力で調べてみたけど違いがわからず、prompt-toolkitのIssuesで質問してみました
動作環境
> python --version
Python 3.7.1
> pip3 list | grep prompt-toolkit
prompt-toolkit 2.0.8
それぞれの違い
text_before_cursor
:
その行のカーソル位置より前のテキストを返すプロパティ
get_word_before_cursor
:
(WORD=True
(default))カーソル前の単語のまとまりを返す(Vimのi_CTRL-W
で消去する文字列のまとまりを返す)
(WORD=False
)カーソル前からスペースまでの文字列を返す
text_before_cursor
その行のカーソル位置より前のテキスト
hogehoge hogege|Hello world!
の場合、
hogehoge hogege
の部分が取得できる
get_word_before_cursor
カーソル前の単語を取得する
WORD
の指定によって、取得する単語が変わる
-
WORD=True
(default) カーソル前の単語のまとまりを返す(Vimのi_CTRL-W
で消去する文字列のまとまりを返す) -
WORD=False
カーソル前からスペースまでの文字列を返す
WORD=False
の場合(default)
取得する文字列の正規表現は_FIND_WORD_RE
となる
_FIND_WORD_RE = re.compile(r'([a-zA-Z0-9_]+|[^a-zA-Z0-9_\s]+)')
以下のどちらかの文字列
- 単語を構成する文字の文字列(
[a-zA-Z0-9_]
は\w
と同じ意味) - 記号の文字列(
[^a-zA-Z0-9_\s]
は[^\w\s]
と同じ意味)
>>> import re
>>> re.findall(r'([a-zA-Z0-9_]+|[^a-zA-Z0-9_\s]+)', 'hoge hoge--hogege guhehe')
['hoge', 'hoge', '--', 'hogege', 'guhehe']
Vimのi_CTRL-W
の単語のまとまりと同じ
WORD=True
の場合
取得する文字列の正規表現は_FIND_BIG_WORD_RE
となる
_FIND_BIG_WORD_RE = re.compile(r'([^\s]+)')
スペース以外の文字の文字列(スペース区切りとなる)
>>> import re
>>> re.findall(r'[^\s]+', 'hoge hoge--hogege guhehe')
['hoge', 'hoge--hogege', 'guhehe']
スペースで区切られた文字列のリストが取得できた
get_word_before_cursor
の処理が面白かったからメモ
- 取得文字列の開始位置をカーソルからの相対位置で取得(
find_start_of_previous_word
を呼び出す)- カーソル前のテキストを反転
-
WORD
によって、取得文字列の正規表現を決める - マッチをテスト
- マッチした文字列の開始位置(反転してるから
end()
で取得) -
-
演算子で負の数で返す(カーソルからの相対位置を返す)
- カーソルの相対位置をもとに、文字列を取得する
>>> import re
# WORD=Falseとして動作確認してみる
>>> regex = re.compile(r'([a-zA-Z0-9_]+|[^a-zA-Z0-9_\s]+)')
# この文字列の末尾にカーソルがあると想定する
>>> text_before_cursor = 'Hello Python'
# 反転
>>> text_before_cursor_reverse = text_before_cursor[::-1]
>>> text_before_cursor_reverse
'nohtyP olleH'
# マッチのテスト
>>> iter = regex.finditer(text_before_cursor_reverse)
# 取得文字列の開始位置をカーソルからの相対位置で取得
>>> start = - next(iter).end(0)
>>> start
-6
# 文字列の取得
>>> text_before_cursor[len(text_before_cursor) + start:]
'Python'
単語とみなす文字列のまとまりを取得するための反転が面白い
def get_word_before_cursor(self, WORD=False, pattern=None):
"""
Give the word before the cursor.
If we have whitespace before the cursor this returns an empty string.
:param pattern: (None or compiled regex). When given, use this regex
pattern.
"""
text_before_cursor = self.text_before_cursor
start = self.find_start_of_previous_word(WORD=WORD, pattern=pattern)
if start is None:
# Space before the cursor or no text before cursor.
return ''
return text_before_cursor[len(text_before_cursor) + start:]
def find_start_of_previous_word(self, count=1, WORD=False, pattern=None):
"""
Return an index relative to the cursor position pointing to the start
of the previous word. Return `None` if nothing was found.
:param pattern: (None or compiled regex). When given, use this regex
pattern.
"""
assert not (WORD and pattern)
# Reverse the text before the cursor, in order to do an efficient
# backwards search.
text_before_cursor = self.text_before_cursor[::-1]
if pattern:
regex = pattern
elif WORD:
regex = _FIND_BIG_WORD_RE
else:
regex = _FIND_WORD_RE
iterator = regex.finditer(text_before_cursor)
try:
for i, match in enumerate(iterator):
if i + 1 == count:
return - match.end(0)
except StopIteration:
pass