15 Commits

Author SHA1 Message Date
Storm Dragon
aabc202d83 Latest version of configure_pipewire.sh tested and appears to work. 2025-10-17 22:19:58 -04:00
Storm Dragon
2f3a114790 Pipewire configuration tool updated. In a bout of pure insanity I tested this on my production system and it worked without a hitch, so should be good to go. 2025-10-17 22:19:30 -04:00
Storm Dragon
c797974560 Pre tag release. If no problems reported this will become the new stable release. 2025-10-17 21:27:36 -04:00
Storm Dragon
af4740d5ad Various minor fixes in preparation for new release. 2025-10-17 21:26:13 -04:00
Storm Dragon
5ef5faaebe Progressbar tweaks. 2025-10-17 21:03:12 -04:00
Storm Dragon
7041d2567a Progress bar updates. 2025-09-26 18:07:35 -04:00
Storm Dragon
2c38bcf5f4 Another attempt at fixing external numpad detection. I *think* some of them send numlock state with every event. If that's the case, this should fix it. 2025-09-13 14:11:27 -04:00
Storm Dragon
96cdda99c4 Separate menu entries for some settings, improves usability. Fixed device detection for devices that do not contain what they do in their name, e.g. numpads that are not listed as numpads. This hopefully fixes a bug with some external numpads. 2025-09-12 12:09:00 -04:00
Storm Dragon
0658d37ae8 I don't wanna say this too loud, but I think tab completion is much more reliable now. No more not reading when you press tab and something appears. 2025-08-31 20:45:32 -04:00
Storm Dragon
a6bb3e1301 A bit of code cleanup. Nothing should be changed at all functionally. 2025-08-31 20:30:06 -04:00
Storm Dragon
5ff653bd00 Progress bar and commit validator updates. 2025-08-31 14:54:07 -04:00
Storm Dragon
356f4b01c1 Got the version file wrong again. Need to be more careful. 2025-08-31 14:44:46 -04:00
Storm Dragon
c7ad4d9200 merged to master. 2025-08-31 14:39:26 -04:00
Storm Dragon
d274fe78f3 Rebind the keyboard layout switcher to fenrir+control+f4. 2025-08-31 14:37:48 -04:00
Storm Dragon
f5344a7227 removing keyboard layouts that are no longer used 2025-08-23 18:30:35 -04:00
139 changed files with 1245 additions and 462 deletions

View File

@@ -130,4 +130,4 @@ KEY_FENRIR,KEY_F8=export_clipboard_to_x
KEY_FENRIR,KEY_CTRL,KEY_DOWN=read_all_by_line
KEY_FENRIR,KEY_CTRL,KEY_PAGEDOWN=read_all_by_page
KEY_FENRIR,KEY_SHIFT,KEY_V=announce_fenrir_version
KEY_F4=cycle_keyboard_layout
KEY_FENRIR,KEY_LEFTCTRL,KEY_F4=cycle_keyboard_layout

View File

@@ -130,4 +130,4 @@ KEY_FENRIR,KEY_F8=export_clipboard_to_x
KEY_FENRIR,KEY_CTRL,KEY_DOWN=read_all_by_line
KEY_FENRIR,KEY_CTRL,KEY_PAGEDOWN=read_all_by_page
KEY_FENRIR,KEY_SHIFT,KEY_V=announce_fenrir_version
KEY_F4=cycle_keyboard_layout
KEY_FENRIR,KEY_LEFTCTRL,KEY_F4=cycle_keyboard_layout

View File

@@ -67,4 +67,4 @@ class command:
def set_callback(self, callback):
pass
pass

View File

@@ -62,4 +62,4 @@ class command:
def set_callback(self, callback):
pass
pass

View File

