Skip to content
sgk-devPublic

Latest commit

 

History

62 Commits

Folders and files

Repository files navigation

WordWrap logo

WordWrap

Fix text typed in the wrong keyboard layout - the Linux answer to Punto Switcher.

Select the mistyped text, press Ctrl+F1: ghbdtn becomes привет, руддщ becomes hello, and the system layout switches to match.

Python Platform PyPI License Tests


Why

You typed a whole sentence before noticing the layout was wrong. Instead of deleting and retyping, select it and hit one hotkey - WordWrap rewrites the characters through the correct layout, pastes the result back in place, and flips the system layout so your next keystroke is already right.

It is manual on purpose: it never watches what you type and never guesses. It acts only when you press the hotkey.

Features

  • Bidirectional - works whether EN or RU is currently active; direction is picked from the text itself, not from the active layout.
  • Works anywhere text is typed - editors, browsers, VS Code, Telegram; terminals get a dedicated hotkey that clears the input line and pastes with Ctrl+Shift+V.
  • Fix the last word with a single hotkey - no selection needed.
  • Tray app - enable / disable with a click, colour or monochrome icon.
  • Bilingual UI - English by default, Russian selectable in Settings.
  • Launch on login - one checkbox in Settings.
  • Privacy-first - text content is never logged, no network access of any kind.

How it works

  1. Global hotkey caught via evdev (needs the input group).
  2. Your clipboard is saved and a private marker is put in it; the selection is copied over the marker with Ctrl+Insert. Marker still there means nothing is selected, so the last word is selected automatically (optional).
  3. Text is converted character-by-character between layouts (en <-> ru and en <-> uk built in). The direction comes from the text itself, not from the active layout.
  4. The result is pasted back via clipboard + synthetic Ctrl+V - wtype is not supported by Mutter, so this is the reliable path.
  5. The system layout is switched by pressing the GNOME switch input source shortcut (Super+Space by default, read from your settings). GNOME ignores gsettings set ... current, so the shortcut is the only working path. With per-window input sources (Settings -> Keyboard -> Switch input sources individually for each window) the focused window's layout is read from ibus engine, because mru-sources only changes on interactive switches; without IBus the shortcut is pressed and the result is read back from mru-sources. With 3+ layouts the shortcut is held and tapped to reach the target in the switcher.
  6. Your clipboard is restored.

Pressing the convert hotkey again within a few seconds of a conversion, with nothing selected, does not convert the last word back - it only makes sure the layout is the one the conversion switched to. If the layout already is that one, the press works as usual and converts the last word.

Terminal mode (Ctrl+Shift+F1) is different: it takes the mouse selection, clears the whole readline input line (Ctrl+A, Ctrl+K - Ctrl+Y brings it back) and pastes the fixed text with Ctrl+Shift+V. It assumes the mistyped text is the current input line. For TUI prompts that do not understand Ctrl+A / Ctrl+K (Claude Code, some REPLs) switch Settings -> Behavior -> Terminal: how to erase the old text to Backspace per character and keep the cursor at the end of the mistyped text. Full-screen TUIs (vim, tmux, htop) are not supported.

Hotkeys

Action Hotkey
Convert selection Ctrl+F1
Convert in a terminal (clears the input line, pastes with Ctrl+Shift+V) Ctrl+Shift+F1
Convert the last word (no selection needed) Ctrl+F2
Enable / disable conversion Ctrl+Pause

All configurable in Settings or ~/.config/sgk-wordwrap/config.json. The listener only watches the keyboard and does not consume the event, so the hotkey also reaches the focused app - that is why the defaults are otherwise-unused keys.

Tray and settings

The tray icon (top panel) shows enabled / disabled state. Left-click toggles it; right-click opens the menu:

  • Enabled / Paused - toggle conversion
  • Settings... - language, launch-on-login, monochrome icon, hotkeys, excluded programs, behavior (word fallback, clipboard restore, terminal paste / erase mode)
  • About - version, author, link to star the project
  • Quit

