Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ Windows_and_Linux/config.json
**/__pycache__
**/*.mo
**/pot_files
Windows_and_Linux/dist/
Windows_and_Linux/packaging/stage/
Windows_and_Linux/packaging/dist/
Windows_and_Linux/*.deb
Windows_and_Linux/*.venv
Windows_and_Linux/packaging/nfpm.yaml

# Xcode user-specific data
**/xcuserdata/
**/project.xcworkspace/xcuserdata/
**/project.xcworkspace/xcuserdata/
30 changes: 24 additions & 6 deletions README's Linked Content/To Compile the Application Yourself.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,48 @@ Here's how to compile it with PyInstaller and a virtual environment:

1. First, create and activate a virtual environment:
```bash
# Install virtualenv if you haven't already
pip install virtualenv
# Debian/Ubuntu only (one-time): install venv support
sudo apt install -y python3-venv

# Create a new virtual environment
virtualenv myvenv
python3 -m venv .venv

# Activate it
# On Windows:
myvenv\Scripts\activate
.venv\Scripts\activate
# On Linux:
source myvenv/bin/activate
source .venv/bin/activate
```

2. Once activated, install the required packages:

```bash
pip install -r requirements.txt
python -m pip install -r requirements.txt
```

3. Build Writing Tools:
```bash
python pyinstaller-build-script.py
```

4. (Linux optional) Build a Debian package:

Install nFPM first (one-time) using the official installation instructions:
https://nfpm.goreleaser.com/docs/install/

```bash
# Build .deb (outputs to packaging/dist/)
./build-deb.sh

# Install it
sudo apt install ./packaging/dist/*.deb
```

5. (Linux optional) Manual source install without `.deb`:
```bash
./install-local-linux.sh
```

### macOS Version (by [Aryamirsepasi](https://github.com/Aryamirsepasi)) build instructions:

1. **Install Xcode**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,19 @@ After extracting the folder, open your **Terminal** (or **Command Prompt**) in t
- Windows:
```bash
cd path\to\Windows_and_Linux
pip install -r requirements.txt
py -m venv .venv
.venv\Scripts\activate
python -m pip install -r requirements.txt
```

- Linux:
```bash
cd /path/to/Windows_and_Linux
pip3 install -r requirements.txt
# Debian/Ubuntu only (one-time): install venv support
sudo apt install -y python3-venv
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
```
Of course, you'll need to have [Python installed](https://www.python.org/downloads/)!