@@ -4,7 +4,7 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.
import time
from fenrirscreenreader.core.i18n import _
@@ -14,55 +14,150 @@ class command:
def initialize(self, environment):
self.env = environment
# Initialize tab completion state tracking
if "tabCompletion" not in self.env["commandBuffer"]:
self.env["commandBuffer"]["tabCompletion"] = {
"lastTabTime": 0,
"pendingCompletion": None,
"retryCount": 0
}
def shutdown(self):
pass
def get_description(self):
return "No Description found"
return _("Announces tab completions when detected")
def _is_recent_tab_input(self):
"""Check if TAB was pressed recently (within 200ms window)"""
current_time = time.time()
tab_detected = False
# Check KEY mode
if self.env["runtime"]["InputManager"].get_shortcut_type() in ["KEY"]:
if (self.env["runtime"]["InputManager"].get_last_deepest_input()
in [["KEY_TAB"]]):
tab_detected = True
self.env["commandBuffer"]["tabCompletion"]["lastTabTime"] = current_time
# Check BYTE mode
elif self.env["runtime"]["InputManager"].get_shortcut_type() in ["BYTE"]:
for currByte in self.env["runtime"]["ByteManager"].get_last_byte_key():
if currByte == 9: # Tab character
tab_detected = True
self.env["commandBuffer"]["tabCompletion"]["lastTabTime"] = current_time
# Check if tab was pressed recently (200ms window)
if not tab_detected:
time_since_tab = current_time - self.env["commandBuffer"]["tabCompletion"]["lastTabTime"]
if time_since_tab <= 0.2: # 200ms window
tab_detected = True
return tab_detected
def _is_flexible_completion_match(self, x_move, delta_text):
"""Use flexible matching instead of strict equality"""
if not delta_text:
return False
delta_len = len(delta_text)
# Exact match (preserve original behavior)
if x_move == delta_len:
return True
# Flexible range: allow ±2 characters difference
# Handles spacing adjustments and unicode width variations
if abs(x_move - delta_len) <= 2 and delta_len > 0:
return True
# For longer completions, allow proportional variance
if delta_len > 10 and abs(x_move - delta_len) <= (delta_len * 0.2):
return True
return False
def _detect_completion_patterns(self, delta_text):
"""Detect common tab completion patterns for improved accuracy"""
if not delta_text:
return False
delta_stripped = delta_text.strip()
# File extension completion
if '.' in delta_stripped and delta_stripped.count('.') <= 2:
return True
# Path completion (contains / or \)
if '/' in delta_stripped or '\\' in delta_stripped:
return True
# Command parameter completion (starts with -)
if delta_stripped.startswith('-') and len(delta_stripped) > 1:
return True
# Word boundary completion (alphanumeric content)
if delta_stripped.isalnum() and len(delta_stripped) >= 2:
return True
return False
def run(self):
# try to detect the tab completion by cursor change
"""Enhanced tab completion detection with improved reliability"""
# Basic cursor movement check (preserve original logic)
x_move = (
self.env["screen"]["new_cursor"]["x"]
- self.env["screen"]["old_cursor"]["x"]
)
if x_move <= 0:
return
if self.env["runtime"]["InputManager"].get_shortcut_type() in ["KEY"]:
if not (
self.env["runtime"]["InputManager"].get_last_deepest_input()
in [["KEY_TAB"]]
):
if x_move < 5:
return
elif self.env["runtime"]["InputManager"].get_shortcut_type() in [
"BYTE"
]:
found = False
for currByte in self.env["runtime"][
"ByteManager"
].get_last_byte_key():
if currByte == 9:
found = True
if not found:
if x_move < 5:
return
# is there any change?
# Enhanced tab input detection with persistence
tab_detected = self._is_recent_tab_input()
# Fallback for non-tab movements (preserve original thresholds)
if not tab_detected:
if x_move < 5:
return
# Screen delta availability check
if not self.env["runtime"]["ScreenManager"].is_delta():
# If tab was detected but no delta yet, store for potential retry
if tab_detected and self.env["commandBuffer"]["tabCompletion"]["retryCount"] < 2:
self.env["commandBuffer"]["tabCompletion"]["pendingCompletion"] = {
"x_move": x_move,
"timestamp": time.time()
}
self.env["commandBuffer"]["tabCompletion"]["retryCount"] += 1
return
if not x_move == len(self.env["screen"]["new_delta"]):
return
# filter unneded space on word begin
curr_delta = self.env["screen"]["new_delta"]
if (
len(curr_delta.strip()) != len(curr_delta)
and curr_delta.strip() != ""
):
delta_text = self.env["screen"]["new_delta"]
# Enhanced correlation checking with flexible matching
if not self._is_flexible_completion_match(x_move, delta_text):
# Additional pattern-based validation for edge cases
if not (tab_detected and self._detect_completion_patterns(delta_text)):
return
# Reset retry counter on successful detection
self.env["commandBuffer"]["tabCompletion"]["retryCount"] = 0
self.env["commandBuffer"]["tabCompletion"]["pendingCompletion"] = None
# Mark that we've handled this delta to prevent duplicate announcements
# This prevents the incoming text handler from also announcing the same content
self.env["commandBuffer"]["tabCompletion"]["lastProcessedDelta"] = delta_text
self.env["commandBuffer"]["tabCompletion"]["lastProcessedTime"] = time.time()
# Text filtering and announcement (preserve original behavior)
curr_delta = delta_text
if (len(curr_delta.strip()) != len(curr_delta) and curr_delta.strip() != ""):
curr_delta = curr_delta.strip()
self.env["runtime"]["OutputManager"].present_text(
curr_delta, interrupt=True, announce_capital=True, flush=False
)
# Enhanced announcement with better handling of empty completions
if curr_delta:
self.env["runtime"]["OutputManager"].present_text(
curr_delta, interrupt=True, announce_capital=True, flush=False
)
def set_callback(self, callback):
pass

