|
|
from pathlib import Path
|
|
|
|
|
|
from IPython.terminal.shortcuts import create_ipython_shortcuts
|
|
|
|
|
|
def name(c):
|
|
|
s = c.__class__.__name__
|
|
|
if s == '_Invert':
|
|
|
return '(Not: %s)' % name(c.filter)
|
|
|
if s in log_filters.keys():
|
|
|
return '(%s: %s)' % (log_filters[s], ', '.join(name(x) for x in c.filters))
|
|
|
return log_filters[s] if s in log_filters.keys() else s
|
|
|
|
|
|
|
|
|
def sentencize(s):
|
|
|
"""Extract first sentence
|
|
|
"""
|
|
|
s = s.replace('\n', ' ').strip().split('.')
|
|
|
s = s[0] if len(s) else s
|
|
|
try:
|
|
|
return " ".join(s.split())
|
|
|
except AttributeError:
|
|
|
return s
|
|
|
|
|
|
|
|
|
def most_common(lst, n=3):
|
|
|
"""Most common elements occurring more then `n` times
|
|
|
"""
|
|
|
from collections import Counter
|
|
|
|
|
|
c = Counter(lst)
|
|
|
return [k for (k, v) in c.items() if k and v > n]
|
|
|
|
|
|
|
|
|
def multi_filter_str(flt):
|
|
|
"""Yield readable conditional filter
|
|
|
"""
|
|
|
assert hasattr(flt, 'filters'), 'Conditional filter required'
|
|
|
yield name(flt)
|
|
|
|
|
|
|
|
|
log_filters = {'_AndList': 'And', '_OrList': 'Or'}
|
|
|
log_invert = {'_Invert'}
|
|
|
|
|
|
class _DummyTerminal:
|
|
|
"""Used as a buffer to get prompt_toolkit bindings
|
|
|
"""
|
|
|
handle_return = None
|
|
|
input_transformer_manager = None
|
|
|
display_completions = None
|
|
|
editing_mode = "emacs"
|
|
|
|
|
|
|
|
|
ipy_bindings = create_ipython_shortcuts(_DummyTerminal()).bindings
|
|
|
|
|
|
dummy_docs = [] # ignore bindings without proper documentation
|
|
|
|
|
|
common_docs = most_common([kb.handler.__doc__ for kb in ipy_bindings])
|
|
|
if common_docs:
|
|
|
dummy_docs.extend(common_docs)
|
|
|
|
|
|
dummy_docs = list(set(dummy_docs))
|
|
|
|
|
|
single_filter = {}
|
|
|
multi_filter = {}
|
|
|
for kb in ipy_bindings:
|
|
|
doc = kb.handler.__doc__
|
|
|
if not doc or doc in dummy_docs:
|
|
|
continue
|
|
|
|
|
|
shortcut = ' '.join([k if isinstance(k, str) else k.name for k in kb.keys])
|
|
|
shortcut += shortcut.endswith('\\') and '\\' or ''
|
|
|
if hasattr(kb.filter, 'filters'):
|
|
|
flt = ' '.join(multi_filter_str(kb.filter))
|
|
|
multi_filter[(shortcut, flt)] = sentencize(doc)
|
|
|
else:
|
|
|
single_filter[(shortcut, name(kb.filter))] = sentencize(doc)
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
here = Path(__file__).parent
|
|
|
dest = here / "source" / "config" / "shortcuts"
|
|
|
|
|
|
def sort_key(item):
|
|
|
k, v = item
|
|
|
shortcut, flt = k
|
|
|
return (str(shortcut), str(flt))
|
|
|
|
|
|
for filters, output_filename in [
|
|
|
(single_filter, "single_filtered"),
|
|
|
(multi_filter, "multi_filtered"),
|
|
|
]:
|
|
|
with (dest / "{}.csv".format(output_filename)).open(
|
|
|
"w", encoding="utf-8"
|
|
|
) as csv:
|
|
|
for (shortcut, flt), v in sorted(filters.items(), key=sort_key):
|
|
|
csv.write(":kbd:`{}`\t{}\t{}\n".format(shortcut, flt, v))
|
|
|
|