Expand All @@ -34,5 +40,11 @@ Of course, you'll need to have [Python installed](https://www.python.org/downloa
python3 main.py
```

**Optional Linux desktop integration (manual/source install):**
```bash
cd /path/to/Windows_and_Linux
./install-local-linux.sh
```


### [**◀️ Back to main page**](https://github.com/theJayTea/WritingTools)
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,18 @@ Aside from being the only Windows/Linux program like Apple's Writing Tools, and
### **🐧 Linux (work-in-progress)**:
[Run it from the source code](https://github.com/theJayTea/WritingTools/blob/main/README's%20Linked%20Content/To%20Run%20Writing%20Tools%20Directly%20from%20the%20Source%20Code.md)

You can also build an installable `.deb` package yourself:
1. `cd Windows_and_Linux`
2. On Debian/Ubuntu, install venv support (one-time): `sudo apt install -y python3-venv`
3. Create and activate a virtual environment: `python3 -m venv .venv && source .venv/bin/activate`
4. Install requirements: `python -m pip install -r requirements.txt`
5. Install nFPM (packager): https://nfpm.goreleaser.com/docs/install/
6. Build package: `./build-deb.sh`
7. Install package: `sudo apt install ./packaging/dist/*.deb`

Note: on first launch, `writing-tools` auto-initializes your user profile under `~/.local/share/writingtools`.
`install-local-linux.sh` remains available for manual/source installs.

Writing Tools works well on x11. On Wayland, there are a few caveats:
- [it works on XWayland apps](https://github.com/theJayTea/WritingTools/issues/34#issuecomment-2461633556)
- [and it works if you disable Wayland for individual Flatpaks with Flatseal.](https://github.com/theJayTea/WritingTools/issues/93#issuecomment-2576511041)
Expand Down
39 changes: 39 additions & 0 deletions Windows_and_Linux/Writing Tools.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# -*- mode: python ; coding: utf-8 -*-


a = Analysis(
['main.py'],
pathex=[],
binaries=[],
datas=[('locales', 'locales')],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=['tkinter', 'unittest', 'IPython', 'jedi', 'email_validator', 'psutil', 'pyzmq', 'tornado', 'PySide6.QtNetwork', 'PySide6.QtXml', 'PySide6.QtQml', 'PySide6.QtQuick', 'PySide6.QtQuickWidgets', 'PySide6.QtPrintSupport', 'PySide6.QtSql', 'PySide6.QtTest', 'PySide6.QtSvg', 'PySide6.QtSvgWidgets', 'PySide6.QtHelp', 'PySide6.QtMultimedia', 'PySide6.QtMultimediaWidgets', 'PySide6.QtOpenGL', 'PySide6.QtOpenGLWidgets', 'PySide6.QtPositioning', 'PySide6.QtLocation', 'PySide6.QtSerialPort', 'PySide6.QtWebChannel', 'PySide6.QtWebSockets', 'PySide6.QtWinExtras', 'PySide6.QtNetworkAuth', 'PySide6.QtRemoteObjects', 'PySide6.QtTextToSpeech', 'PySide6.QtWebEngineCore', 'PySide6.QtWebEngineWidgets', 'PySide6.QtWebEngine', 'PySide6.QtBluetooth', 'PySide6.QtNfc', 'PySide6.QtWebView', 'PySide6.QtCharts', 'PySide6.QtDataVisualization', 'PySide6.QtPdf', 'PySide6.QtPdfWidgets', 'PySide6.QtQuick3D', 'PySide6.QtQuickControls2', 'PySide6.QtQuickParticles', 'PySide6.QtQuickTest', 'PySide6.QtQuickWidgets', 'PySide6.QtSensors', 'PySide6.QtStateMachine', 'PySide6.Qt3DCore', 'PySide6.Qt3DRender', 'PySide6.Qt3DInput', 'PySide6.Qt3DLogic', 'PySide6.Qt3DAnimation', 'PySide6.Qt3DExtras'],
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure)

exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='Writing Tools',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon=['icons/app_icon.png'],
)
159 changes: 159 additions & 0 deletions Windows_and_Linux/build-deb.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PKG_DIR="${SCRIPT_DIR}/packaging"
STAGE_DIR="${PKG_DIR}/stage"
OUTPUT_DIR="${PKG_DIR}/dist"

DEFAULT_VERSION="$(tr -d '[:space:]' < "${SCRIPT_DIR}/Latest_Version_for_Update_Check.txt")"
VERSION="${1:-${DEFAULT_VERSION}}"
ARCH_OVERRIDE="${2:-}"

if [[ -z "${VERSION}" ]]; then
echo "ERROR: Package version is empty."
echo "Provide a version as the first argument, e.g. ./build-deb.sh 8"
exit 1
fi

if ! command -v nfpm >/dev/null 2>&1; then
echo "ERROR: nfpm is required but was not found in PATH."
echo "Install: https://nfpm.goreleaser.com/docs/install/"
exit 1
fi

if ! command -v python3 >/dev/null 2>&1; then
echo "ERROR: python3 is required to build the app binary."
exit 1
fi

map_arch() {
local machine
machine="${1}"

case "${machine}" in
x86_64)
echo "amd64"
;;
aarch64|arm64)
echo "arm64"
;;
armv7l)
echo "arm7"
;;
i686|i386)
echo "386"
;;
*)
return 1
;;
esac
}

if [[ -n "${ARCH_OVERRIDE}" ]]; then
NFPM_ARCH="${ARCH_OVERRIDE}"
else
if ! NFPM_ARCH="$(map_arch "$(uname -m)")"; then
echo "ERROR: Unsupported architecture: $(uname -m)"
echo "Pass nfpm arch manually as second argument (e.g. amd64, arm64)."
exit 1
fi
fi

export NFPM_VERSION="${VERSION}"
export NFPM_RELEASE="${NFPM_RELEASE:-1}"
export NFPM_ARCH

echo "[1/4] Building PyInstaller binary"
(
cd "${SCRIPT_DIR}"
python3 pyinstaller-build-script.py
)

DIST_EXE="${SCRIPT_DIR}/dist/Writing Tools"
if [[ ! -x "${DIST_EXE}" ]]; then
echo "ERROR: Expected binary not found: ${DIST_EXE}"
exit 1
fi

echo "[2/4] Staging package files"
rm -rf "${STAGE_DIR}" "${OUTPUT_DIR}"
mkdir -p \
"${STAGE_DIR}/usr/bin" \
"${STAGE_DIR}/usr/lib/writing-tools/payload" \
"${STAGE_DIR}/usr/share/applications" \
"${STAGE_DIR}/usr/share/icons/hicolor/256x256/apps" \
"${OUTPUT_DIR}"

install -m 0755 "${DIST_EXE}" "${STAGE_DIR}/usr/lib/writing-tools/payload/Writing Tools"
install -m 0755 "${SCRIPT_DIR}/install-local-linux.sh" "${STAGE_DIR}/usr/lib/writing-tools/install-local-linux.sh"

cp -a "${SCRIPT_DIR}/icons" "${STAGE_DIR}/usr/lib/writing-tools/payload/icons"
cp -a "${SCRIPT_DIR}/locales" "${STAGE_DIR}/usr/lib/writing-tools/payload/locales"

for file_name in background.png background_dark.png background_popup.png background_popup_dark.png options.json Latest_Version_for_Update_Check.txt; do
install -m 0644 "${SCRIPT_DIR}/${file_name}" "${STAGE_DIR}/usr/lib/writing-tools/payload/${file_name}"
done

install -m 0644 "${SCRIPT_DIR}/icons/app_icon.png" "${STAGE_DIR}/usr/share/icons/hicolor/256x256/apps/writing-tools.png"

cat > "${STAGE_DIR}/usr/share/applications/writing-tools.desktop" <<'EOF'
[Desktop Entry]
Type=Application
Name=Writing Tools
Comment=AI-powered writing helper with global hotkey popup
Exec=/usr/bin/writing-tools
Icon=writing-tools
Terminal=false
Categories=Office;Utility;
StartupNotify=false
EOF
chmod 0644 "${STAGE_DIR}/usr/share/applications/writing-tools.desktop"

cat > "${STAGE_DIR}/usr/bin/writing-tools" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

INSTALLER="/usr/lib/writing-tools/install-local-linux.sh"
PAYLOAD="/usr/lib/writing-tools/payload"
USER_LAUNCHER="${HOME}/.local/bin/writing-tools"

if [[ "${EUID}" -eq 0 ]]; then
echo "Please run writing-tools as a regular desktop user, not as root."
echo "Example: sudo -u <username> writing-tools"
exit 1
fi

if [[ ! -x "${USER_LAUNCHER}" ]]; then
if [[ ! -x "${INSTALLER}" ]]; then
echo "ERROR: Missing installer helper at ${INSTALLER}"
exit 1
fi

if [[ ! -d "${PAYLOAD}" ]]; then
echo "ERROR: Missing payload directory at ${PAYLOAD}"
exit 1
fi

"${INSTALLER}" --package-mode --app-source "${PAYLOAD}" || true
fi

if [[ -x "${USER_LAUNCHER}" ]]; then
exec "${USER_LAUNCHER}" "$@"
fi

echo "Writing Tools could not initialize your local profile automatically."
echo "Run this once as your user and try again:"
echo " /usr/lib/writing-tools/install-local-linux.sh --package-mode --app-source /usr/lib/writing-tools/payload"
exit 1
EOF
chmod 0755 "${STAGE_DIR}/usr/bin/writing-tools"

echo "[3/4] Building .deb package with nfpm"
(
cd "${SCRIPT_DIR}"
nfpm pkg --packager deb --config "${PKG_DIR}/nfpm.yaml" --target "${OUTPUT_DIR}/"
)

echo "[4/4] Build completed"
ls -1 "${OUTPUT_DIR}"/*.deb
Loading