View File

@@ -0,0 +1,128 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.
import time
from fenrirscreenreader.core.i18n import _
class command:
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
def shutdown(self):
pass
def get_description(self):
return _("Handles delayed retry for tab completion detection")
def run(self):
"""Check for and process pending tab completions with slight delay"""
# Only process if we have tab completion state
if "tabCompletion" not in self.env["commandBuffer"]:
return
tab_state = self.env["commandBuffer"]["tabCompletion"]
pending = tab_state.get("pendingCompletion")
if not pending:
return
current_time = time.time()
# Process pending completion after 50ms delay
if current_time - pending["timestamp"] < 0.05:
return
# Check if screen delta is now available
if not self.env["runtime"]["ScreenManager"].is_delta():
# Give up after 200ms total
if current_time - pending["timestamp"] > 0.2:
tab_state["pendingCompletion"] = None
tab_state["retryCount"] = 0
return
# Process the delayed completion
delta_text = self.env["screen"]["new_delta"]
x_move = pending["x_move"]
# Use the same flexible matching logic as main tab completion
match_found = self._is_flexible_completion_match(x_move, delta_text)
if not match_found:
# Try pattern-based detection as final fallback
match_found = self._detect_completion_patterns(delta_text)
if match_found and delta_text:
# Mark that we've handled this delta to prevent duplicate announcements
tab_state["lastProcessedDelta"] = delta_text
tab_state["lastProcessedTime"] = current_time
# Filter and announce the completion
curr_delta = delta_text
if (len(curr_delta.strip()) != len(curr_delta) and
curr_delta.strip() != ""):
curr_delta = curr_delta.strip()
if curr_delta:
self.env["runtime"]["OutputManager"].present_text(
curr_delta, interrupt=True, announce_capital=True, flush=False
)
# Clear pending completion
tab_state["pendingCompletion"] = None
tab_state["retryCount"] = 0
def _is_flexible_completion_match(self, x_move, delta_text):
"""Use flexible matching (duplicated from main command for heartbeat use)"""
if not delta_text:
return False
delta_len = len(delta_text)
# Exact match
if x_move == delta_len:
return True
# Flexible range: allow ±2 characters difference
if abs(x_move - delta_len) <= 2 and delta_len > 0:
return True
# For longer completions, allow proportional variance
if delta_len > 10 and abs(x_move - delta_len) <= (delta_len * 0.2):
return True
return False
def _detect_completion_patterns(self, delta_text):
"""Detect common tab completion patterns (duplicated from main command)"""
if not delta_text:
return False
delta_stripped = delta_text.strip()
# File extension completion
if '.' in delta_stripped and delta_stripped.count('.') <= 2:
return True
# Path completion
if '/' in delta_stripped or '\\' in delta_stripped:
return True
# Command parameter completion
if delta_stripped.startswith('-') and len(delta_stripped) > 1:
return True
# Word boundary completion
if delta_stripped.isalnum() and len(delta_stripped) >= 2:
return True
return False
def set_callback(self, callback):
pass

View File