Language and icon-style changes apply immediately; hotkey and behavior changes need a restart.

Install (GNOME Wayland / Ubuntu)

Requires wl-clipboard, python3-pyqt6, python3-evdev and membership in the input group (for the evdev listener and the uinput virtual keyboard).

With pipx (from PyPI):

sudo apt install wl-clipboard python3-pyqt6 python3-evdev pipx
sudo usermod -aG input "$USER"          # then log out and back in once
pipx install --system-site-packages sgk-wordwrap
sgk-wordwrap --install-desktop          # adds WordWrap to the applications menu

The latest development version comes straight from GitHub instead: pipx install --system-site-packages git+https://github.com/sgk-dev/wordwrap.

Then open the GNOME activities overview, search for WordWrap and launch it. Turn on Launch on login in Settings if you want it to start with your session.

From a clone, as a systemd user service:

bash packaging/install.sh
# log out and back in once (for the 'input' group), then:
systemctl --user start sgk-wordwrap

install.sh creates a venv, the menu entry and a sgk-wordwrap user service that starts with the graphical session. Use either the service or the Settings checkbox for autostart, not both - a second instance simply exits.

Run in the foreground

python3 -m sgk_wordwrap --log-level DEBUG      # with tray
python3 -m sgk_wordwrap --no-gui               # headless

Configuration

~/.config/sgk-wordwrap/config.json (created on first run):

{
  "ui": { "language": "en", "tray_icon_style": "color" },
  "hotkeys": {
    "convert": "ctrl+f1",
    "convert_terminal": "ctrl+shift+f1",
    "convert_last_word": "ctrl+f2",
    "toggle": "ctrl+pause"
  },
  "layouts": { "custom_maps_dir": null },
  "behavior": {
    "enabled_on_start": true,
    "fallback_to_word_on_no_selection": true,
    "restore_clipboard": true,
    "terminal_paste_combo": "ctrl+shift+v",
    "terminal_erase": "line",
    "copy_settle_ms": 400,
    "clipboard_settle_ms": 0,
    "paste_settle_ms": 100
  }
}

Custom layouts

Point layouts.custom_maps_dir at a folder and drop JSON files into it:

{
  "name": "en-de", "from_layout": "en", "to_layout": "de",
  "map": { "y": "z", "z": "y", "Y": "Z", "Z": "Y" }
}

Notes and limitations

  • Direction is detected from the text. Pressed on correct text by mistake? Undo with Ctrl+Z in the app - the paste is a single edit.
  • Clipboard restore: text is restored as it was. A non-text clipboard (an image, for example) is restored as its first non-text type only; other types and hints such as the password-manager "secret" flag are lost. Content above 20 MB is not restored.
  • Clipboard history managers (Clipboard Indicator, GPaste, CopyQ) record the intermediate values WordWrap puts on the clipboard: a private marker, the selected text and the converted text. Exclude WordWrap there or use their private mode if the selected text can be sensitive.
  • Password fields: window / process detection is not available on GNOME Wayland, so the excluded-programs list works only on X11. Do not press the hotkey in a password field.
  • Layout switching relies on the GNOME switch input source shortcut. If the layout does not follow, the log has a sgk_layout_switch_failed warning with what was read back.
  • Active layouts come from the system (gsettings), not from the config.
  • Supported environment: GNOME on Wayland (Ubuntu, Mutter). X11 / KDE / wlroots code exists in the tree but is out of scope for this release.

Support the project

If WordWrap saves you time, a star on GitHub helps a lot.

License

WordWrap is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License v3.0 or later (see LICENSE). It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.

Copyright (c) 2026 SGK (sidash.seo@gmail.com)

The WordWrap name and logo are not covered by the GPL and remain the property of SGK; forks must use a different name and their own artwork.


Developed by SGK with ❤️

Releases

Packages

Contributors

Languages