split nixos from darwin

required because they don't share all attributes
This commit is contained in:
Noah Masur
2022-12-21 17:07:58 -07:00
parent 7063bd5f7a
commit d021baa1bb
78 changed files with 22 additions and 21 deletions

View File

@ -1,651 +0,0 @@
{ config, pkgs, lib, ... }: {
# MacOS-specific settings for Alacritty
home-manager.users.${config.user} = lib.mkIf pkgs.stdenv.isDarwin {
programs.alacritty.settings = {
font.size = lib.mkForce 20.0;
shell.program = "${pkgs.fish}/bin/fish";
window.startup_mode = "SimpleFullScreen";
key_bindings = [
{
key = "F";
mods = "Super";
action = "ToggleSimpleFullscreen";
}
{
key = "F";
mods = "Control|Shift";
action = "SearchForward";
}
{
key = "L";
mods = "Super";
chars = "\\x1F";
}
# Some Mac key combinations need to be manually added
{
key = "Return";
mods = "Shift";
chars = "\\x1b[13;2u";
}
{
key = "Return";
mods = "Control";
chars = "\\x1b[13;5u";
}
{
key = "Return";
mods = "Control|Shift";
chars = "\\x1b[13;6u";
}
{
key = "N";
mods = "Command";
action = "SpawnNewInstance";
}
{
key = "PageUp";
action = "ScrollPageUp";
}
{
key = "PageUp";
mods = "Alt";
chars = "\\x1B[5~";
}
{
key = "PageUp";
mods = "Shift";
chars = "\\x1B[5~";
}
{
key = "PageDown";
action = "ScrollPageDown";
}
{
key = "PageDown";
mods = "Alt";
chars = "\\x1B[6~";
}
{
key = "PageDown";
mods = "Shift";
chars = "\\x1B[6~";
}
{
key = "Home";
action = "ScrollToTop";
}
{
key = "Home";
mods = "Alt";
chars = "\\x1BOH";
}
{
key = "Home";
mods = "Shift";
chars = "\\x1B[H";
}
{
key = "End";
action = "ScrollToBottom";
}
{
key = "End";
mods = "Alt";
chars = "\\x1BOF";
}
{
key = "End";
mods = "Shift";
chars = "\\x1B[F";
}
{
key = "Tab";
mods = "Alt";
chars = "\\x1B ";
}
{
key = "Tab";
mods = "Alt|Shift";
chars = "\\x1Bx1B[Z";
}
# {
# key = "Back";
# chars = "\\x7F";
# }
{
key = "Back";
mods = "Alt";
chars = "\\x1Bx7F";
}
{
key = "Back";
mods = "Alt|Shift";
chars = "\\x1Bx08";
}
{
key = "Space";
mods = "Control";
chars = "\\x00";
}
{
key = "Space";
mods = "Alt";
chars = "\\x20";
}
{
key = "Left";
mods = "Alt";
chars = "\\x1Bb";
}
{
key = "Left";
mods = "Alt|Shift";
chars = "\\x1Bx1B[D";
}
{
key = "Right";
mods = "Alt";
chars = "\\x1Bf";
}
{
key = "Right";
mods = "Alt|Shift";
chars = "\\x1Bx1B[C";
}
{
key = "Down";
mods = "Alt";
chars = "\\x1Bx1B[B";
}
{
key = "Down";
mods = "Alt|Shift";
chars = "\\x1Bx1B[B";
}
{
key = "Up";
mods = "Alt";
chars = "\\x1Bx1B[A";
}
{
key = "Up";
mods = "Alt|Shift";
chars = "\\x1Bx1B[A";
}
{
key = "A";
mods = "Alt";
chars = "\\x1Ba";
}
{
key = "A";
mods = "Alt|Shift";
chars = "\\x1BA";
}
{
key = "B";
mods = "Alt";
chars = "\\x1Bb";
}
{
key = "B";
mods = "Alt|Shift";
chars = "\\x1BB";
}
{
key = "C";
mods = "Alt";
chars = "\\x1Bc";
}
{
key = "C";
mods = "Alt|Shift";
chars = "\\x1BC";
}
{
key = "D";
mods = "Alt";
chars = "\\x1Bd";
}
{
key = "D";
mods = "Alt|Shift";
chars = "\\x1BD";
}
{
key = "E";
mods = "Alt";
chars = "\\x1Be";
}
{
key = "E";
mods = "Alt|Shift";
chars = "\\x1BE";
}
{
key = "F";
mods = "Alt";
chars = "\\x1Bf";
}
{
key = "F";
mods = "Alt|Shift";
chars = "\\x1BF";
}
{
key = "G";
mods = "Alt";
chars = "\\x1Bg";
}
{
key = "G";
mods = "Alt|Shift";
chars = "\\x1BG";
}
{
key = "H";
mods = "Alt";
chars = "\\x1Bh";
}
{
key = "H";
mods = "Alt|Shift";
chars = "\\x1BH";
}
{
key = "I";
mods = "Alt";
chars = "\\x1Bi";
}
{
key = "I";
mods = "Alt|Shift";
chars = "\\x1BI";
}
{
key = "J";
mods = "Alt";
chars = "\\x1Bj";
}
{
key = "J";
mods = "Alt|Shift";
chars = "\\x1BJ";
}
{
key = "K";
mods = "Alt";
chars = "\\x1Bk";
}
{
key = "K";
mods = "Alt|Shift";
chars = "\\x1BK";
}
{
key = "L";
mods = "Alt";
chars = "\\x1Bl";
}
{
key = "L";
mods = "Alt|Shift";
chars = "\\x1BL";
}
{
key = "M";
mods = "Alt";
chars = "\\x1Bm";
}
{
key = "M";
mods = "Alt|Shift";
chars = "\\x1BM";
}
{
key = "N";
mods = "Alt";
chars = "\\x1Bn";
}
{
key = "N";
mods = "Alt|Shift";
chars = "\\x1BN";
}
{
key = "O";
mods = "Alt";
chars = "\\x1Bo";
}
{
key = "O";
mods = "Alt|Shift";
chars = "\\x1BO";
}
{
key = "P";
mods = "Alt";
chars = "\\x1Bp";
}
{
key = "P";
mods = "Alt|Shift";
chars = "\\x1BP";
}
{
key = "Q";
mods = "Alt";
chars = "\\x1Bq";
}
{
key = "Q";
mods = "Alt|Shift";
chars = "\\x1BQ";
}
{
key = "R";
mods = "Alt";
chars = "\\x1Br";
}
{
key = "R";
mods = "Alt|Shift";
chars = "\\x1BR";
}
{
key = "S";
mods = "Alt";
chars = "\\x1Bs";
}
{
key = "S";
mods = "Alt|Shift";
chars = "\\x1BS";
}
{
key = "T";
mods = "Alt";
chars = "\\x1Bt";
}
{
key = "T";
mods = "Alt|Shift";
chars = "\\x1BT";
}
{
key = "U";
mods = "Alt";
chars = "\\x1Bu";
}
{
key = "U";
mods = "Alt|Shift";
chars = "\\x1BU";
}
{
key = "V";
mods = "Alt";
chars = "\\x1Bv";
}
{
key = "V";
mods = "Alt|Shift";
chars = "\\x1BV";
}
{
key = "W";
mods = "Alt";
chars = "\\x1Bw";
}
{
key = "W";
mods = "Alt|Shift";
chars = "\\x1BW";
}
{
key = "X";
mods = "Alt";
chars = "\\x1Bx";
}
{
key = "X";
mods = "Alt|Shift";
chars = "\\x1BX";
}
{
key = "Y";
mods = "Alt";
chars = "\\x1By";
}
{
key = "Y";
mods = "Alt|Shift";
chars = "\\x1BY";
}
{
key = "Z";
mods = "Alt";
chars = "\\x1Bz";
}
{
key = "Z";
mods = "Alt|Shift";
chars = "\\x1BZ";
}
{
key = "Key1";
mods = "Alt";
chars = "\\x1B1";
}
{
key = "Key1";
mods = "Alt|Shift";
chars = "\\x1B!";
}
{
key = "Key2";
mods = "Alt";
chars = "\\x1B2";
}
{
key = "Key2";
mods = "Alt|Shift";
chars = "\\x1B#";
}
{
key = "Key3";
mods = "Alt";
chars = "\\x1B3";
}
{
key = "Key3";
mods = "Alt|Shift";
chars = "\\x1B#";
}
{
key = "Key4";
mods = "Alt";
chars = "\\x1B4";
}
{
key = "Key4";
mods = "Alt|Shift";
chars = "\\x1B$";
}
{
key = "Key5";
mods = "Alt";
chars = "\\x1B5";
}
{
key = "Key5";
mods = "Alt|Shift";
chars = "\\x1B%";
}
{
key = "Key6";
mods = "Alt";
chars = "\\x1B6";
}
{
key = "Key6";
mods = "Alt|Shift";
chars = "\\x1B^";
}
{
key = "Key7";
mods = "Alt";
chars = "\\x1B7";
}
{
key = "Key7";
mods = "Alt|Shift";
chars = "\\x1B&";
}
{
key = "Key8";
mods = "Alt";
chars = "\\x1B8";
}
{
key = "Key8";
mods = "Alt|Shift";
chars = "\\x1B*";
}
{
key = "Key9";
mods = "Alt";
chars = "\\x1B9";
}
{
key = "Key9";
mods = "Alt|Shift";
chars = "\\x1B(";
}
{
key = "Key0";
mods = "Alt";
chars = "\\x1B0";
}
{
key = "Key0";
mods = "Alt|Shift";
chars = "\\x1B)";
}
{
key = "Minus";
mods = "Alt";
chars = "\\x1B-";
}
{
key = "Minus";
mods = "Alt|Shift";
chars = "\\x1B_";
}
{
key = "Equals";
mods = "Alt";
chars = "\\x1B=";
}
{
key = "Equals";
mods = "Alt|Shift";
chars = "\\x1B+";
}
{
key = "LBracket";
mods = "Alt";
chars = "\\x1B[";
}
{
key = "LBracket";
mods = "Alt|Shift";
chars = "\\x1B{";
}
{
key = "RBracket";
mods = "Alt";
chars = "\\x1B]";
}
{
key = "RBracket";
mods = "Alt|Shift";
chars = "\\x1B}";
}
{
key = "Backslash";
mods = "Alt";
chars = "\\x1B\\\\";
}
{
key = "Backslash";
mods = "Alt|Shift";
chars = "\\x1B|";
}
{
key = "Semicolon";
mods = "Alt";
chars = "\\x1B;";
}
{
key = "Semicolon";
mods = "Alt|Shift";
chars = "\\x1B =";
}
{
key = "Apostrophe";
mods = "Alt";
chars = "\\x1B'";
}
{
key = "Apostrophe";
mods = "Alt|Shift";
chars = ''\x1B"'';
}
{
key = "Comma";
mods = "Alt";
chars = "\\x1B;";
}
{
key = "Comma";
mods = "Alt|Shift";
chars = "\\x1B<";
}
{
key = "Period";
mods = "Alt";
chars = "\\x1B.";
}
{
key = "Period";
mods = "Alt|Shift";
chars = "\\x1B>";
}
{
key = "Slash";
mods = "Alt";
chars = "\\x1B/";
}
{
key = "Slash";
mods = "Alt|Shift";
chars = "\\x1B?";
}
{
key = "Grave";
mods = "Alt";
chars = "\\x1B`";
}
{
key = "Grave";
mods = "Alt|Shift";
chars = "\\x1B~";
}
];
};
};
}

