AceCentre / MorseWriter

Small app to convert 1 or 2 key presses from morse into text and keyboard-mapped keys
23 stars 4 forks source link

Support abbreviations #38

Closed willwade closed 4 months ago

willwade commented 5 months ago

Custom abbreviations should be supported. We could display this alongside predictions or ignore that.

willwade commented 5 months ago
  1. Store the abbreviation expansions in a file.
  2. Load the abbreviations into the application at startup.
  3. Expand abbreviations as the user types.

Step 1: Store Abbreviations in a File

Create a file called abbreviations.txt in your user data folder with the content as follows:

2moro   tomorrow
u   you
w8  wait
b4  before
c   see
r   are
afaik   as far as I know
asap    as soon as possible
ianal   I am not a lawyer

Step 2: Load Abbreviations into the Application

Add a method to load the abbreviations from the file into a dictionary:

def load_abbreviations(file_path):
    abbreviations = {}
    try:
        with open(file_path, 'r') as f:
            for line in f:
                if line.strip():
                    abbr, expansion = line.strip().split('\t')
                    abbreviations[abbr] = expansion
    except Exception as e:
        logging.error(f"Failed to load abbreviations: {e}")
    return abbreviations

Step 3: Integrate Abbreviation Expansion

Add a method to expand abbreviations in the text:

def expand_abbreviations(text, abbreviations):
    words = text.split()
    expanded_words = [abbreviations.get(word, word) for word in words]
    return ' '.join(expanded_words)

Step 4: Use These Methods in Your Application

Modify your main application code to load the abbreviations and expand them as the user types. You can integrate this functionality within your existing TypeState class or wherever you handle text input.

Here’s an example of how you might modify the TypeState class to include abbreviation expansion:

class TypeState(pressagio.callback.Callback):
    def __init__ (self):
        self.text = ""
        self.predictions = None
        self.presage = pressagio.Pressagio(self, pressagioconfig)
        self.abbreviations = load_abbreviations(os.path.join(os.path.expanduser("~"), "user_data", "abbreviations.txt"))

    def past_stream (self):
        return self.text

    def future_stream (self):
        return self.text

    def pushchar (self, char):
        self.text += char
        self.predictions = None
        logging.debug(f"Updated TypeState text: {self.text}")

    def popchar (self):
        self.text = self.text[:-1]
        self.predictions = None

    def getpredictions(self):
        logging.debug("[TypeState] Fetching predictions for text: {}".format(self.text))
        if self.predictions is None:
            try:
                expanded_text = expand_abbreviations(self.text, self.abbreviations)
                logging.debug("[TypeState] Expanded text: {}".format(expanded_text))
                self.predictions = self.presage.predict()
            except Exception as e:
                logging.error(f"[TypeState] Failed to generate predictions: {str(e)}")
                self.predictions = []
        return self.predictions

Step 5: Modify Input Handling

Ensure the text is expanded before predictions are made or displayed:

def endCharacter(self):
    morse_code = "".join(str(char) for char in self.currentCharacter)
    if self.endCharacterTimer is not None:
        self.endCharacterTimer.stop()
        self.endCharacterTimer = None

    try:
        active_layout = self.layoutManager.get_active_layout()
        items = active_layout.get('items', [])
        item = next((item for item in items if item.get('code') == morse_code), None)
        print(item)

        if item and '_action' in item:
            action = item['_action']
            action.perform()
            logging.info(f"[endCharacter] Action performed for Morse code: {morse_code}")
            if self.config['withsound']:
                play(self.config.get('SoundTyping', 'res/typing_sound.wav'))  # Play typing sound
        else:
            logging.warning(f"[endCharacter] No action found for Morse code: {morse_code}")
    except Exception as e:
        logging.error(f"[endCharacter] Failed to perform action for Morse code: {morse_code}. Error: {e}")
    finally:
        self.currentCharacter = []  # Reset after handling
        expanded_text = expand_abbreviations(self.codeslayoutview.text(), self.abbreviations)
        self.codeslayoutview.setText(expanded_text)
        self.codeslayoutview.reset()

This ensures that as the user types, any recognized abbreviations are automatically expanded.