1
0
Fork 0
mirror of https://github.com/LnL7/nix-darwin.git synced 2025-03-31 04:04:45 +00:00
This commit is contained in:
Ryan Orendorff 2025-03-25 04:04:43 +05:00 committed by GitHub
commit 26aa4a3206
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 240 additions and 0 deletions

View file

@ -0,0 +1,29 @@
{ stdenv, callPackage, python3Packages, writers }:
commands:
let
custom-commmands-file = callPackage ./custom-commands.nix { };
generate-commands-plist =
python3Packages.callPackage ./generate-commands-plist {
inherit (writers) writePython3Bin;
};
math-symbols-input = callPackage ./package { };
in stdenv.mkDerivation {
name = "commands-plist";
phases = [ "installPhase" ];
installPhase = ''
mkdir -p $out
# Call the generate_commands_plist python cli to convert the default
# list of replacements and a custom list of replacements to a plist file.
${generate-commands-plist}/bin/generate_commands_plist \
${math-symbols-input}/Math\ Symbols\ Input.app/Contents/Resources/commands.txt \
${custom-commmands-file commands} \
$out/com.mathsymbolsinput.inputmethod.MathSymbolsInput.plist
'';
}

View file

@ -0,0 +1,14 @@
# Converts an attr list to the text file format used by Math Symbols Input.
# for example, the following command attribute set
#
# {"alpha" = "α"; "beta" = "β";}
#
# would be converted to
#
# \alpha α
# \beta β
#
{ writeText, lib }:
commands:
writeText "custom-commands.txt" (builtins.concatStringsSep "\n"
(lib.attrsets.mapAttrsToList (name: value: "\\${name} ${value}") commands))

View file

@ -0,0 +1,59 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.math-symbols-input;
package = pkgs.callPackage ./package { };
plist-base-path = "com.mathsymbolsinput.inputmethod.MathSymbolsInput.plist ";
plist-full-path = "~/Library/Preferences/${plist-base-path}";
commands-to-plist = pkgs.callPackage ./commands-to-plist.nix { };
custom-commands-plist = "${commands-to-plist cfg.symbols}/${plist-base-path}";
command-to-run = pkgs.writeScriptBin "write_defaults" ''
defaults write ${plist-full-path} "$(defaults read ${custom-commands-plist} | sed 's|\\\\|\\|g')"
'';
in {
options.services.math-symbols-input = {
enable = mkEnableOption ''
LaTeX-style mathematical symbols input method for macOS
'';
symbols = mkOption {
type = types.attrs;
default = { };
example = literalExample ''
{
"xd" = "😆";
}
'';
description = "Custom symbols to add to Math Symbols Input";
};
};
# Note that this only makes sense for homebrew
config = mkIf cfg.enable {
system.activationScripts.preActivation.text = ''
echo "Setting up Math Symbols Input"
if [ -d /Library/Input\ Methods/Math\ Symbols\ Input.app ]; then
rm /Library/Input\ Methods/Math\ Symbols\ Input.app
fi
ln -s ${package}/Math\ Symbols\ Input.app /Library/Input\ Methods/
if [ ! -f ${plist-full-path} ]; then
defaults write ${plist-full-path} CustomCommands ""
chmod 600 ${plist-full-path}
chown $SUDO_USER:staff ${plist-full-path}
fi
# Force a cache reload by writing
su - $SUDO_USER -c "${command-to-run}/bin/write_defaults"
'';
};
}

View file

@ -0,0 +1,6 @@
{ lib, writePython3Bin, cytoolz }:
writePython3Bin "generate_commands_plist" {
libraries = [ cytoolz ];
flakeIgnore = [ "E501" ];
} (builtins.readFile ./generate_commands_plist.py)

View file

@ -0,0 +1,106 @@
from functools import reduce
from pathlib import Path
from collections.abc import Iterable
from typing import TypedDict
from operator import ior
from cytoolz import compose_left
from cytoolz.curried import filter, map
###############################################################################
# Types #
###############################################################################
Commands = dict[str, str]
# This is the structure in the Math Symbols Input plist file
class MathSymbolsPlist(TypedDict):
CustomCommands: Commands
DefaultCommands: Commands
PreferencesTab: str
###############################################################################
# Pure Commands #
###############################################################################
def valid_line(line: str) -> bool:
"""Is this line a command line (true) or a comment (false)"""
return not line.startswith("#") and not line.isspace()
def clean_line(line: str) -> str:
"""Remove whitespace so commands don't have random whitespace in them"""
return line.strip()
def command_line_to_commands(line: str) -> Commands:
"""Convert a single command string line to a Commands"""
command, symbol = line.split(" ")
return {command: symbol}
def combine_commands(commands: Iterable[Commands]) -> Commands:
"""Combine a bunch of Commands dicts into one
Equivalent to combining a bunch of [d1, d2, ..., dn] as
d = {}
d |= d1
d |= d2
...
d |= dn
"""
return reduce(ior, commands, dict())
# Operates on a generator, so only reads one line at a time
def lines_to_commands(lines: Iterable[str]) -> Commands:
"""Convert an iterable of command strings onto one Commands dict"""
return compose_left(
filter(valid_line),
map(compose_left(clean_line, command_line_to_commands)),
combine_commands,
)(lines)
def commands_to_plist(custom: Commands, default: Commands) -> MathSymbolsPlist:
return MathSymbolsPlist(
CustomCommands=custom, DefaultCommands=default, PreferencesTab="custom-commands"
)
###############################################################################
# Stateful/Impure functions #
###############################################################################
def path_to_commands(p: Path) -> Commands:
with open(p, "r") as f:
return lines_to_commands(f)
def command_paths_to_plist(custom_path: Path, default_path: Path) -> MathSymbolsPlist:
custom = path_to_commands(custom_path)
default = path_to_commands(default_path)
return commands_to_plist(custom, default)
###############################################################################
# Main #
###############################################################################
if __name__ == "__main__":
import sys
import plistlib
locations = sys.argv[1:4]
default_path, custom_path, output_path = map(Path, locations)
commands = command_paths_to_plist(custom_path, default_path)
with open(output_path, "wb") as f:
plistlib.dump(commands, f, fmt=plistlib.FMT_BINARY)

View file

@ -0,0 +1,26 @@
{ stdenv, fetchurl, xar, zip, cpio }:
stdenv.mkDerivation rec {
pname = "MathSymbolsInput";
version = "v1.3";
src = fetchurl {
url =
"https://github.com/knrafto/${pname}/releases/download/${version}/${pname}.pkg";
sha256 = "sha256-+s+TFoAv2rWl3gOHp8LLUZm+OTMDxgZtK0vmHQDJzFU=";
};
phases = [ "unpackPhase" "buildPhase" "installPhase" ];
unpackPhase = "xar -xf $src";
buildInputs = [ xar zip cpio ];
buildPhase = ''
cat MathSymbolsInput.pkg/Payload | gunzip -dc | cpio -i
'';
installPhase = ''
mkdir -p $out
cp -r "Math Symbols Input.app" $out
'';
}