View File

@ -1,17 +0,0 @@
{ config, ... }: {
imports = [
./alacritty.nix
./fonts.nix
./hammerspoon.nix
./homebrew.nix
./kitty.nix
./networking.nix
./nixpkgs.nix
./system.nix
./tmux.nix
./user.nix
./utilities.nix
];
}

View File

@ -1,17 +0,0 @@
{ config, pkgs, lib, ... }: {
home-manager.users.${config.user} = lib.mkIf pkgs.stdenv.isDarwin {
home.packages = with pkgs;
[ (nerdfonts.override { fonts = [ "VictorMono" ]; }) ];
programs.alacritty.settings = { font.normal.family = "VictorMono"; };
programs.kitty.font = {
package = (pkgs.nerdfonts.override { fonts = [ "VictorMono" ]; });
name = "VictorMono Nerd Font Mono";
};
};
}

View File

@ -1,32 +0,0 @@
{ config, pkgs, lib, ... }: {
# Hammerspoon - MacOS custom automation scripting
config = lib.mkIf pkgs.stdenv.isDarwin {
home-manager.users.${config.user} = {
xdg.configFile."hammerspoon/init.lua".source = ./hammerspoon/init.lua;
xdg.configFile."hammerspoon/Spoons/ControlEscape.spoon".source =
./hammerspoon/Spoons/ControlEscape.spoon;
xdg.configFile."hammerspoon/Spoons/DismissAlerts.spoon".source =
./hammerspoon/Spoons/DismissAlerts.spoon;
xdg.configFile."hammerspoon/Spoons/Launcher.spoon/init.lua".source =
pkgs.substituteAll {
src = ./hammerspoon/Spoons/Launcher.spoon/init.lua;
firefox = "${pkgs.firefox-bin}/Applications/Firefox.app";
discord = "${pkgs.discord}/Applications/Discord.app";
kitty = "${pkgs.kitty}/Applications/kitty.app";
};
xdg.configFile."hammerspoon/Spoons/MoveWindow.spoon".source =
./hammerspoon/Spoons/MoveWindow.spoon;
};
homebrew.casks = [ "hammerspoon" ];
system.activationScripts.postUserActivation.text = ''
defaults write org.hammerspoon.Hammerspoon MJConfigFile "~/.config/hammerspoon/init.lua"
'';
};
}

View File

@ -1 +0,0 @@
indent_type = "Spaces"

View File

@ -1,112 +0,0 @@
--- === ControlEscape ===
---
--- Adapted very loosely from https://github.com/jasonrudolph/ControlEscape.spoon
--- Removed timing/delay; always send Escape as well as Control
---
--- Make the `control` key more useful: If the `control` key is tapped, treat it
--- as the `escape` key. If the `control` key is held down and used in
--- combination with another key, then provide the normal `control` key
--- behavior.
local obj = {}
obj.__index = obj
-- Metadata
obj.name = "ControlEscape"
obj.version = "0.1"
obj.author = "Jason Rudolph <jason@jasonrudolph.com>"
obj.homepage = "https://github.com/jasonrudolph/ControlEscape.spoon"
obj.license = "MIT - https://opensource.org/licenses/MIT"
function obj:init()
self.movements = 0
self.sendEscape = false
self.lastModifiers = {}
-- Create an eventtap to run each time the modifier keys change (i.e., each
-- time a key like control, shift, option, or command is pressed or released)
self.controlTap = hs.eventtap.new({ hs.eventtap.event.types.flagsChanged }, function(event)
local newModifiers = event:getFlags()
-- If this change to the modifier keys does not involve a *change* to the
-- up/down state of the `control` key (i.e., it was up before and it's
-- still up, or it was down before and it's still down), then don't take
-- any action.
if self.lastModifiers["ctrl"] == newModifiers["ctrl"] then
return false
end
-- Control was not down but is now
if not self.lastModifiers["ctrl"] then
-- Only prepare to send escape if no other modifier keys are in use
self.lastModifiers = newModifiers
if not self.lastModifiers["cmd"] and not self.lastModifiers["alt"] then
self.sendEscape = true
self.movements = 0
end
-- Control was down and is up, hasn't been blocked by another key, and
-- isn't above the movement threshold
elseif self.sendEscape == true and not newModifiers["ctrl"] and self.movements < 30 then
self.lastModifiers = newModifiers
-- Allow for shift-escape
if newModifiers["shift"] then
hs.eventtap.keyStroke({ "shift" }, "escape", 0)
else
hs.eventtap.keyStroke(newModifiers, "escape", 0)
end
self.sendEscape = false
self.movements = 0
self.numberOfCharacters = 0
-- Control was down and is up, but isn't ready to send escape
else
self.lastModifiers = newModifiers
end
end)
-- If any other key is pressed, don't send escape
self.asModifier = hs.eventtap.new({ hs.eventtap.event.types.keyDown }, function(_)
self.sendEscape = false
-- print("Don't sent escape")
end)
-- If mouse is moving significantly, don't send escape
self.scrolling = hs.eventtap.new({ hs.eventtap.event.types.gesture }, function(event)
local touches = event:getTouches()
local i, v = next(touches, nil)
while i do
if v["phase"] == "moved" then
-- Increment the movement counter
self.movements = self.movements + 1
end
i, v = next(touches, i) -- get next index
end
end)
end
--- ControlEscape:start()
--- Method
--- Start sending `escape` when `control` is pressed and released in isolation
function obj:start()
self.controlTap:start()
self.asModifier:start()
self.scrolling:start()
end
--- ControlEscape:stop()
--- Method
--- Stop sending `escape` when `control` is pressed and released in isolation
function obj:stop()
-- Stop monitoring keystrokes
self.controlTap:stop()
self.asModifier:stop()
self.scrolling:stop()
-- Reset state
self.sendEscape = false
self.lastModifiers = {}
end
return obj

View File

@ -1,298 +0,0 @@
/* Credit: https://gist.github.com/lancethomps/a5ac103f334b171f70ce2ff983220b4f */
function run(input, parameters) {
const appNames = [];
const skipAppNames = [];
const verbose = true;
const scriptName = "close_notifications_applescript";
const CLEAR_ALL_ACTION = "Clear All";
const CLEAR_ALL_ACTION_TOP = "Clear";
const CLOSE_ACTION = "Close";
const notNull = (val) => {
return val !== null && val !== undefined;
};
const isNull = (val) => {
return !notNull(val);
};
const notNullOrEmpty = (val) => {
return notNull(val) && val.length > 0;
};
const isNullOrEmpty = (val) => {
return !notNullOrEmpty(val);
};
const isError = (maybeErr) => {
return notNull(maybeErr) && (maybeErr instanceof Error || maybeErr.message);
};
const systemVersion = () => {
return Application("Finder").version().split(".").map(val => parseInt(val));
};
const systemVersionGreaterThanOrEqualTo = (vers) => {
return systemVersion()[0] >= vers;
};
const isBigSurOrGreater = () => {
return systemVersionGreaterThanOrEqualTo(11);
};
const V11_OR_GREATER = isBigSurOrGreater();
const APP_NAME_MATCHER_ROLE = V11_OR_GREATER ? "AXStaticText" : "AXImage";
const hasAppNames = notNullOrEmpty(appNames);
const hasSkipAppNames = notNullOrEmpty(skipAppNames);
const hasAppNameFilters = hasAppNames || hasSkipAppNames;
const appNameForLog = hasAppNames ? ` [${appNames.join(",")}]` : "";
const logs = [];
const log = (message, ...optionalParams) => {
let message_with_prefix = `${new Date().toISOString().replace("Z", "").replace("T", " ")} [${scriptName}]${appNameForLog} ${message}`;
console.log(message_with_prefix, optionalParams);
logs.push(message_with_prefix);
};
const logError = (message, ...optionalParams) => {
if (isError(message)) {
let err = message;
message = `${err}${err.stack ? (" " + err.stack) : ""}`;
}
log(`ERROR ${message}`, optionalParams);
};
const logErrorVerbose = (message, ...optionalParams) => {
if (verbose) {
logError(message, optionalParams);
}
};
const logVerbose = (message) => {
if (verbose) {
log(message);
}
};
const getLogLines = () => {
return logs.join("\n");
};
const getSystemEvents = () => {
let systemEvents = Application("System Events");
systemEvents.includeStandardAdditions = true;
return systemEvents;
};
const getNotificationCenter = () => {
try {
return getSystemEvents().processes.byName("NotificationCenter");
} catch (err) {
logError("Could not get NotificationCenter");
throw err;
}
};
const getNotificationCenterGroups = (retryOnError = false) => {
try {
let notificationCenter = getNotificationCenter();
if (notificationCenter.windows.length <= 0) {
return [];
}
if (!V11_OR_GREATER) {
return notificationCenter.windows();
}
return notificationCenter.windows[0].uiElements[0].uiElements[0].uiElements();
} catch (err) {
logError("Could not get NotificationCenter groups");
if (retryOnError) {
logError(err);
log("Retrying getNotificationCenterGroups...");
return getNotificationCenterGroups(false);
} else {
throw err;
}
}
};
const isClearButton = (description, name) => {
return description === "button" && name === CLEAR_ALL_ACTION_TOP;
};
const matchesAnyAppNames = (value, checkValues) => {
if (isNullOrEmpty(checkValues)) {
return false;
}
let lowerAppName = value.toLowerCase();
for (let checkValue of checkValues) {
if (lowerAppName === checkValue.toLowerCase()) {
return true;
}
}
return false;
};
const matchesAppName = (role, value) => {
if (role !== APP_NAME_MATCHER_ROLE) {
return false;
}
if (hasAppNames) {
return matchesAnyAppNames(value, appNames);
}
return !matchesAnyAppNames(value, skipAppNames);
};
const notificationGroupMatches = (group) => {
try {
let description = group.description();
if (V11_OR_GREATER && isClearButton(description, group.name())) {
return true;
}
if (V11_OR_GREATER && description !== "group") {
return false;
}
if (!V11_OR_GREATER) {
let matchedAppName = !hasAppNameFilters;
if (!matchedAppName) {
for (let elem of group.uiElements()) {
if (matchesAppName(elem.role(), elem.description())) {
matchedAppName = true;
break;
}
}
}
if (matchedAppName) {
return notNull(findCloseActionV10(group, -1));
}
return false;
}
if (!hasAppNameFilters) {
return true;
}
let firstElem = group.uiElements[0];
return matchesAppName(firstElem.role(), firstElem.value());
} catch (err) {
logErrorVerbose(`Caught error while checking window, window is probably closed: ${err}`);
logErrorVerbose(err);
}
return false;
};
const findCloseActionV10 = (group, closedCount) => {
try {
for (let elem of group.uiElements()) {
if (elem.role() === "AXButton" && elem.title() === CLOSE_ACTION) {
return elem.actions["AXPress"];
}
}
} catch (err) {
logErrorVerbose(`(group_${closedCount}) Caught error while searching for close action, window is probably closed: ${err}`);
logErrorVerbose(err);
return null;
}
log("No close action found for notification");
return null;
};
const findCloseAction = (group, closedCount) => {
try {
if (!V11_OR_GREATER) {
return findCloseActionV10(group, closedCount);
}
let checkForPress = isClearButton(group.description(), group.name());
let clearAllAction;
let closeAction;
for (let action of group.actions()) {
let description = action.description();
if (description === CLEAR_ALL_ACTION) {
clearAllAction = action;
break;
} else if (description === CLOSE_ACTION) {
closeAction = action;
} else if (checkForPress && description === "press") {
clearAllAction = action;
break;
}
}
if (notNull(clearAllAction)) {
return clearAllAction;
} else if (notNull(closeAction)) {
return closeAction;
}
} catch (err) {
logErrorVerbose(`(group_${closedCount}) Caught error while searching for close action, window is probably closed: ${err}`);
logErrorVerbose(err);
return null;
}
log("No close action found for notification");
return null;
};
const closeNextGroup = (groups, closedCount) => {
try {
for (let group of groups) {
if (notificationGroupMatches(group)) {
let closeAction = findCloseAction(group, closedCount);
if (notNull(closeAction)) {
try {
closeAction.perform();
return [true, 1];
} catch (err) {
logErrorVerbose(`(group_${closedCount}) Caught error while performing close action, window is probably closed: ${err}`);
logErrorVerbose(err);
}
}
return [true, 0];
}
}
return false;
} catch (err) {
logError("Could not run closeNextGroup");
throw err;
}
};
try {
let groupsCount = getNotificationCenterGroups(true).filter(group => notificationGroupMatches(group)).length;
if (groupsCount > 0) {
logVerbose(`Closing ${groupsCount}${appNameForLog} notification group${(groupsCount > 1 ? "s" : "")}`);
let startTime = new Date().getTime();
let closedCount = 0;
let maybeMore = true;
let maxAttempts = 2;
let attempts = 1;
while (maybeMore && ((new Date().getTime() - startTime) <= (1000 * 30))) {
try {
let closeResult = closeNextGroup(getNotificationCenterGroups(), closedCount);
maybeMore = closeResult[0];
if (maybeMore) {
closedCount = closedCount + closeResult[1];
}
} catch (innerErr) {
if (maybeMore && closedCount === 0 && attempts < maxAttempts) {
log(`Caught an error before anything closed, trying ${maxAttempts - attempts} more time(s).`)
attempts++;
} else {
throw innerErr;
}
}
}
} else {
throw Error(`No${appNameForLog} notifications found...`);
}
} catch (err) {
logError(err);
logError(err.message);
getLogLines();
throw err;
}
return getLogLines();
}

View File

@ -1,17 +0,0 @@
--- === Dismiss Alerts ===
local obj = {}
obj.__index = obj
-- Metadata
obj.name = "DismissAlerts"
obj.version = "0.1"
obj.license = "MIT - https://opensource.org/licenses/MIT"
function obj:init()
hs.hotkey.bind({ "cmd", "alt", "ctrl" }, "k", function()
hs.osascript.javascriptFromFile("Spoons/DismissAlerts.spoon/close_notifications_applescript.js")
end)
end
return obj

View File

@ -1,107 +0,0 @@
--- === Launcher ===
local obj = {}
obj.__index = obj
-- Metadata
obj.name = "Launcher"
obj.version = "0.1"
obj.license = "MIT - https://opensource.org/licenses/MIT"
function DrawSwitcher()
-- Drawing
local width = hs.screen.mainScreen():fullFrame().w
local switcherWidth = 500
local canv = hs.canvas.new({
x = width / 2 - switcherWidth / 2,
y = 1,
h = 3,
w = switcherWidth,
})
canv[#canv + 1] = {
action = "build",
type = "rectangle",
}
canv[#canv + 1] = {
type = "rectangle",
fillColor = { alpha = 1, red = 0.8, green = 0.6, blue = 0.3 },
action = "fill",
}
return canv:show()
end
function obj:init()
-- Begin launcher mode
if self.launcher == nil then
self.launcher = hs.hotkey.modal.new("ctrl", "space")
end
-- Behaviors on enter
function self.launcher:entered()
-- hs.alert("Entered mode")
self.canv = DrawSwitcher()
end
-- Behaviors on exit
function self.launcher:exited()
-- hs.alert("Exited mode")
self.canv:hide()
end
-- Use escape to exit launcher mode
self.launcher:bind("", "escape", function()
self.launcher:exit()
end)
-- Launcher shortcuts
self.launcher:bind("ctrl", "space", function() end)
self.launcher:bind("", "return", function()
self:switch("@kitty@")
end)
self.launcher:bind("", "C", function()
self:switch("Calendar.app")
end)
self.launcher:bind("", "D", function()
self:switch("@discord@")
end)
self.launcher:bind("", "E", function()
self:switch("Mail.app")
end)
self.launcher:bind("", "U", function()
self:switch("Music.app")
end)
self.launcher:bind("", "F", function()
self:switch("@firefox@")
end)
self.launcher:bind("", "H", function()
self:switch("Hammerspoon.app")
end)
self.launcher:bind("", "G", function()
self:switch("Mimestream.app")
end)
self.launcher:bind("", "M", function()
self:switch("Messages.app")
end)
self.launcher:bind("", "O", function()
self:switch("Obsidian.app")
end)
self.launcher:bind("", "P", function()
self:switch("System Preferences.app")
end)
self.launcher:bind("", "R", function()
hs.reload()
end)
self.launcher:bind("", "S", function()
self:switch("Slack.app")
end)
self.launcher:bind("", "Z", function()
self:switch("zoom.us.app")
end)
end
function obj:switch(app)
hs.application.launchOrFocus(app)
self.launcher:exit()
end
return obj

View File

@ -1,52 +0,0 @@
--- === Move Window ===
local obj = {}
obj.__index = obj
-- Metadata
obj.name = "MoveWindow"
obj.version = "0.1"
obj.license = "MIT - https://opensource.org/licenses/MIT"
function obj:init()
hs.window.animationDuration = 0
dofile(hs.spoons.resourcePath("worklayout.lua"))()
-- bind hotkey
hs.hotkey.bind({ "alt", "ctrl", "cmd" }, "n", function()
-- get the focused window
local win = hs.window.focusedWindow()
-- get the screen where the focused window is displayed, a.k.a. current screen
local screen = win:screen()
-- local nextScreen = screen:next()
-- compute the unitRect of the focused window relative to the current screen
-- and move the window to the next screen setting the same unitRect
win:moveToScreen(screen:next(), true, true, 0)
end)
hs.hotkey.bind({ "alt", "ctrl", "cmd" }, "b", function()
local win = hs.window.focusedWindow()
local screen = win:screen()
win:moveToScreen(screen:previous(), true, true, 0)
end)
hs.hotkey.bind({ "alt", "ctrl", "cmd" }, "m", function()
-- get the focused window
local win = hs.window.focusedWindow()
local frame = win:frame()
-- maximize if possible
local max = win:screen():fullFrame()
frame.x = max.x
frame.y = max.y
frame.w = max.w
frame.h = max.h
win:setFrame(frame)
-- -- first maximize to grid
-- hs.grid.maximizeWindow(win)
-- -- then spam maximize
-- for i = 1, 8 do
-- win:maximize()
-- end
end)
end
return obj

View File

@ -1,60 +0,0 @@
--- === Work Layout ===
-- Portions of this is adopted from:
-- https://github.com/anishathalye/dotfiles-local/tree/ffdadd313e58514eb622736b09b91a7d7eb7c6c9/hammerspoon
-- License is also available:
-- https://github.com/anishathalye/dotfiles-local/blob/ffdadd313e58514eb622736b09b91a7d7eb7c6c9/LICENSE.md
WORK_LEFT_MONITOR = "DELL U2415 (2)"
WORK_RIGHT_MONITOR = "DELL U2415 (1)"
LAPTOP_MONITOR = "Built-in Retina Display"
-- Used to find out the name of the monitor in Hammerspoon
-- local function dump(o)
-- if type(o) == "table" then
-- local s = "{ "
-- for k, v in pairs(o) do
-- if type(k) ~= "number" then
-- k = '"' .. k .. '"'
-- end
-- s = s .. "[" .. k .. "] = " .. dump(v) .. ","
-- end
-- return s .. "} "
-- else
-- return tostring(o)
-- end
-- end
-- Turn on when looking for the monitor name
-- print(dump(hs.screen.allScreens()))
local function concat(...)
local res = {}
for _, tab in ipairs({ ... }) do
for _, elem in ipairs(tab) do
table.insert(res, elem)
end
end
return res
end
local function worklayout()
hs.hotkey.bind({ "alt", "ctrl", "cmd" }, "l", function()
local u = hs.geometry.unitrect
-- set the layout
local left = {
{ "kitty", nil, WORK_LEFT_MONITOR, u(0, 0, 1, 1), nil, nil, visible = true },
}
local right = {
{ "Slack", nil, WORK_RIGHT_MONITOR, u(0, 0, 1, 1), nil, nil, visible = true },
{ "Mail", nil, WORK_RIGHT_MONITOR, u(0, 0, 1, 1), nil, nil, visible = true },
{ "zoom.us", nil, WORK_RIGHT_MONITOR, u(1 / 4, 1 / 4, 1 / 2, 1 / 2), nil, nil, visible = true },
}
local laptop = {
{ "Firefox", nil, LAPTOP_MONITOR, u(0, 0, 1, 1), nil, nil, visible = true },
}
local layout = concat(left, right, laptop)
hs.layout.apply(layout)
end)
end
return worklayout

View File

@ -1,4 +0,0 @@
hs.loadSpoon("ControlEscape"):start() -- Load Hammerspoon bits from https://github.com/jasonrudolph/ControlEscape.spoon
hs.loadSpoon("Launcher"):init()
hs.loadSpoon("DismissAlerts"):init()
hs.loadSpoon("MoveWindow"):init()

View File

@ -1,56 +0,0 @@
{ config, pkgs, lib, ... }: {
# Homebrew - Mac-specific packages that aren't in Nix
config = lib.mkIf pkgs.stdenv.isDarwin {
# Requires Homebrew to be installed
system.activationScripts.preUserActivation.text = ''
if ! xcode-select --version 2>/dev/null; then
$DRY_RUN_CMD xcode-select --install
fi
if ! /usr/local/bin/brew --version 2>/dev/null; then
$DRY_RUN_CMD /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
'';
homebrew = {
enable = true;
onActivation = {
autoUpdate = false; # Don't update during rebuild
cleanup = "zap"; # Uninstall all programs not declared
upgrade = true;
};
global = {
brewfile = true; # Run brew bundle from anywhere
lockfiles = false; # Don't save lockfile (since running from anywhere)
};
taps = [
"homebrew/cask" # Required for casks
"homebrew/cask-drivers" # Used for Logitech G-Hub
];
brews = [
"trash" # Delete files and folders to trash instead of rm
"openjdk" # Required by Apache Directory Studio
];
casks = [
"1password" # 1Password packaging on Nix is broken for macOS
"scroll-reverser" # Different scroll style for mouse vs. trackpad
"meetingbar" # Show meetings in menu bar
"gitify" # Git notifications in menu bar
"logitech-g-hub" # Mouse and keyboard management
"mimestream" # Gmail client
"obsidian" # Obsidian packaging on Nix is not available for macOS
"steam" # Not packaged for Nix
"apache-directory-studio" # Packaging on Nix is not available for macOS
];
};
home-manager.users.${config.user} = {
programs.fish.shellAbbrs.t = "trash";
};
};
}

View File

@ -1,18 +0,0 @@
{ config, pkgs, lib, ... }: {
# MacOS-specific settings for Kitty
home-manager.users.${config.user} = lib.mkIf pkgs.stdenv.isDarwin {
programs.kitty = {
darwinLaunchOptions = [ "--start-as=fullscreen" ];
font.size = lib.mkForce 20;
settings = {
shell = "/run/current-system/sw/bin/fish";
macos_traditional_fullscreen = true;
macos_quit_when_last_window_closed = true;
disable_ligatures = "always";
macos_option_as_alt = true;
};
};
};
}

View File

@ -1,11 +0,0 @@
{ config, pkgs, lib, ... }: {
config = lib.mkIf pkgs.stdenv.isDarwin {
networking = {
computerName = "${config.fullName}'\\''s Mac";
# Adjust if necessary
# hostName = "";
};
};
}

View File

@ -1,33 +0,0 @@
{ config, pkgs, lib, ... }: {
home-manager.users.${config.user} = lib.mkIf pkgs.stdenv.isDarwin {
programs.fish = {
shellAbbrs = {
nr = lib.mkForce "rebuild-darwin";
nro = lib.mkForce "rebuild-darwin offline";
};
functions = {
rebuild-darwin = {
body = ''
if test "$argv[1]" = "offline"
set option "--option substitute false"
end
git -C ${config.dotfilesPath} add --intent-to-add --all
commandline -r "darwin-rebuild switch $option --flake ${config.dotfilesPath}#macbook"
commandline --function execute
'';
};
rebuild-home = lib.mkForce {
body = ''
git -C ${config.dotfilesPath} add --intent-to-add --all
commandline -r "${pkgs.home-manager}/bin/home-manager switch --flake ${config.dotfilesPath}#macbook";
commandline --function execute
'';
};
};
};
};
}

View File

@ -1,186 +0,0 @@
{ pkgs, lib, ... }: {
config = lib.mkIf pkgs.stdenv.isDarwin {
services.nix-daemon.enable = true;
environment.shells = [ pkgs.fish ];
security.pam.enableSudoTouchIdAuth = true;
system = {
keyboard = {
remapCapsLockToControl = true;
enableKeyMapping = true; # Allows for skhd
};
defaults = {
NSGlobalDomain = {
# Set to dark mode
AppleInterfaceStyle = "Dark";
# Don't change from dark to light automatically
# AppleInterfaceSwitchesAutomatically = false;
# Enable full keyboard access for all controls (e.g. enable Tab in modal dialogs)
AppleKeyboardUIMode = 3;
# Automatically show and hide the menu bar
_HIHideMenuBar = true;
# Expand save panel by default
NSNavPanelExpandedStateForSaveMode = true;
# Expand print panel by default
PMPrintingExpandedStateForPrint = true;
# Replace press-and-hold with key repeat
ApplePressAndHoldEnabled = false;
# Set a fast key repeat rate
KeyRepeat = 2;
# Shorten delay before key repeat begins
InitialKeyRepeat = 12;
# Save to local disk by default, not iCloud
NSDocumentSaveNewDocumentsToCloud = false;
# Disable autocorrect capitalization
NSAutomaticCapitalizationEnabled = false;
# Disable autocorrect smart dashes
NSAutomaticDashSubstitutionEnabled = false;
# Disable autocorrect adding periods
NSAutomaticPeriodSubstitutionEnabled = false;
# Disable autocorrect smart quotation marks
NSAutomaticQuoteSubstitutionEnabled = false;
# Disable autocorrect spellcheck
NSAutomaticSpellingCorrectionEnabled = false;
};
dock = {
# Automatically show and hide the dock
autohide = true;
# Add translucency in dock for hidden applications
showhidden = true;
# Enable spring loading on all dock items
enable-spring-load-actions-on-all-items = true;
# Highlight hover effect in dock stack grid view
mouse-over-hilite-stack = true;
mineffect = "genie";
orientation = "bottom";
show-recents = false;
tilesize = 44;
};
finder = {
# Default Finder window set to column view
FXPreferredViewStyle = "clmv";
# Finder search in current folder by default
FXDefaultSearchScope = "SCcf";
# Disable warning when changing file extension
FXEnableExtensionChangeWarning = false;
# Allow quitting of Finder application
QuitMenuItem = true;
};
# Disable "Are you sure you want to open" dialog
LaunchServices.LSQuarantine = false;
# Disable trackpad tap to click
trackpad.Clicking = false;
# universalaccess = {
# # Zoom in with Control + Scroll Wheel
# closeViewScrollWheelToggle = true;
# closeViewZoomFollowsFocus = true;
# };
# Where to save screenshots
screencapture.location = "~/Downloads";
};
# Settings that don't have an option in nix-darwin
activationScripts.postActivation.text = ''
echo "Disable disk image verification"
defaults write com.apple.frameworks.diskimages skip-verify -bool true
defaults write com.apple.frameworks.diskimages skip-verify-locked -bool true
defaults write com.apple.frameworks.diskimages skip-verify-remote -bool true
echo "Avoid creating .DS_Store files on network volumes"
defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true
echo "Disable the warning before emptying the Trash"
defaults write com.apple.finder WarnOnEmptyTrash -bool false
echo "Require password immediately after sleep or screen saver begins"
defaults write com.apple.screensaver askForPassword -int 1
defaults write com.apple.screensaver askForPasswordDelay -int 0
echo "Allow apps from anywhere"
SPCTL=$(spctl --status)
if ! [ "$SPCTL" = "assessments disabled" ]; then
sudo spctl --master-disable
fi
'';
# User-level settings
activationScripts.postUserActivation.text = ''
echo "Show the ~/Library folder"
chflags nohidden ~/Library
echo "Enable dock magnification"
defaults write com.apple.dock magnification -bool true
echo "Set dock magnification size"
defaults write com.apple.dock largesize -int 48
echo "Define dock icon function"
__dock_item() {
printf "%s%s%s%s%s" \
"<dict><key>tile-data</key><dict><key>file-data</key><dict>" \
"<key>_CFURLString</key><string>" \
"$1" \
"</string><key>_CFURLStringType</key><integer>0</integer>" \
"</dict></dict></dict>"
}
echo "Choose and order dock icons"
defaults write com.apple.dock persistent-apps -array \
"$(__dock_item /Applications/1Password.app)" \
"$(__dock_item /Applications/Slack.app)" \
"$(__dock_item /System/Applications/Calendar.app)" \
"$(__dock_item ${pkgs.firefox-bin}/Applications/Firefox.app)" \
"$(__dock_item /System/Applications/Messages.app)" \
"$(__dock_item /System/Applications/Mail.app)" \
"$(__dock_item /Applications/Mimestream.app)" \
"$(__dock_item /Applications/zoom.us.app)" \
"$(__dock_item ${pkgs.discord}/Applications/Discord.app)" \
"$(__dock_item /Applications/Obsidian.app)" \
"$(__dock_item ${pkgs.kitty}/Applications/kitty.app)" \
"$(__dock_item /System/Applications/System\ Settings.app)"
'';
};
};
}

View File

@ -1,133 +0,0 @@
{ config, pkgs, lib, ... }: {
options.tmux.enable = lib.mkEnableOption "Tmux terminal multiplexer";
config.home-manager.users.${config.user} = lib.mkIf config.tmux.enable {
programs.tmux = {
enable = true;
baseIndex = 1; # Start windows and panes at 1
escapeTime = 0; # Wait time after escape is input
historyLimit = 100000;
keyMode = "vi";
newSession = true; # Automatically spawn new session
plugins = [ ];
resizeAmount = 10;
shell = "${pkgs.fish}/bin/fish";
terminal = "screen-256color";
extraConfig = ''
# Horizontal and vertical splits
bind \\ split-window -h -c '#{pane_current_path}'
bind - split-window -v -c '#{pane_current_path}'
# Move between panes with vi keys
bind h select-pane -L
bind j select-pane -D
bind K select-pane -U
bind l select-pane -R
# Split out pane
bind b break-pane
# Synchronize panes
bind S set-window-option synchronize-panes
# Copy mode works as Vim
bind Escape copy-mode
bind k copy-mode
bind C-[ copy-mode
# Use v to trigger selection
bind-key -T copy-mode-vi v send-keys -X begin-selection
# Use y to yank current selection
bind-key -T copy-mode-vi y send-keys -X copy-selection-and-cancel
# Enable mouse mode
set -g mouse on
# Status bar
set -g status-interval 60 # Seconds between refreshes
set -g renumber-windows on
set-option -g status-position bottom
## COLORSCHEME: gruvbox dark
set-option -g status "on"
# Default statusbar color
set-option -g status-style bg=colour237,fg=colour223 # bg=bg1, fg=fg1
# Default window title colors
set-window-option -g window-status-style bg=colour214,fg=colour237 # bg=yellow, fg=bg1
# Default window with an activity alert
set-window-option -g window-status-activity-style bg=colour237,fg=colour248 # bg=bg1, fg=fg3
# Active window title colors
set-window-option -g window-status-current-style bg=red,fg=colour237 # fg=bg1
# Pane border
set-option -g pane-active-border-style fg=colour250 #fg2
set-option -g pane-border-style fg=colour237 #bg1
# Message infos
set-option -g message-style bg=colour239,fg=colour223 # bg=bg2, fg=fg1
# Writing commands inactive
set-option -g message-command-style bg=colour239,fg=colour223 # bg=fg3, fg=bg1
# Pane number display
set-option -g display-panes-active-colour colour250 #fg2
set-option -g display-panes-colour colour237 #bg1
# Clock
set-window-option -g clock-mode-colour colour109 #blue
# Bell
set-window-option -g window-status-bell-style bg=colour167,fg=colour235 # bg=red, fg=bg
# Theme settings mixed with colors (unfortunately, but there is no cleaner way)
set-option -g status-justify "left"
set-option -g status-left-style none
set-option -g status-left-length "80"
set-option -g status-right-style none
set-option -g status-right-length "80"
set-window-option -g window-status-separator ""
set-option -g status-left "#[fg=colour248, bg=colour241] #S #[fg=colour241, bg=colour237, nobold, noitalics, nounderscore]"
set-option -g status-right "#[fg=colour239, bg=colour237, nobold, nounderscore, noitalics]#[fg=colour246,bg=colour239] %Y-%m-%d %H:%M #[fg=colour248, bg=colour239, nobold, noitalics, nounderscore]"
set-window-option -g window-status-current-format "#[fg=colour237, bg=colour214, nobold, noitalics, nounderscore]#[fg=colour239, bg=colour214] #I #[fg=colour239, bg=colour214, bold] #W #[fg=colour214, bg=colour237, nobold, noitalics, nounderscore]"
set-window-option -g window-status-format "#[fg=colour237,bg=colour239,noitalics]#[fg=colour223,bg=colour239] #I #[fg=colour223, bg=colour239] #W #[fg=colour239, bg=colour237, noitalics]"
'';
};
programs.alacritty.settings = {
# shell.args = [
# "--login"
# "--init-command"
# "tmux attach-session -t noah || tmux new-session -s noah"
# ];
key_bindings = [
{
key = "H";
mods = "Super|Shift";
chars = "\\x02p"; # Previous tmux window
}
{
key = "L";
mods = "Super|Shift";
chars = "\\x02n"; # Next tmux window
}
];
};
programs.fish.shellAbbrs = {
ta = "tmux attach-session";
tan = "tmux attach-session -t noah";
tnn = "tmux new-session -s noah";
};
};
}

View File

@ -1,21 +0,0 @@
{ config, pkgs, lib, ... }: {
config = lib.mkIf pkgs.stdenv.isDarwin {
users.users."${config.user}" = {
# macOS user
home = config.homePath;
shell = pkgs.fish; # Default shell
};
# Used for aerc
home-manager.users.${config.user} = {
home.sessionVariables = {
XDG_CONFIG_HOME = "${config.homePath}/.config";
};
};
};
}

View File

@ -1,53 +0,0 @@
{ config, pkgs, lib, ... }:
let
# Quickly package shell scripts with their dependencies
# From https://discourse.nixos.org/t/how-to-create-a-script-with-dependencies/7970/6
mkScript = { name, file, env ? [ ] }:
pkgs.writeScriptBin name ''
for i in ${lib.concatStringsSep " " env}; do
export PATH="$i/bin:$PATH"
done
exec ${pkgs.bash}/bin/bash ${file} $@
'';
in {
home-manager.users.${config.user} = lib.mkIf pkgs.stdenv.isDarwin {
home.packages = with pkgs; [
# visidata # CSV inspector
dos2unix # Convert Windows text files
inetutils # Includes telnet
youtube-dl # Convert web videos
pandoc # Convert text documents
mpd # TUI slideshows
awscli2
awslogs
google-cloud-sdk
ansible
vault
consul
noti # Create notifications programmatically
ipcalc # Make IP network calculations
(mkScript {
name = "ocr";
file = ../shell/bash/scripts/ocr.sh;
env = [ tesseract ];
})
];
programs.fish.shellAbbrs = {
# Add noti for ghpr in Darwin
ghpr = lib.mkForce "gh pr create && sleep 3 && noti gh run watch";
grw = lib.mkForce "noti gh run watch";
# Shortcut to edit hosts file
hosts = "sudo nvim /etc/hosts";
};
};
}