@@ -24,11 +24,22 @@ class command:
def run(self):
if self.env["input"]["oldNumLock"] == self.env["input"]["newNumLock"]:
return
# Only announce numlock changes if an actual numlock key was pressed
# This prevents spurious announcements from external numpad automatic state changes
# AND the LED state actually changed (some numpads send spurious NUMLOCK events)
current_input = self.env["input"]["currInput"]
if current_input and "KEY_NUMLOCK" in current_input:
# Check if this is a genuine numlock key press by verifying:
# 1. KEY_NUMLOCK is in the current input sequence
# 2. The LED state has actually changed
# 3. This isn't just a side effect from a KP_ key (which some buggy numpads do)
is_genuine_numlock = (
current_input and
"KEY_NUMLOCK" in current_input and
not any(key.startswith("KEY_KP") for key in current_input if isinstance(key, str))
)
if is_genuine_numlock:
if self.env["input"]["newNumLock"]:
self.env["runtime"]["OutputManager"].present_text(
_("Numlock on"), interrupt=True

View File

@@ -66,12 +66,18 @@ class command:
# Check if delta is too large (screen change) vs small incremental
# updates
delta_length = len(self.env["screen"]["new_delta"])
delta_text = self.env["screen"]["new_delta"]
delta_length = len(delta_text)
if (
delta_length > 200
): # Allow longer progress lines like Claude Code's status
return False
# If delta contains newlines and is substantial, let incoming handler
# deal with it to avoid interfering with multi-line text output
if '\n' in delta_text and delta_length > 50:
return False
# Check if current line looks like a prompt - progress unlikely during
# prompts
if self.is_current_line_prompt():
@@ -270,7 +276,7 @@ class command:
self.env["commandBuffer"]["lastProgressTime"] = current_time
return
# Pattern 5: Braille progress indicators
# Pattern 5: Braille spinner indicators
braille_match = re.search(r'[⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏⡿⣟⣯⣷⣾⣽⣻⢿]', text)
if braille_match:
if current_time - self.env["commandBuffer"]["lastProgressTime"] >= 1.0:
@@ -279,26 +285,46 @@ class command:
return
# Pattern 6: Claude Code progress indicators
claude_progress_match = re.search(r'^[·✶✢✻*]\s+[\w\s-]+[…\.]*\s*\(esc to interrupt\)\s*$', text)
claude_progress_match = re.search(r'[·✶✢✻*].*?\(esc to interrupt[^)]*\)', text)
if claude_progress_match:
if current_time - self.env["commandBuffer"]["lastProgressTime"] >= 1.0:
self.play_activity_beep()
self.env["commandBuffer"]["lastProgressTime"] = current_time
return
# Pattern 7: Moon phase progress indicators
# Pattern 7: Moon phase spinner indicators
moon_match = re.search(r'[🌑🌒🌓🌔🌕🌖🌗🌘]', text)
if moon_match:
moon_phases = {
'🌑': 0, '🌒': 12.5, '🌓': 25, '🌔': 37.5,
'🌕': 50, '🌖': 62.5, '🌗': 75, '🌘': 87.5
}
moon_char = moon_match.group(0)
if moon_char in moon_phases:
percentage = moon_phases[moon_char]
if percentage != self.env["commandBuffer"]["lastProgressValue"]:
self.play_progress_tone(percentage)
self.env["commandBuffer"]["lastProgressValue"] = percentage
if current_time - self.env["commandBuffer"]["lastProgressTime"] >= 1.0:
self.play_activity_beep()
self.env["commandBuffer"]["lastProgressTime"] = current_time
return
# Pattern 8: Thinking/processing with timing (🔄 Thinking... 23s)
thinking_match = re.search(r'🔄[^\w]*(?:thinking|processing|working|analyzing)[^\d]*(\d+)s?\b', text, re.IGNORECASE)
if thinking_match:
# Extract timing value for activity beep frequency adjustment
seconds = int(thinking_match.group(1))
# Use slightly longer interval for thinking patterns to avoid spam
thinking_interval = 1.5 if seconds < 10 else 2.0
if (
current_time - self.env["commandBuffer"]["lastProgressTime"]
>= thinking_interval
):
self.env["runtime"]["DebugManager"].write_debug_out(
f"Playing thinking activity beep (timing: {seconds}s)",
debug.DebugLevel.INFO,
)
self.play_activity_beep()
self.env["commandBuffer"]["lastProgressTime"] = current_time
return
# Pattern 9: Half-circle/circle progress indicators (◐ ◓ ◒ ◑)
circle_match = re.search(r'[◐◓◒◑]', text)
if circle_match:
if current_time - self.env["commandBuffer"]["lastProgressTime"] >= 1.0:
self.play_activity_beep()
self.env["commandBuffer"]["lastProgressTime"] = current_time
return
def play_progress_tone(self, percentage):

View File

@@ -4,7 +4,7 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.
import time
from fenrirscreenreader.core.i18n import _
@@ -19,7 +19,26 @@ class command:
pass
def get_description(self):
return "No Description found"
return _("Announces incoming text changes")
def _was_handled_by_tab_completion(self, delta_text):
"""Check if this delta was already handled by tab completion to avoid duplicates"""
if "tabCompletion" not in self.env["commandBuffer"]:
return False
tab_state = self.env["commandBuffer"]["tabCompletion"]
# Check if this exact delta was processed recently by tab completion
if (tab_state.get("lastProcessedDelta") == delta_text and
tab_state.get("lastProcessedTime")):
# Only suppress if processed within the last 50ms to avoid stale suppression
# Reduced from 100ms to minimize false positives with rapid multi-line updates
time_since_processed = time.time() - tab_state["lastProcessedTime"]
if time_since_processed <= 0.05:
return True
return False
def run(self):
if not self.env["runtime"]["SettingsManager"].get_setting_as_bool(
@@ -30,6 +49,12 @@ class command:
if not self.env["runtime"]["ScreenManager"].is_delta(ignoreSpace=True):
return
delta_text = self.env["screen"]["new_delta"]
# Skip if tab completion already handled this delta
if self._was_handled_by_tab_completion(delta_text):
return
# this must be a keyecho or something
# if len(self.env['screen']['new_delta'].strip(' \n\t')) <= 1:
x_move = abs(
@@ -41,14 +66,14 @@ class command:
- self.env["screen"]["old_cursor"]["y"]
)
if (x_move >= 1) and x_move == len(self.env["screen"]["new_delta"]):
if (x_move >= 1) and x_move == len(delta_text):
# if len(self.env['screen']['new_delta'].strip(' \n\t0123456789'))
# <= 2:
if "\n" not in self.env["screen"]["new_delta"]:
if "\n" not in delta_text:
return
# print(x_move, y_move, len(self.env['screen']['new_delta']), len(self.env['screen']['newNegativeDelta']))
self.env["runtime"]["OutputManager"].present_text(
self.env["screen"]["new_delta"], interrupt=False, flush=False
delta_text, interrupt=False, flush=False
)
def set_callback(self, callback):

View File

@@ -1 +1 @@
# Emoji VMenu category
# Emoji VMenu category

View File

@@ -1 +1 @@
# Flags emoji subcategory
# Flags emoji subcategory

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added Canada flag to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added UK flag to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added USA flag to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -1 +1 @@
# Food emoji subcategory
# Food emoji subcategory

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added red apple to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added avocado to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added beer to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added birthday cake to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added coffee to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added donut to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added hamburger to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added pizza to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added strawberry to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added taco to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -1 +1 @@
# Holidays emoji subcategory
# Holidays emoji subcategory

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added alien monster to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added bat to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added black cat to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added bunny to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added mage to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added Christmas tree to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added coffin to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added Easter egg to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added fireworks to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added ghost to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added gift to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added jack o'lantern to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added mummy to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added Santa to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added shamrock to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added skull to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added snowman to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added spider to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added turkey to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added vampire to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added spider web to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added witch to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added zombie to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -1 +1 @@
# Nature emoji subcategory
# Nature emoji subcategory

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added butterfly to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added cat to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added cherry blossom to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added dog to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added moon to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added rainbow to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added rose to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added sun to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added sunflower to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added tree to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added the mighty wolf Fenrir to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -1 +1 @@
# People emoji subcategory
# People emoji subcategory

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added grinning face to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added angry face to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added beaming face to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added face blowing kiss to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added cool face to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added crying face to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added devil face to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added dizzy face to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added exploding head to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added face with symbols to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added grinning face with sweat to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added heart-eyes face to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added smiling face with hearts to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added angry face with horns to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added laughing face to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added nauseated face to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added pleading face to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added poop to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added rolling on floor laughing to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added sad face to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added face savoring food to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added screaming face to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added shocked face to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added smiling face to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added smirking face to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added thumbs up to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added winking face to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -1 +1 @@
# Symbols emoji subcategory
# Symbols emoji subcategory

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added chains to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added checkmark to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added bone to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added dagger to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added fire to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added folded hands to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added heart to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added high voltage lightning bolt to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added hundred points to clipboard",
interrupt=False, flush=False
)
)

View File

@@ -19,4 +19,4 @@ class command():
self.env["runtime"]["OutputManager"].present_text(
"Added lightning to clipboard",
interrupt=False, flush=False
)
)

Some files were not shown because too many files have changed in this diff Show More