diff --git a/cubedeck.py b/cubedeck.py new file mode 100644 index 0000000..3475221 --- /dev/null +++ b/cubedeck.py @@ -0,0 +1,164 @@ +# Usage: +# +# Download cube list .txt from CubeCobra's export to .txt function +# +# $ python3 cubedeck.py MyCubeList.txt +# +# +# +# Enter card: Mo [tab] +# Mogg War Marshal Moment's Peace Monastery Swiftspear Mortarpod Mountain +# Moldervine Cloak Momentary Blink Monoskelion Mortify +# +# Enter card: Moldervine Cloak +# +# Enter card: Moment's Peace +# +# Enter card: Momentary Blink +# +# Enter card: :u # Undo last card added (Momentary Blink) +# +# Enter card: :nl # Add empty line to separate sideboard +# +# Enter card: Monoskelion +# +# Enter card: 10 Forest # autocomplete doesn't work with number +# +# Enter card: :ls # List deck input so far +# ['Moldervine Cloak', 'Moment's Peace', '', 'Monoskelion', '10 Forest'] +# +# Enter card: :wq # Save to file and open in default application +# Saved deck to 20230425-001458.txt +# +# Enter card: :q # Exit without saving + +from datetime import datetime + +import os +import platform +import readline +import sys +import subprocess + + +def load_cube(cube_file): + cube = [] + with open(cube_file) as f: + for line in f: + card = line.strip() + if card: + cube.append(card) + return cube + + +BASIC_LANDS = ['Plains', 'Island', 'Swamp', 'Mountain', 'Forest'] +CUBE_CARDS = load_cube(sys.argv[1]) +CARDS = BASIC_LANDS + CUBE_CARDS +CARDS_LOWER = {card.lower(): card for card in CARDS} + + +def open_file_with_default(file): + if platform.system() == 'Darwin': # macOS + subprocess.call(('open', file)) + elif platform.system() == 'Windows': # Windows + os.startfile(file) + else: # linux variants + if 'microsoft' in platform.uname().release.lower(): + subprocess.call(('wslview', file)) # WSL + else: + subprocess.call(('xdg-open', file)) # Actual linux + + +def enable_autocomplete(): + if 'libedit' in readline.__doc__: + readline.parse_and_bind("bind ^I rl_complete") + else: + readline.parse_and_bind("tab: complete") + + +def card_completer(text, state): + text_to_complete = readline.get_line_buffer().lower() + options = [CARDS_LOWER[i] for i in CARDS_LOWER if i.startswith(text_to_complete)] + if state < len(options): + return options[state][readline.get_begidx():] + else: + return None + + +def add_card(deck, card): + count_str = None + card_to_check = card + if card[0].isdigit(): + parts = card.split(' ', 1) + if len(parts) > 1 and parts[0].isdigit(): + count_str = parts[0] + card_to_check = parts[1] + + card_canon = card_to_check.lower() + if card_canon not in CARDS_LOWER: + yn = input('"%s" not in cardlist. Are you sure you want to add it to the deck? ' % card_to_check) + if not yn.strip().startswith('y'): + print('Not added.') + return + + add_card_with_count(deck, card_canon, count_str) + + +def add_card_with_count(deck, card_canon, count_str): + card = CARDS_LOWER.get(card_canon, card_canon) + if count_str is None: + deck.append(card) + else: + deck.append('%s %s' % (count_str, card)) + + +def add_delimiter(deck): + deck.append('') + + +def remove_last_card(deck): + if len(deck) == 0: + print('Empty deck, cannot delete.') + return + + deck.pop() + + +def save_deck(deck): + file_name = datetime.today().strftime('%Y%m%d-%H%M%S') + '.txt' + with open(file_name, 'w') as f: + for card in deck: + f.write(card) + f.write('\n') + print('Saved deck to %s' % file_name) + open_file_with_default(file_name) + + +if __name__ == '__main__': + deck = [] + enable_autocomplete() + readline.set_completer(card_completer) + readline.set_completer_delims('') + + while True: + command = input('Enter card: ').strip() + + if command == '': + continue + if command == ':q': + print('Exiting without saving.') + exit(0) + elif command == ':wq': + save_deck(deck) + exit(0) + elif command == ':l': + print(deck) + elif command == ':nl': + add_delimiter(deck) + elif command == ':u': + remove_last_card(deck) + elif command.startswith(':'): + print('Unrecognized command "%s"' % command) + else: + add_card(deck, command) +