Created
June 9, 2021 19:46
-
-
Save gs-niteesh/8d025a1f83653282de4e5c137bdd7d51 to your computer and use it in GitHub Desktop.
aqmp_autocomplete_prototype.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import urwid | |
import complete | |
from blinker import Signal | |
import logging | |
logging.basicConfig(filename='log.txt', level=logging.INFO) | |
start_suggestion = Signal() | |
select_suggestion = Signal() | |
reset_suggestion = Signal() | |
load_help_text = Signal() | |
typeable_chars = "abcdefghijklmnopqrstuvwxzyABCDEFGHIJKLMNOPQRSTUVWXZY" | |
class QEdit(urwid.Edit): | |
def __init__(self): | |
super().__init__() | |
def keypress(self, size, key): | |
text = self.get_edit_text() | |
logging.info('QEdit keypress: %s', key) | |
if key in typeable_chars or key == 'backspace': | |
# Send keys to Suggestion Widget. | |
if key == 'backspace' and text: | |
start_suggestion.send(self, text=text[:-1]) | |
else: | |
start_suggestion.send(self, text=text + key) | |
elif key == 'tab': | |
# On pressing tab key, emit signal to inform the suggestion widget | |
# to highlight the suggestion word and move to the next suggestion | |
# word on pressing repeadtly. | |
select_suggestion.send(self, text=text) | |
return | |
elif key == 'enter': | |
# Inform the suggestion widget to select the current highlighted | |
# word and display its help text. | |
load_help_text.send(self) | |
else: | |
reset_suggestion.send(self) | |
return super().keypress(size, key) | |
# Stolen from mitmproxy (slightly modified) | |
class SuggestionsWidget(urwid.Columns): | |
def __init__(self): | |
super().__init__([], dividechars=1) | |
self._last_suggestions = None | |
def populate(self, suggestions): | |
if not suggestions: | |
self.clear() | |
return | |
for item in suggestions: | |
self._append(item, 'suggestion') | |
self._last_suggestions = suggestions | |
def highlight_suggestion(self, index): | |
counter = 0 | |
for col in self.contents: | |
text, attr = col[0].original_widget.get_text() | |
if counter != index: | |
attr = 'suggestion' | |
else: | |
attr = 'suggestion:highlight' | |
col[0].original_widget.set_text((attr, text)) | |
counter += 1 | |
def _append(self, item, style='suggestion'): | |
self.contents.append((urwid.AttrMap(urwid.Text(item), style), | |
self.options('given', len(item), False))) | |
def clear(self): | |
self.contents.clear() | |
class HelpText(urwid.Frame): | |
def __init__(self, master): | |
super().__init__( | |
urwid.LineBox(urwid.Filler(urwid.Text('Show some help text')), | |
title='Help Text')) | |
self.master = master | |
def keypress(self, size, key): | |
if key == 'esc': | |
self.remove_overlay() | |
res = super().keypress(size, key) | |
return res | |
def remove_overlay(self): | |
# This idea of storing reference to master is taken from mitmproxy | |
# Many main widgets in mitmproxy store a reference to the consolemaster | |
# class. | |
self.master.remove_overlay() | |
class Editor(urwid.Frame): | |
def __init__(self): | |
self.edit = QEdit() | |
self.body = urwid.Filler(self.edit, valign='top') | |
self.footer = SuggestionsWidget() | |
start_suggestion.connect(self.start_suggestion) | |
select_suggestion.connect(self.select_suggestion) | |
reset_suggestion.connect(self.reset_suggestion) | |
load_help_text.connect(self.load_help_text) | |
self.showing_suggestions = False | |
self.overlay = HelpText(self) | |
self.idx = 0 | |
super().__init__(self.body, footer=self.footer) | |
def remove_overlay(self): | |
# Should use a proper stack based window management system | |
self.body = self.last_window | |
def load_help_text(self, sender): | |
# Display an simple overlay | |
text = self.footer.contents[self.idx - 1][0].original_widget | |
self.edit.set_edit_text(text.text) | |
self.edit.edit_pos = len(text.text) | |
self.show_help_text() | |
self.footer.clear() | |
def show_help_text(self): | |
self.last_window = self.body | |
self.body = urwid.Overlay(self.overlay, self.body, 'center', | |
('relative', 80), 'top', ('relative', 80)) | |
def reset_suggestion(self, sender): | |
# reset the suggestion widget state | |
if not self.showing_suggestions: | |
return | |
self.footer.clear() | |
self.idx = 0 | |
self.showing_suggestions = False | |
def select_suggestion(self, sender, text): | |
# text - Here we again pass text when no suggestion is shown but the | |
# user presses tab. | |
# Highlightes one of the suggestion words | |
if not text: | |
return | |
if not self.showing_suggestions: | |
self.start_suggestion(self, text) | |
self.footer.highlight_suggestion(self.idx) | |
max_len = len(self.footer.contents) | |
self.idx = 0 if self.idx == max_len - 1 else self.idx + 1 | |
def start_suggestion(self, sender, text=None): | |
# text - Input by user | |
# A simple suggestion mechanism that check if words in the dictionary | |
# start with text | |
logging.info('start_suggestion: %s', text) | |
if self.showing_suggestions: | |
self.idx = 0 | |
self.footer.clear() | |
suggestions = [] | |
if not text: | |
self.footer.clear() | |
self.showing_suggestions = False | |
return | |
for word in complete.suggestions: | |
word = word.lower() | |
if word.startswith(text): | |
suggestions.append(word) | |
self.footer.populate(suggestions) | |
self.showing_suggestions = True | |
class App: | |
def __init__(self): | |
self.widget = Editor() | |
palette = [ | |
('highlight', 'black', 'light gray'), | |
('suggestion', '', ''), | |
('suggestion:highlight', 'light red', ''), | |
] | |
self.loop = urwid.MainLoop(self.widget, palette=palette) | |
def run(self): | |
self.loop.run() | |
if __name__ == '__main__': | |
logging.info('Starting App') | |
App().run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
suggestions = [ | |
"Acumen", | |
"Adhere", | |
"Abolish", | |
"Abash", | |
"Abound", | |
"Abate", | |
"Abject", | |
"Abjure", | |
"Abortive", | |
"Absolve", | |
"Accord", | |
"Acrimony", | |
"Adamant", | |
"Adherent", | |
"Adjunct", | |
"Admonish", | |
"Adversity", | |
"Alien", | |
"Allay", | |
"Alleviate", | |
"Allure", | |
"Ascend", | |
"Amplify", | |
"Arraign", | |
"Audacity", | |
"Authentic", | |
"Awkward", | |
"Axiom", | |
"Baffle", | |
"Bewitching", | |
"Bleak", | |
"Brittle", | |
"Bustle", | |
"Barbarous", | |
"Baroque", | |
"Barren", | |
"Barrier", | |
"Base", | |
"Batty", | |
"Bawdy", | |
"Befogged", | |
"Benevolent", | |
"Benign", | |
"Bind", | |
"Bleak", | |
"Blunt", | |
"Boisterous", | |
"Bold", | |
"Busy", | |
"Calculating", | |
"Calamity", | |
"Callous", | |
"Calumny", | |
"Capable", | |
"Captivate", | |
"Captivity", | |
"Cease", | |
"Chaste", | |
"Chastise", | |
"Compassion", | |
"Comprise", | |
"Concede", | |
"Concur", | |
"Consent", | |
"Consequence", | |
"Consolidate", | |
"Conspicuous", | |
"Contempt", | |
"Contradict", | |
"Contrary", | |
"Calm", | |
"Callous", | |
"Camouflage", | |
"Candid", | |
"Captivate", | |
"Carnal", | |
"Catholic", | |
"Celebrated", | |
"Cement", | |
"Censure", | |
"Cheap", | |
"Clandestine", | |
"Classic", | |
"Coarse", | |
"Comic", | |
"Compact", | |
"Compress", | |
"Conceit", | |
"Concord", | |
"Condemn", | |
"Confident", | |
"Consolidate", | |
"Courtesy", | |
"Creation", | |
"Cunning", | |
"Decay", | |
"Deceit", | |
"Decipher", | |
"Defile", | |
"Defray", | |
"Deliberate", | |
"Demolish", | |
"Deprive", | |
"Deride", | |
"Disdain", | |
"Dissuade", | |
"Denounce", | |
"Dense", | |
"Derogatory", | |
"Despair", | |
"Destructive", | |
"Docile", | |
"Dwarf", | |
"Eager", | |
"Eclipse", | |
"Eccentric", | |
"Ecstasy", | |
"Efface", | |
"Eloquence", | |
"Encumbrance", | |
"Endeavour", | |
"Enormous", | |
"Epitome", | |
"Equivocal", | |
"Eradicate", | |
"Fabricate", | |
"Fallacy", | |
"Falter", | |
"Fanatical", | |
"Feeble", | |
"Ferocious", | |
"Feud", | |
"Fluctuate", | |
"Forsake", | |
"Fragile", | |
"Frantic", | |
"Frivolous", | |
"Frugality", | |
"Gather", | |
"Gloom", | |
"Glut", | |
"Gorgeous", | |
"Gracious", | |
"Grisly", | |
"Grudge", | |
"Guile", | |
"Generosity", | |
"Genuine", | |
"Gloomy", | |
"Glory", | |
"Hamper", | |
"Hapless", | |
"Harass", | |
"Haughty", | |
"Hazard", | |
"Heretic", | |
"Hideous", | |
"Hamstrung", | |
"Harmony", | |
"Hasty", | |
"Honor", | |
"Humble", | |
"Humility", | |
"Hypocrisy", | |
"Impenitent", | |
"Impulsive", | |
"Indifferent", | |
"Indigent", | |
"Infernal", | |
"Insipid", | |
"Interesting", | |
"Immaculate", | |
"Immense", | |
"Immerse", | |
"Imminent", | |
"Immunity", | |
"Impair", | |
"Impartial", | |
"Impediment", | |
"Impious", | |
"Impute", | |
"Inclination", | |
"Incompetent", | |
"Incongruous", | |
"Inevitable", | |
"Infringe", | |
"Ingenuous", | |
"Insinuate", | |
"Insipid", | |
"Insolvent", | |
"Instill", | |
"Intricate", | |
"Intrigue", | |
"Intrinsic", | |
"Invective", | |
"Invincible", | |
"Irrepressible", | |
"Immaculate", | |
"Jaded", | |
"Jejune", | |
"Jovial", | |
"Jubilant", | |
"Judicious", | |
"Just", | |
"Justify", | |
"Juvenile", | |
"Keen", | |
"Kindred", | |
"Knave", | |
"Knell", | |
"Knotty", | |
"Lavish", | |
"Lax", | |
"Lenient", | |
"Liable", | |
"Liberal", | |
"Linger", | |
"Lucid", | |
"Lunacy", | |
"Lure", | |
"Luscious", | |
"Luxuriant", | |
"Languid", | |
"Malice", | |
"Mandatory", | |
"Masculine", | |
"Merit", | |
"Miraculous", | |
"Mitigate", | |
"Modest", | |
"Molest", | |
"Mollify", | |
"Momentous", | |
"Monotonous", | |
"Morbid", | |
"Munificent", | |
"Murky", | |
"Mutinous", | |
"Mutual", | |
"Niggardly", | |
"Nimble", | |
"Nonchalant", | |
"Novice", | |
"Noxious", | |
"Nullify", | |
"Notion", | |
"Numerous", | |
"Obstruct", | |
"Obliging", | |
"Obscure", | |
"Obstinate", | |
"Obtain", | |
"Obvious", | |
"Odious", | |
"Offensive", | |
"Occult", | |
"Offspring", | |
"Ominous", | |
"Opaque", | |
"Optimist", | |
"Oracular", | |
"Ordain", | |
"Ornamental", | |
"Outbreak", | |
"Outrage", | |
"Pacify", | |
"Persuade", | |
"Perturbed", | |
"Propagate", | |
"Progress", | |
"Prompt", | |
"Prudence", | |
"Pamper", | |
"Paramount", | |
"Peerless", | |
"Peevish", | |
"Pertness", | |
"Perverse", | |
"Placid", | |
"Pompous", | |
"Precarious", | |
"Predicament", | |
"Quack", | |
"Quaint", | |
"Quarantine", | |
"Quell", | |
"Quibble", | |
"Raid", | |
"Rapidity", | |
"Reason", | |
"Rebellious", | |
"Rectify", | |
"Reluctant", | |
"Restrain", | |
"Ratify", | |
"Ravage", | |
"Redeem", | |
"Remnant", | |
"Remonstrate", | |
"Remorse", | |
"Rescind", | |
"Resentment", | |
"Retract", | |
"Reverence", | |
"Rout", | |
"Rustic", | |
"Ruthless", | |
"Sacred", | |
"Savage", | |
"Startled", | |
"Steep", | |
"Stranger", | |
"Sublime", | |
"Succinct", | |
"Sympathy", | |
"System", | |
"Sarcastic", | |
"Saucy", | |
"Shrewd", | |
"Scanty", | |
"Servile", | |
"Shabby", | |
"Slander", | |
"Sneer", | |
"Solicit", | |
"Subterfuge", | |
"Stain", | |
"Spurious", | |
"Sporadic", | |
"Spry", | |
"Squalid", | |
"Successful", | |
"Sterile", | |
"Stupor", | |
"Subsequent", | |
"Substantial", | |
"Subvert", | |
"Superficial", | |
"Sycophant", | |
"Taboo", | |
"Taciturn", | |
"Tedious", | |
"Temperate", | |
"Tenement", | |
"Tenacious", | |
"Throng", | |
"Timid", | |
"Tranquil", | |
"Transient", | |
"Trenchant", | |
"Treacherous", | |
"Trivial", | |
"Tumultuous", | |
"Tyro", | |
"Tame", | |
"Terse", | |
"Thick", | |
"Thrifty", | |
"Tranquil", | |
"Transparent", | |
"Tremble", | |
"Uncouth", | |
"Utterly", | |
"Umbrage", | |
"Uncouth", | |
"Urchin", | |
"Urge", | |
"Vain", | |
"Vagrant", | |
"Valor", | |
"Vanity", | |
"Venerable", | |
"Venom", | |
"Veteran", | |
"Vicious", | |
"Vigilant", | |
"Vivacious", | |
"Vilify", | |
"Vouch", | |
"Virtue", | |
"Vivid", | |
"Waive", | |
"Wan", | |
"Wane", | |
"Wary", | |
"Wed", | |
"Wicked", | |
"Wield", | |
"Wile", | |
"Winsome", | |
"Wilt", | |
"Yell", | |
"Yield", | |
"Yearn", | |
"Yoke", | |
"Zeal", | |
"Zenith", | |
"Zest", | |
"Zig", | |
"zag" | |
] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment