mirror of
https://github.com/felixfoertsch/EurKEY-macOS.git
synced 2026-04-16 06:28:28 +02:00
rename v2.0 to EurKEY Next, add ANSI support, normalize Caps Lock, fix v1.4
- rename v2.0 → EurKEY Next across all files, scripts, workflows, website - rename bundle EurKey-macOS → EurKEY-macOS - add §/± to ¬ dead key (¬+s → §, ¬+S → ±) for ANSI keyboard compatibility - normalize Caps Lock = Shift across all four layouts, remove custom Caps bindings - fix v1.4: revert accidental Caps/ẞ changes, correct changelog to super/subscript swap - update README: remove duplicate v1.2–v1.4 changelog, reorder versions (Next first) - update website: ISO+ANSI feature card, EurKEY Next branding, consistent version order Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,7 @@ set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
BUILD_DIR="${PROJECT_DIR}/build"
|
||||
BUNDLE_DIR="${BUILD_DIR}/EurKey-macOS.bundle"
|
||||
BUNDLE_DIR="${BUILD_DIR}/EurKEY-Next.bundle"
|
||||
CONTENTS_DIR="${BUNDLE_DIR}/Contents"
|
||||
RESOURCES_DIR="${CONTENTS_DIR}/Resources"
|
||||
|
||||
@@ -20,11 +20,11 @@ if [[ "${1:-}" == "--version" ]]; then
|
||||
VERSION="${2:?missing version argument}"
|
||||
fi
|
||||
|
||||
BUNDLE_ID="de.felixfoertsch.keyboardlayout.EurKEY-macOS"
|
||||
BUNDLE_NAME="EurKEY-macOS"
|
||||
BUNDLE_ID="de.felixfoertsch.keyboardlayout.EurKEY-Next"
|
||||
BUNDLE_NAME="EurKEY-Next"
|
||||
|
||||
# layout versions to include
|
||||
VERSIONS=("v1.2" "v1.3" "v1.4" "v2.0")
|
||||
# layout names to include (EurKEY Next is the main layout, others are legacy versions)
|
||||
LAYOUTS=("EurKEY Next" "EurKEY v1.4" "EurKEY v1.3" "EurKEY v1.2")
|
||||
|
||||
SRC_DIR="${PROJECT_DIR}/src"
|
||||
|
||||
@@ -39,9 +39,9 @@ bash "${SCRIPT_DIR}/build-icons.sh"
|
||||
rm -rf "${BUNDLE_DIR}"
|
||||
mkdir -p "${RESOURCES_DIR}"
|
||||
|
||||
for ver in "${VERSIONS[@]}"; do
|
||||
cp "${SRC_DIR}/keylayouts/EurKEY ${ver}.keylayout" "${RESOURCES_DIR}/"
|
||||
cp "${SRC_DIR}/icons/EurKEY ${ver}.icns" "${RESOURCES_DIR}/"
|
||||
for layout in "${LAYOUTS[@]}"; do
|
||||
cp "${SRC_DIR}/keylayouts/${layout}.keylayout" "${RESOURCES_DIR}/"
|
||||
cp "${SRC_DIR}/icons/${layout}.icns" "${RESOURCES_DIR}/"
|
||||
done
|
||||
|
||||
for lang in en de es; do
|
||||
@@ -74,15 +74,14 @@ PLIST_VERSION
|
||||
|
||||
echo " <string>${VERSION}</string>" >> "${CONTENTS_DIR}/Info.plist"
|
||||
|
||||
# add KLInfo for each version
|
||||
for ver in "${VERSIONS[@]}"; do
|
||||
layout_name="EurKEY ${ver}"
|
||||
# generate input source ID: bundle id + layout name with spaces removed, lowercased
|
||||
source_id_suffix=$(echo "eurkey${ver}" | tr '[:upper:]' '[:lower:]' | tr -d ' ')
|
||||
# add KLInfo for each layout
|
||||
for layout in "${LAYOUTS[@]}"; do
|
||||
# generate input source ID: bundle id + layout name lowercased, spaces removed
|
||||
source_id_suffix=$(echo "${layout}" | tr '[:upper:]' '[:lower:]' | tr -d ' ')
|
||||
source_id="${BUNDLE_ID}.${source_id_suffix}"
|
||||
|
||||
cat >> "${CONTENTS_DIR}/Info.plist" << KLINFO_ENTRY
|
||||
<key>KLInfo_${layout_name}</key>
|
||||
<key>KLInfo_${layout}</key>
|
||||
<dict>
|
||||
<key>TICapsLockLanguageSwitchCapable</key>
|
||||
<true/>
|
||||
@@ -101,7 +100,7 @@ cat >> "${CONTENTS_DIR}/Info.plist" << 'PLIST_FOOTER'
|
||||
</plist>
|
||||
PLIST_FOOTER
|
||||
|
||||
echo "Generated Info.plist with ${#VERSIONS[@]} layout entries"
|
||||
echo "Generated Info.plist with ${#LAYOUTS[@]} layout entries"
|
||||
|
||||
# --- generate version.plist ---
|
||||
cat > "${CONTENTS_DIR}/version.plist" << VPLIST
|
||||
|
||||
@@ -12,7 +12,7 @@ set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
BUILD_DIR="${PROJECT_DIR}/build"
|
||||
BUNDLE_DIR="${BUILD_DIR}/EurKey-macOS.bundle"
|
||||
BUNDLE_DIR="${BUILD_DIR}/EurKEY-Next.bundle"
|
||||
|
||||
# parse arguments
|
||||
VERSION="${1:-$(date +%Y.%m.%d)}"
|
||||
@@ -20,7 +20,7 @@ if [[ "${1:-}" == "--version" ]]; then
|
||||
VERSION="${2:?missing version argument}"
|
||||
fi
|
||||
|
||||
DMG_NAME="EurKEY-macOS-${VERSION}"
|
||||
DMG_NAME="EurKEY-Next-${VERSION}"
|
||||
DMG_PATH="${BUILD_DIR}/${DMG_NAME}.dmg"
|
||||
STAGING_DIR="${BUILD_DIR}/dmg-staging"
|
||||
|
||||
@@ -41,7 +41,7 @@ mkdir -p "${STAGING_DIR}"
|
||||
cp -R "${BUNDLE_DIR}" "${STAGING_DIR}/"
|
||||
|
||||
# copy layout PDFs
|
||||
cp "${BUILD_DIR}"/eurkey-*-layout.pdf "${STAGING_DIR}/"
|
||||
cp "${BUILD_DIR}"/eurkey-*layout.pdf "${STAGING_DIR}/"
|
||||
|
||||
# create symlink to installation target
|
||||
ln -s "/Library/Keyboard Layouts" "${STAGING_DIR}/Install Here (Keyboard Layouts)"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# Requires: rsvg-convert (librsvg), iconutil (macOS built-in)
|
||||
#
|
||||
# The v1.2/v1.3/v1.4 icon is a template badge with "EU" text.
|
||||
# The v2.0 icon is a monochrome star ring (managed separately).
|
||||
# The EurKEY Next icon is a monochrome star ring (managed separately).
|
||||
#
|
||||
# Usage: bash scripts/build-icons.sh
|
||||
set -euo pipefail
|
||||
@@ -54,7 +54,7 @@ rm "${ICONSET}"/tmp_*.png
|
||||
ICNS_PATH="${ICON_DIR}/badge-eu.icns"
|
||||
iconutil --convert icns --output "${ICNS_PATH}" "${ICONSET}"
|
||||
|
||||
# install for v1.2, v1.3, v1.4 (v2.0 keeps its own icon)
|
||||
# install for v1.2, v1.3, v1.4 (EurKEY Next keeps its own icon)
|
||||
cp "${ICNS_PATH}" "${ICON_DIR}/EurKEY v1.2.icns"
|
||||
cp "${ICNS_PATH}" "${ICON_DIR}/EurKEY v1.3.icns"
|
||||
cp "${ICNS_PATH}" "${ICON_DIR}/EurKEY v1.4.icns"
|
||||
|
||||
@@ -443,20 +443,22 @@ def generate_pdf(version, output_dir):
|
||||
"""Generate a PDF for the given layout version."""
|
||||
src_dir = Path(__file__).parent.parent / "src" / "keylayouts"
|
||||
keylayout = src_dir / f"EurKEY {version}.keylayout"
|
||||
display_name = f"EurKEY {version}"
|
||||
pdf_name = f"eurkey-{version.lower()}-layout.pdf"
|
||||
|
||||
if not keylayout.exists():
|
||||
print(f"ERROR: {keylayout} not found")
|
||||
return False
|
||||
|
||||
print(f"Generating PDF for EurKEY {version}...")
|
||||
print(f"Generating PDF for {display_name}...")
|
||||
data = parse_keylayout(str(keylayout), keyboard_type=0)
|
||||
|
||||
pdf = LayoutPDF(f"EurKEY {version}")
|
||||
pdf = LayoutPDF(display_name)
|
||||
pdf.generate(data)
|
||||
|
||||
out = Path(output_dir)
|
||||
out.mkdir(parents=True, exist_ok=True)
|
||||
output_path = out / f"eurkey-{version}-layout.pdf"
|
||||
output_path = out / pdf_name
|
||||
pdf.output(str(output_path))
|
||||
print(f" Written: {output_path}")
|
||||
return True
|
||||
@@ -466,7 +468,7 @@ def main():
|
||||
parser = argparse.ArgumentParser(description="Generate keyboard layout PDFs")
|
||||
parser.add_argument(
|
||||
"--version", "-v", nargs="*",
|
||||
default=["v1.2", "v1.3", "v1.4", "v2.0"],
|
||||
default=["Next", "v1.4", "v1.3", "v1.2"],
|
||||
help="Layout versions to generate (default: all)",
|
||||
)
|
||||
default_output = str(Path(__file__).parent.parent / "build")
|
||||
|
||||
@@ -18,7 +18,7 @@ from pathlib import Path
|
||||
sys.path.insert(0, str(Path(__file__).parent))
|
||||
from parse_keylayout import parse_keylayout, TYPING_KEY_CODES, MODIFIER_LABELS, KEY_CODE_NAMES
|
||||
|
||||
BUNDLE_DIR = Path(__file__).parent.parent / "build" / "EurKey-macOS.bundle" / "Contents" / "Resources"
|
||||
BUNDLE_DIR = Path(__file__).parent.parent / "build" / "EurKEY-Next.bundle" / "Contents" / "Resources"
|
||||
|
||||
# modifier indices that contain meaningful typing output
|
||||
# (exclude index 6 = Option+Command and 7 = Control — these are system shortcuts)
|
||||
@@ -184,27 +184,25 @@ def format_char_display(c):
|
||||
V1_2_EXCEPTIONS = {
|
||||
# Option+Shift S: v1.2 has § where v1.3 has ẞ (capital sharp s)
|
||||
"4:1": {"output": "§"},
|
||||
"5:1": {"output": "§"}, # Caps+Option S: mirrors Option+Shift (§)
|
||||
# v1.2 does not have the ¬ (negation) dead key — added in v1.3
|
||||
# instead, Option+- has the © dead key, and Option+\ outputs plain ¬
|
||||
"_dead_key_skip": ["dead: ¬"],
|
||||
"3:27": {"deadKey": "dead: ©"}, # Option+-: © dead key instead of ¬ dead key
|
||||
"3:42": {"output": "¬"}, # Option+\: plain ¬ instead of ¬ dead key
|
||||
"4:27": {"output": "№"}, # Option+Shift+-: № instead of ✗
|
||||
"5:27": {"deadKey": "dead: ©"}, # Caps+Option+-: © dead key instead of ¬ dead key
|
||||
"5:27": {"output": "№"}, # Caps+Option+-: mirrors Option+Shift (№)
|
||||
}
|
||||
|
||||
# v1.4 differences from v1.3:
|
||||
# - §/` key (code 10) in Caps/Caps+Option outputs ẞ instead of §
|
||||
# - ¬ dead key has an extra ¬ composition (self-referencing)
|
||||
# - swaps super/subscript numbers in α dead key
|
||||
# - ¬ dead key has an extra ¬ composition (self-referencing, harmless Ukelele artifact)
|
||||
V1_4_EXCEPTIONS = {
|
||||
"2:10": {"output": "ẞ"}, # Caps: §/` → ẞ (capital sharp s)
|
||||
"5:10": {"output": "ẞ"}, # Caps+Option: §/` → ẞ
|
||||
"5:27": {"output": ""}, # Caps+Option+-: no output (missing ¬ dead key in this layer)
|
||||
"dead:dead: ¬:extra:¬": True, # extra ¬ composition in negation dead key
|
||||
}
|
||||
|
||||
# v2.0 is a custom edition — skip validation for now, just document diffs
|
||||
V2_0_EXCEPTIONS = {
|
||||
# EurKEY Next (main edition) — skip validation, custom layout
|
||||
EURKEY_NEXT_EXCEPTIONS = {
|
||||
"_skip_validation": True,
|
||||
}
|
||||
|
||||
@@ -212,7 +210,7 @@ VERSIONS = {
|
||||
"v1.2": {"file": "v1.2", "exceptions": V1_2_EXCEPTIONS, "label": "EurKEY v1.2"},
|
||||
"v1.3": {"file": "v1.3", "exceptions": {}, "label": "EurKEY v1.3 (reference)"},
|
||||
"v1.4": {"file": "v1.4", "exceptions": V1_4_EXCEPTIONS, "label": "EurKEY v1.4"},
|
||||
"v2.0": {"file": "v2.0", "exceptions": V2_0_EXCEPTIONS, "label": "EurKEY v2.0 (custom)"},
|
||||
"next": {"file": "Next", "exceptions": EURKEY_NEXT_EXCEPTIONS, "label": "EurKEY Next"},
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user