mirror of
https://github.com/nmasur/dotfiles
synced 2025-07-06 00:20:13 +00:00
Merge branch 'experimental'
This commit is contained in:
10
modules/applications/1password.nix
Normal file
10
modules/applications/1password.nix
Normal file
@ -0,0 +1,10 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
config = lib.mkIf config.gui.enable {
|
||||
unfreePackages = [ "1password" "_1password-gui" ];
|
||||
home-manager.users.${config.user} = {
|
||||
home.packages = with pkgs; [ _1password-gui ];
|
||||
};
|
||||
};
|
||||
|
||||
}
|
83
modules/applications/alacritty.nix
Normal file
83
modules/applications/alacritty.nix
Normal file
@ -0,0 +1,83 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
config = lib.mkIf config.gui.enable {
|
||||
home-manager.users.${config.user} = {
|
||||
xsession.windowManager.i3.config.terminal = "alacritty";
|
||||
programs.rofi.terminal = "${pkgs.alacritty}/bin/alacritty";
|
||||
programs.alacritty = {
|
||||
enable = true;
|
||||
settings = {
|
||||
window = {
|
||||
dimensions = {
|
||||
columns = 85;
|
||||
lines = 30;
|
||||
};
|
||||
padding = {
|
||||
x = 20;
|
||||
y = 20;
|
||||
};
|
||||
opacity = 1.0;
|
||||
};
|
||||
scrolling.history = 10000;
|
||||
font = { size = 14.0; };
|
||||
key_bindings = [
|
||||
{
|
||||
key = "L";
|
||||
mods = "Control|Shift";
|
||||
chars = "\\x1F";
|
||||
}
|
||||
{
|
||||
key = "K";
|
||||
mods = "Control";
|
||||
mode = "~Vi";
|
||||
action = "ToggleViMode";
|
||||
}
|
||||
{
|
||||
key = "Return";
|
||||
mode = "Vi";
|
||||
action = "ToggleViMode";
|
||||
}
|
||||
# Used to enable $ keybind in Vi mode
|
||||
{
|
||||
key = 5; # Scancode for key4
|
||||
mods = "Shift";
|
||||
mode = "Vi|~Search";
|
||||
action = "Last";
|
||||
}
|
||||
];
|
||||
colors = {
|
||||
primary = {
|
||||
background = config.gui.colorscheme.base00;
|
||||
foreground = config.gui.colorscheme.base05;
|
||||
};
|
||||
cursor = {
|
||||
text = "#1d2021";
|
||||
cursor = config.gui.colorscheme.base05;
|
||||
};
|
||||
normal = {
|
||||
black = "#1d2021";
|
||||
red = config.gui.colorscheme.base08;
|
||||
green = config.gui.colorscheme.base0B;
|
||||
yellow = config.gui.colorscheme.base0A;
|
||||
blue = config.gui.colorscheme.base0D;
|
||||
magenta = config.gui.colorscheme.base0E;
|
||||
cyan = config.gui.colorscheme.base0C;
|
||||
white = config.gui.colorscheme.base05;
|
||||
};
|
||||
bright = {
|
||||
black = config.gui.colorscheme.base03;
|
||||
red = config.gui.colorscheme.base09;
|
||||
green = config.gui.colorscheme.base01;
|
||||
yellow = config.gui.colorscheme.base02;
|
||||
blue = config.gui.colorscheme.base04;
|
||||
magenta = config.gui.colorscheme.base06;
|
||||
cyan = config.gui.colorscheme.base0F;
|
||||
white = config.gui.colorscheme.base07;
|
||||
};
|
||||
};
|
||||
draw_bold_text_with_bright_colors = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
10
modules/applications/calibre.nix
Normal file
10
modules/applications/calibre.nix
Normal file
@ -0,0 +1,10 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
config = lib.mkIf config.gui.enable {
|
||||
home-manager.users.${config.user} = {
|
||||
home.packages = with pkgs; [ calibre ];
|
||||
# home.sessionVariables = { CALIBRE_USE_DARK_PALETTE = 1; };
|
||||
};
|
||||
environment.sessionVariables = { CALIBRE_USE_DARK_PALETTE = "1"; };
|
||||
};
|
||||
}
|
15
modules/applications/default.nix
Normal file
15
modules/applications/default.nix
Normal file
@ -0,0 +1,15 @@
|
||||
{ ... }: {
|
||||
|
||||
imports = [
|
||||
./1password.nix
|
||||
./alacritty.nix
|
||||
./calibre.nix
|
||||
./discord.nix
|
||||
./firefox.nix
|
||||
./media.nix
|
||||
./obsidian.nix
|
||||
./qbittorrent.nix
|
||||
./nautilus.nix
|
||||
];
|
||||
|
||||
}
|
19
modules/applications/discord.nix
Normal file
19
modules/applications/discord.nix
Normal file
@ -0,0 +1,19 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
config = lib.mkIf config.gui.enable {
|
||||
unfreePackages = [ "discord" ];
|
||||
home-manager.users.${config.user} = {
|
||||
home.packages = with pkgs; [ discord ];
|
||||
xdg.configFile."discord/settings.json".text = ''
|
||||
{
|
||||
"BACKGROUND_COLOR": "#202225",
|
||||
"IS_MAXIMIZED": false,
|
||||
"IS_MINIMIZED": false,
|
||||
"OPEN_ON_STARTUP": false,
|
||||
"MINIMIZE_TO_TRAY": false,
|
||||
"SKIP_HOST_UPDATE": true
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
121
modules/applications/firefox.nix
Normal file
121
modules/applications/firefox.nix
Normal file
@ -0,0 +1,121 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
config = lib.mkIf config.gui.enable {
|
||||
|
||||
unfreePackages = [ "onepassword-password-manager" "okta-browser-plugin" ];
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
programs.firefox = {
|
||||
enable = true;
|
||||
extensions = with pkgs.nur.repos.rycee.firefox-addons; [
|
||||
ublock-origin
|
||||
vimium
|
||||
multi-account-containers
|
||||
facebook-container
|
||||
temporary-containers
|
||||
onepassword-password-manager
|
||||
okta-browser-plugin
|
||||
sponsorblock
|
||||
reddit-enhancement-suite
|
||||
bypass-paywalls-clean
|
||||
markdownload
|
||||
darkreader
|
||||
snowflake
|
||||
don-t-fuck-with-paste
|
||||
i-dont-care-about-cookies
|
||||
];
|
||||
profiles.Profile0 = {
|
||||
id = 0;
|
||||
name = "default";
|
||||
isDefault = true;
|
||||
settings = {
|
||||
"browser.aboutConfig.showWarning" = false;
|
||||
"browser.warnOnQuit" = false;
|
||||
"browser.theme.dark-private-windows" = true;
|
||||
"browser.toolbars.bookmarks.visibility" = "newtab";
|
||||
"browser.startup.page" = 3; # Restore previous session
|
||||
"browser.newtabpage.enabled" = false; # Make new tabs blank
|
||||
"general.autoScroll" = true; # Drag middle-mouse to scroll
|
||||
"services.sync.prefs.sync.general.autoScroll" =
|
||||
false; # Prevent disabling autoscroll
|
||||
"extensions.pocket.enabled" = false;
|
||||
"toolkit.legacyUserProfileCustomizations.stylesheets" =
|
||||
true; # Allow userChrome.css
|
||||
"layout.css.color-mix.enabled" = true;
|
||||
};
|
||||
userChrome = ''
|
||||
:root {
|
||||
--focus-outline-color: ${config.gui.colorscheme.base04} !important;
|
||||
--toolbar-color: ${config.gui.colorscheme.base07} !important;
|
||||
--tab-min-height: 30px !important;
|
||||
}
|
||||
/* Background of tab bar */
|
||||
.toolbar-items {
|
||||
background-color: ${config.gui.colorscheme.base00} !important;
|
||||
}
|
||||
/* Tabs themselves */
|
||||
.tabbrowser-tab .tab-stack {
|
||||
border-radius: 5px 5px 0 0;
|
||||
overflow: hidden;
|
||||
background-color: ${config.gui.colorscheme.base00};
|
||||
color: ${config.gui.colorscheme.base06} !important;
|
||||
}
|
||||
.tab-content {
|
||||
border-bottom: 2px solid color-mix(in srgb, var(--identity-tab-color) 40%, transparent);
|
||||
border-radius: 5px 5px 0 0;
|
||||
background-color: ${config.gui.colorscheme.base00};
|
||||
color: ${config.gui.colorscheme.base06} !important;
|
||||
}
|
||||
.tab-content[selected=true] {
|
||||
border-bottom: 2px solid color-mix(in srgb, var(--identity-tab-color) 25%, transparent);
|
||||
background-color: ${config.gui.colorscheme.base01} !important;
|
||||
color: ${config.gui.colorscheme.base07} !important;
|
||||
}
|
||||
/* Below tab bar */
|
||||
#nav-bar {
|
||||
background: ${config.gui.colorscheme.base01} !important;
|
||||
}
|
||||
/* URL bar in nav bar */
|
||||
#urlbar[focused=true] {
|
||||
color: ${config.gui.colorscheme.base07} !important;
|
||||
background: ${config.gui.colorscheme.base02} !important;
|
||||
caret-color: ${config.gui.colorscheme.base05} !important;
|
||||
}
|
||||
#urlbar:not([focused=true]) {
|
||||
color: ${config.gui.colorscheme.base04} !important;
|
||||
background: ${config.gui.colorscheme.base02} !important;
|
||||
}
|
||||
#urlbar ::-moz-selection {
|
||||
color: ${config.gui.colorscheme.base07} !important;
|
||||
background: ${config.gui.colorscheme.base02} !important;
|
||||
}
|
||||
#urlbar-input-container {
|
||||
border: 1px solid ${config.gui.colorscheme.base01} !important;
|
||||
}
|
||||
#urlbar-background {
|
||||
background: ${config.gui.colorscheme.base01} !important;
|
||||
}
|
||||
/* Text in URL bar */
|
||||
#urlbar-input, #urlbar-scheme, .searchbar-textbox {
|
||||
color: ${config.gui.colorscheme.base07} !important;
|
||||
}
|
||||
'';
|
||||
userContent = ''
|
||||
@-moz-document url-prefix(about:blank) {
|
||||
* {
|
||||
background-color:${config.gui.colorscheme.base01} !important;
|
||||
}
|
||||
}
|
||||
'';
|
||||
|
||||
extraConfig = "";
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{ config, ... }: {
|
||||
config = {
|
||||
services.keybase.enable = true;
|
||||
services.kbfs.enable = true;
|
||||
};
|
||||
}
|
11
modules/applications/media.nix
Normal file
11
modules/applications/media.nix
Normal file
@ -0,0 +1,11 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
config = lib.mkIf config.gui.enable {
|
||||
home-manager.users.${config.user}.home.packages = with pkgs; [
|
||||
mpv # Video viewer
|
||||
sxiv # Image viewer
|
||||
mupdf # PDF viewer
|
||||
];
|
||||
};
|
||||
|
||||
}
|
13
modules/applications/nautilus.nix
Normal file
13
modules/applications/nautilus.nix
Normal file
@ -0,0 +1,13 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
# Install Nautilus file manager
|
||||
config = lib.mkIf config.gui.enable {
|
||||
home-manager.users.${config.user} = {
|
||||
home.packages = with pkgs; [
|
||||
gnome.nautilus
|
||||
gnome.sushi # Quick preview with spacebar
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
}
|
10
modules/applications/obsidian.nix
Normal file
10
modules/applications/obsidian.nix
Normal file
@ -0,0 +1,10 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
config = lib.mkIf config.gui.enable {
|
||||
unfreePackages = [ "obsidian" ];
|
||||
home-manager.users.${config.user} = {
|
||||
home.packages = with pkgs; [ obsidian ];
|
||||
};
|
||||
};
|
||||
|
||||
}
|
12
modules/applications/qbittorrent.nix
Normal file
12
modules/applications/qbittorrent.nix
Normal file
@ -0,0 +1,12 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
config = lib.mkIf config.gui.enable {
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
home.packages = with pkgs; [ qbittorrent ];
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
}
|
20
modules/colorscheme/everforest/default.nix
Normal file
20
modules/colorscheme/everforest/default.nix
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
name = "everforest"; # dark, hard
|
||||
author = "Sainnhe Park";
|
||||
base00 = "#2b3339"; # Default Background
|
||||
base01 = "#323c41"; # Lighter Background
|
||||
base02 = "#503946"; # Selection Background
|
||||
base03 = "#868d80"; # Comments, Invisibles, Line Highlighting
|
||||
base04 = "#d3c6aa"; # Dark Foreground (Used for status bars)
|
||||
base05 = "#d3c6aa"; # Default Foreground, Caret, Delimiters, Operators
|
||||
base06 = "#e9e8d2"; # Light Foreground (Not often used)
|
||||
base07 = "#fff9e8"; # Light Background (Not often used)
|
||||
base08 = "#7fbbb3"; # Variables, XML Tags, Markup Link Text, ...
|
||||
base09 = "#d699b6"; # Integers, Boolean, Constants, ...
|
||||
base0A = "#83c092"; # Classes, Markup Bold, Search Text Background
|
||||
base0B = "#dbbc7f"; # Strings, Inherited Class, Markup Code, Diff Inserted
|
||||
base0C = "#e69875"; # Support, Regular Expressions, Escape Characters, ...
|
||||
base0D = "#a7c080"; # Functions, Methods, Attribute IDs, Headings
|
||||
base0E = "#e67e80"; # Keywords, Storage, Selector, Markup Italic, Diff Changed
|
||||
base0F = "#d699b6"; # Deprecated, Opening/Closing Embedded Language Tags, ...
|
||||
}
|
21
modules/colorscheme/gruvbox/default.nix
Normal file
21
modules/colorscheme/gruvbox/default.nix
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
name = "gruvbox"; # Dark, Medium
|
||||
author =
|
||||
"Dawid Kurek (dawikur@gmail.com), morhetz (https://github.com/morhetz/gruvbox)";
|
||||
base00 = "#282828"; # ----
|
||||
base01 = "#3c3836"; # ---
|
||||
base02 = "#504945"; # --
|
||||
base03 = "#665c54"; # -
|
||||
base04 = "#bdae93"; # +
|
||||
base05 = "#d5c4a1"; # ++
|
||||
base06 = "#ebdbb2"; # +++
|
||||
base07 = "#fbf1c7"; # ++++
|
||||
base08 = "#fb4934"; # red
|
||||
base09 = "#fe8019"; # orange
|
||||
base0A = "#fabd2f"; # yellow
|
||||
base0B = "#b8bb26"; # green
|
||||
base0C = "#8ec07c"; # aqua/cyan
|
||||
base0D = "#83a598"; # blue
|
||||
base0E = "#d3869b"; # purple
|
||||
base0F = "#d65d0e"; # brown
|
||||
}
|
20
modules/colorscheme/nord/default.nix
Normal file
20
modules/colorscheme/nord/default.nix
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
name = "nord";
|
||||
author = "arcticicestudio";
|
||||
base00 = "#2E3440";
|
||||
base01 = "#3B4252";
|
||||
base02 = "#434C5E";
|
||||
base03 = "#4C566A";
|
||||
base04 = "#D8DEE9";
|
||||
base05 = "#E5E9F0";
|
||||
base06 = "#ECEFF4";
|
||||
base07 = "#8FBCBB";
|
||||
base08 = "#88C0D0";
|
||||
base09 = "#81A1C1";
|
||||
base0A = "#5E81AC";
|
||||
base0B = "#BF616A";
|
||||
base0C = "#D08770";
|
||||
base0D = "#EBCB8B";
|
||||
base0E = "#A3BE8C";
|
||||
base0F = "#B48EAD";
|
||||
}
|
23
modules/darwin/alacritty.nix
Normal file
23
modules/darwin/alacritty.nix
Normal file
@ -0,0 +1,23 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
# MacOS-specific settings for Alacritty
|
||||
home-manager.users.${config.user} = {
|
||||
programs.alacritty.settings = {
|
||||
font.size = lib.mkForce 20.0;
|
||||
shell.program = "${pkgs.fish}/bin/fish";
|
||||
key_bindings = [
|
||||
{
|
||||
key = "F";
|
||||
mods = "Super";
|
||||
action = "ToggleSimpleFullscreen";
|
||||
}
|
||||
{
|
||||
key = "L";
|
||||
mods = "Super";
|
||||
chars = "\\x1F";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
}
|
15
modules/darwin/default.nix
Normal file
15
modules/darwin/default.nix
Normal file
@ -0,0 +1,15 @@
|
||||
{ ... }: {
|
||||
|
||||
imports = [
|
||||
./alacritty.nix
|
||||
./dotfiles.nix
|
||||
./fonts.nix
|
||||
./hammerspoon.nix
|
||||
./homebrew.nix
|
||||
./system.nix
|
||||
./tmux.nix
|
||||
./user.nix
|
||||
./utilities.nix
|
||||
];
|
||||
|
||||
}
|
28
modules/darwin/dotfiles.nix
Normal file
28
modules/darwin/dotfiles.nix
Normal file
@ -0,0 +1,28 @@
|
||||
{ config, ... }: {
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
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
|
||||
pushd ${config.dotfilesPath}
|
||||
git add --all
|
||||
popd
|
||||
commandline -r "darwin-rebuild switch $option --flake ${config.dotfilesPath}#macbook"
|
||||
commandline -f execute
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
14
modules/darwin/fonts.nix
Normal file
14
modules/darwin/fonts.nix
Normal file
@ -0,0 +1,14 @@
|
||||
{ config, pkgs, ... }: {
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
home.packages = with pkgs;
|
||||
[ (nerdfonts.override { fonts = [ "FiraCode" ]; }) ];
|
||||
|
||||
programs.alacritty.settings = {
|
||||
font.normal.family = "FiraCode Nerd Font Mono";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
15
modules/darwin/hammerspoon.nix
Normal file
15
modules/darwin/hammerspoon.nix
Normal file
@ -0,0 +1,15 @@
|
||||
{ config, ... }: {
|
||||
|
||||
# Hammerspoon - MacOS custom automation scripting
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
xdg.configFile.hammerspoon = { source = ./hammerspoon; };
|
||||
};
|
||||
|
||||
homebrew.casks = [ "hammerspoon" ];
|
||||
|
||||
system.activationScripts.hammerspoon.text = ''
|
||||
defaults write org.hammerspoon.Hammerspoon MJConfigFile "~/.config/hammerspoon/init.lua"
|
||||
'';
|
||||
|
||||
}
|
120
modules/darwin/hammerspoon/Spoons/ControlEscape.spoon/init.lua
Normal file
120
modules/darwin/hammerspoon/Spoons/ControlEscape.spoon/init.lua
Normal file
@ -0,0 +1,120 @@
|
||||
--- === 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(event)
|
||||
self.sendEscape = false
|
||||
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
|
@ -0,0 +1,298 @@
|
||||
/* 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();
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
--- === 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
|
110
modules/darwin/hammerspoon/Spoons/Launcher.spoon/init.lua
Normal file
110
modules/darwin/hammerspoon/Spoons/Launcher.spoon/init.lua
Normal file
@ -0,0 +1,110 @@
|
||||
--- === 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
|
||||
width = hs.screen.mainScreen():fullFrame().w
|
||||
switcherWidth = 500
|
||||
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("", "space", function()
|
||||
hs.hints.windowHints()
|
||||
self.launcher:exit()
|
||||
end)
|
||||
self.launcher:bind("", "return", function()
|
||||
self:switch("Alacritty.app")
|
||||
end)
|
||||
self.launcher:bind("", "C", function()
|
||||
self:switch("Calendar.app")
|
||||
end)
|
||||
self.launcher:bind("", "D", function()
|
||||
self:switch("Discord.app")
|
||||
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.app")
|
||||
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
|
40
modules/darwin/hammerspoon/Spoons/MoveWindow.spoon/init.lua
Normal file
40
modules/darwin/hammerspoon/Spoons/MoveWindow.spoon/init.lua
Normal file
@ -0,0 +1,40 @@
|
||||
--- === 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()
|
||||
-- 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()
|
||||
-- maximize if possible
|
||||
for i = 1, 8 do
|
||||
win:maximize()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
return obj
|
4
modules/darwin/hammerspoon/init.lua
Normal file
4
modules/darwin/hammerspoon/init.lua
Normal file
@ -0,0 +1,4 @@
|
||||
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()
|
51
modules/darwin/homebrew.nix
Normal file
51
modules/darwin/homebrew.nix
Normal file
@ -0,0 +1,51 @@
|
||||
{ config, ... }: {
|
||||
|
||||
# Homebrew - Mac-specific packages that aren't in Nix
|
||||
# Requires Homebrew to be installed (works if you rebuild twice)
|
||||
|
||||
homebrew = {
|
||||
enable = true;
|
||||
autoUpdate = false; # Don't update during rebuild
|
||||
cleanup = "zap"; # Uninstall all programs not declared
|
||||
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
|
||||
];
|
||||
casks = [
|
||||
"firefox" # Firefox packaging on Nix is broken for MacOS
|
||||
"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
|
||||
];
|
||||
global.brewfile = true; # Run brew bundle from anywhere
|
||||
global.noLock = true; # Don't save lockfile (since running from anywhere)
|
||||
};
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
home.activation = {
|
||||
|
||||
# Always install homebrew if it doesn't exist
|
||||
installHomeBrew =
|
||||
config.home-manager.users.${config.user}.lib.dag.entryAfter
|
||||
[ "writeBoundary" ] ''
|
||||
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
|
||||
'';
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
8
modules/darwin/networking.nix
Normal file
8
modules/darwin/networking.nix
Normal file
@ -0,0 +1,8 @@
|
||||
{ ... }: {
|
||||
|
||||
networking = {
|
||||
computerName = "MacBook"; # Host name
|
||||
hostName = "MacBook";
|
||||
};
|
||||
|
||||
}
|
175
modules/darwin/system.nix
Normal file
175
modules/darwin/system.nix
Normal file
@ -0,0 +1,175 @@
|
||||
{ ... }: {
|
||||
|
||||
services.nix-daemon.enable = 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 "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 "Choose and order dock icons"
|
||||
__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>'
|
||||
}
|
||||
|
||||
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 /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 /Applications/Obsidian.app)" \
|
||||
"$(__dock_item /Applications/Alacritty.app)" \
|
||||
"$(__dock_item /System/Applications/System\ Preferences.app)"
|
||||
|
||||
echo "Allow apps from anywhere"
|
||||
SPCTL=$(spctl --status)
|
||||
if ! [ "$SPCTL" = "assessments disabled" ]
|
||||
then
|
||||
sudo spctl --master-disable
|
||||
fi
|
||||
|
||||
echo "Show the ~/Library folder"
|
||||
chflags nohidden ~/Library
|
||||
'';
|
||||
};
|
||||
|
||||
}
|
125
modules/darwin/tmux.nix
Normal file
125
modules/darwin/tmux.nix
Normal file
@ -0,0 +1,125 @@
|
||||
{ config, pkgs, ... }: {
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
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
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
8
modules/darwin/user.nix
Normal file
8
modules/darwin/user.nix
Normal file
@ -0,0 +1,8 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
users.users."${config.user}" = { # macOS user
|
||||
home = config.homePath;
|
||||
shell = pkgs.zsh; # Default shell
|
||||
};
|
||||
|
||||
}
|
21
modules/darwin/utilities.nix
Normal file
21
modules/darwin/utilities.nix
Normal file
@ -0,0 +1,21 @@
|
||||
{ config, pkgs, ... }: {
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
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
|
||||
kubectl
|
||||
k9s
|
||||
noti # Create notifications programmatically
|
||||
];
|
||||
|
||||
};
|
||||
|
||||
}
|
5
modules/editor/default.nix
Normal file
5
modules/editor/default.nix
Normal file
@ -0,0 +1,5 @@
|
||||
{ ... }: {
|
||||
|
||||
imports = [ ./neovim ./notes.nix ./dotfiles.nix ];
|
||||
|
||||
}
|
42
modules/editor/dotfiles.nix
Normal file
42
modules/editor/dotfiles.nix
Normal file
@ -0,0 +1,42 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
home.activation = {
|
||||
|
||||
# Always clone dotfiles repository if it doesn't exist
|
||||
cloneDotfiles =
|
||||
config.home-manager.users.${config.user}.lib.dag.entryAfter
|
||||
[ "writeBoundary" ] ''
|
||||
if [ ! -d "${config.dotfilesPath}" ]; then
|
||||
$DRY_RUN_CMD mkdir --parents $VERBOSE_ARG $(dirname "${config.dotfilesPath}")
|
||||
$DRY_RUN_CMD ${pkgs.git}/bin/git clone ${config.dotfilesRepo} "${config.dotfilesPath}"
|
||||
fi
|
||||
'';
|
||||
|
||||
};
|
||||
|
||||
programs.fish = {
|
||||
shellAbbrs = {
|
||||
nr = "rebuild-nixos";
|
||||
nro = "rebuild-nixos offline";
|
||||
};
|
||||
functions = {
|
||||
rebuild-nixos = {
|
||||
body = ''
|
||||
if test "$argv[1]" = "offline"
|
||||
set option "--option substitute false"
|
||||
end
|
||||
pushd ${config.dotfilesPath}
|
||||
git add --all
|
||||
popd
|
||||
commandline -r "doas nixos-rebuild switch $option --flake ${config.dotfilesPath}"
|
||||
commandline -f execute
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
13
modules/editor/neovim/bootstrap.lua
Normal file
13
modules/editor/neovim/bootstrap.lua
Normal file
@ -0,0 +1,13 @@
|
||||
-- Bootstrap the Packer plugin manager
|
||||
local fn = vim.fn
|
||||
local install_path = fn.stdpath("data") .. "/site/pack/packer/start/packer.nvim"
|
||||
if fn.empty(fn.glob(install_path)) > 0 then
|
||||
packer_bootstrap = fn.system({
|
||||
"git",
|
||||
"clone",
|
||||
"--depth",
|
||||
"1",
|
||||
"https://github.com/wbthomason/packer.nvim",
|
||||
install_path,
|
||||
})
|
||||
end
|
11
modules/editor/neovim/colors.lua
Normal file
11
modules/editor/neovim/colors.lua
Normal file
@ -0,0 +1,11 @@
|
||||
-- Colorscheme
|
||||
use({
|
||||
"morhetz/gruvbox",
|
||||
config = function()
|
||||
vim.g.gruvbox_italic = 1
|
||||
vim.cmd([[
|
||||
autocmd ColorScheme * highlight Normal ctermbg=NONE guibg=NONE
|
||||
colorscheme gruvbox
|
||||
]])
|
||||
end,
|
||||
})
|
87
modules/editor/neovim/completion.lua
Normal file
87
modules/editor/neovim/completion.lua
Normal file
@ -0,0 +1,87 @@
|
||||
-- =======================================================================
|
||||
-- Completion System
|
||||
-- =======================================================================
|
||||
|
||||
-- Completion sources
|
||||
use("hrsh7th/cmp-nvim-lsp") --- Language server completion plugin
|
||||
use("hrsh7th/cmp-buffer") --- Generic text completion
|
||||
use("hrsh7th/cmp-path") --- Local file completion
|
||||
use("hrsh7th/cmp-cmdline") --- Command line completion
|
||||
use("hrsh7th/cmp-nvim-lua") --- Nvim lua api completion
|
||||
use("saadparwaiz1/cmp_luasnip") --- Luasnip completion
|
||||
use("lukas-reineke/cmp-rg") --- Ripgrep completion
|
||||
|
||||
-- Completion engine
|
||||
use({
|
||||
"hrsh7th/nvim-cmp",
|
||||
requires = { "L3MON4D3/LuaSnip" },
|
||||
config = function()
|
||||
local cmp = require("cmp")
|
||||
cmp.setup({
|
||||
snippet = {
|
||||
expand = function(args)
|
||||
require("luasnip").lsp_expand(args.body)
|
||||
end,
|
||||
},
|
||||
mapping = {
|
||||
["<C-d>"] = cmp.mapping(cmp.mapping.scroll_docs(-4), { "i", "c" }),
|
||||
["<C-f>"] = cmp.mapping(cmp.mapping.scroll_docs(4), { "i", "c" }),
|
||||
["<Esc>"] = function(fallback)
|
||||
cmp.mapping({
|
||||
i = cmp.mapping.abort(),
|
||||
c = cmp.mapping.close(),
|
||||
})
|
||||
vim.cmd("stopinsert") --- Abort and leave insert mode
|
||||
end,
|
||||
-- ['<Tab>'] = cmp.mapping(cmp.mapping.select_next_item(), { 'i', 's' }),
|
||||
-- ['<S-Tab>'] = cmp.mapping(cmp.mapping.select_prev_item(), { 'i', 's' }),
|
||||
["<CR>"] = cmp.mapping.confirm({
|
||||
behavior = cmp.ConfirmBehavior.Insert,
|
||||
select = true,
|
||||
}),
|
||||
["<C-r>"] = cmp.mapping.confirm({
|
||||
behavior = cmp.ConfirmBehavior.Replace,
|
||||
select = true,
|
||||
}),
|
||||
["<C-l>"] = cmp.mapping(function(fallback)
|
||||
if require("luasnip").expand_or_jumpable() then
|
||||
require("luasnip").expand_or_jump()
|
||||
end
|
||||
end, { "i", "s" }),
|
||||
},
|
||||
sources = {
|
||||
{ name = "nvim_lua" },
|
||||
{ name = "nvim_lsp" },
|
||||
{ name = "path" },
|
||||
{ name = "luasnip" },
|
||||
{ name = "buffer", keyword_length = 3, max_item_count = 10 },
|
||||
{
|
||||
name = "rg",
|
||||
keyword_length = 6,
|
||||
max_item_count = 10,
|
||||
option = { additional_arguments = "--ignore-case" },
|
||||
},
|
||||
},
|
||||
experimental = {
|
||||
native_menu = false, --- Use cmp menu instead of Vim menu
|
||||
ghost_text = true, --- Show preview auto-completion
|
||||
},
|
||||
})
|
||||
|
||||
-- Use buffer source for `/`
|
||||
cmp.setup.cmdline("/", {
|
||||
sources = {
|
||||
{ name = "buffer", keyword_length = 5 },
|
||||
},
|
||||
})
|
||||
|
||||
-- Use cmdline & path source for ':'
|
||||
cmp.setup.cmdline(":", {
|
||||
sources = cmp.config.sources({
|
||||
{ name = "path" },
|
||||
}, {
|
||||
{ name = "cmdline" },
|
||||
}),
|
||||
})
|
||||
end,
|
||||
})
|
63
modules/editor/neovim/default.nix
Normal file
63
modules/editor/neovim/default.nix
Normal file
@ -0,0 +1,63 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
home.packages = with pkgs; [
|
||||
neovim
|
||||
gcc # for tree-sitter
|
||||
];
|
||||
|
||||
xdg.configFile = {
|
||||
"nvim/init.lua".text = lib.mkMerge [
|
||||
(lib.mkOrder 100 ''
|
||||
${builtins.readFile ./bootstrap.lua}
|
||||
require("packer").startup(function(use)
|
||||
${builtins.readFile ./packer-basics.lua}
|
||||
'')
|
||||
(lib.mkOrder 200 ''
|
||||
${builtins.readFile ./colors.lua}
|
||||
'')
|
||||
(lib.mkOrder 300 ''
|
||||
${builtins.readFile ./lsp.lua}
|
||||
'')
|
||||
(lib.mkOrder 400 ''
|
||||
${builtins.readFile ./completion.lua}
|
||||
'')
|
||||
(lib.mkOrder 500 ''
|
||||
${builtins.readFile ./syntax.lua}
|
||||
'')
|
||||
(lib.mkOrder 600 ''
|
||||
${builtins.readFile ./telescope.lua}
|
||||
'')
|
||||
(lib.mkOrder 700 ''
|
||||
${builtins.readFile ./packer-sync.lua}
|
||||
end)
|
||||
'')
|
||||
(lib.mkOrder 800 ''
|
||||
${builtins.readFile ./settings.lua}
|
||||
${builtins.readFile ./functions.lua}
|
||||
${builtins.readFile ./keybinds.lua}
|
||||
'')
|
||||
];
|
||||
};
|
||||
|
||||
programs.git.extraConfig.core.editor = "nvim";
|
||||
home.sessionVariables = {
|
||||
EDITOR = "nvim";
|
||||
MANPAGER = "nvim +Man!";
|
||||
};
|
||||
programs.fish = {
|
||||
shellAliases = { vim = "nvim"; };
|
||||
shellAbbrs = {
|
||||
v = lib.mkForce "nvim";
|
||||
vl = lib.mkForce "nvim -c 'normal! `0'";
|
||||
vll = "nvim -c 'Telescope oldfiles'";
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
# Used for icons in Vim
|
||||
fonts.fonts = with pkgs; [ nerdfonts ];
|
||||
|
||||
}
|
49
modules/editor/neovim/functions.lua
Normal file
49
modules/editor/neovim/functions.lua
Normal file
@ -0,0 +1,49 @@
|
||||
-- ===========================================================================
|
||||
-- Custom Functions
|
||||
-- ===========================================================================
|
||||
|
||||
grep_notes = function()
|
||||
local opts = {
|
||||
prompt_title = "Search Notes",
|
||||
cwd = "$NOTES_PATH",
|
||||
}
|
||||
require("telescope.builtin").live_grep(opts)
|
||||
end
|
||||
|
||||
find_notes = function()
|
||||
local opts = {
|
||||
prompt_title = "Find Notes",
|
||||
cwd = "$NOTES_PATH",
|
||||
}
|
||||
require("telescope.builtin").find_files(opts)
|
||||
end
|
||||
|
||||
find_downloads = function()
|
||||
local opts = {
|
||||
prompt_title = "Find Downloads",
|
||||
cwd = "~/downloads",
|
||||
}
|
||||
require("telescope").extensions.file_browser.file_browser(opts)
|
||||
end
|
||||
|
||||
choose_project = function()
|
||||
local opts = require("telescope.themes").get_ivy({
|
||||
layout_config = {
|
||||
bottom_pane = {
|
||||
height = 10,
|
||||
},
|
||||
},
|
||||
})
|
||||
require("telescope").extensions.project.project(opts)
|
||||
end
|
||||
|
||||
command_history = function()
|
||||
local opts = require("telescope.themes").get_ivy({
|
||||
layout_config = {
|
||||
bottom_pane = {
|
||||
height = 15,
|
||||
},
|
||||
},
|
||||
})
|
||||
require("telescope.builtin").command_history(opts)
|
||||
end
|
121
modules/editor/neovim/keybinds.lua
Normal file
121
modules/editor/neovim/keybinds.lua
Normal file
@ -0,0 +1,121 @@
|
||||
-- ===========================================================================
|
||||
-- Key Mapping
|
||||
-- ===========================================================================
|
||||
|
||||
-- Function to cut down config boilerplate
|
||||
local key = function(mode, key_sequence, action, params)
|
||||
params = params or {}
|
||||
params["noremap"] = true
|
||||
vim.api.nvim_set_keymap(mode, key_sequence, action, params)
|
||||
end
|
||||
|
||||
-- Remap space as leader key
|
||||
key("", "<Space>", "<Nop>", { silent = true })
|
||||
vim.g.mapleader = " "
|
||||
vim.g.maplocalleader = " "
|
||||
|
||||
-- Keep selection when changing indentation
|
||||
key("v", "<", "<gv")
|
||||
key("v", ">", ">gv")
|
||||
|
||||
-- Clear search register
|
||||
key("n", "<CR>", ":noh<CR><CR>", { silent = true })
|
||||
|
||||
-- Shuffle lines around
|
||||
key("n", "<A-j>", ":m .+1<CR>==")
|
||||
key("n", "<A-k>", ":m .-2<CR>==")
|
||||
key("i", "<A-j>", "<Esc>:m .+1<CR>==gi")
|
||||
key("i", "<A-k>", "<Esc>:m .-2<CR>==gi")
|
||||
key("v", "<A-j>", ":m '>+1<CR>gv=gv")
|
||||
key("v", "<A-k>", ":m '<-2<CR>gv=gv")
|
||||
|
||||
-- Telescope (fuzzy finder)
|
||||
key("n", "<Leader>k", ":Telescope keymaps<CR>")
|
||||
key("n", "<Leader>/", ":Telescope live_grep<CR>")
|
||||
key("n", "<Leader>ff", ":Telescope find_files<CR>")
|
||||
key("n", "<Leader>fp", ":Telescope git_files<CR>")
|
||||
key("n", "<Leader>fN", "<Cmd>lua find_notes()<CR>")
|
||||
key("n", "<Leader>N", "<Cmd>lua grep_notes()<CR>")
|
||||
key("n", "<Leader>fD", "<Cmd>lua find_downloads()<CR>")
|
||||
key("n", "<Leader>fa", ":Telescope file_browser<CR>")
|
||||
key("n", "<Leader>fw", ":Telescope grep_string<CR>")
|
||||
key("n", "<Leader>wt", ":Telescope tmux sessions<CR>")
|
||||
key("n", "<Leader>ww", ":Telescope tmux windows<CR>")
|
||||
key("n", "<Leader>w/", ":Telescope tmux pane_contents<CR>")
|
||||
key("n", "<Leader>fz", ":Telescope zoxide list<CR>")
|
||||
key("n", "<Leader>b", ":Telescope buffers<CR>")
|
||||
key("n", "<Leader>hh", ":Telescope help_tags<CR>")
|
||||
key("n", "<Leader>fr", ":Telescope oldfiles<CR>")
|
||||
key("n", "<Leader>cc", ":Telescope commands<CR>")
|
||||
key("n", "<Leader>cr", "<Cmd>lua command_history()<CR>")
|
||||
key("n", "<Leader>y", "<Cmd>lua clipboard_history()<CR>")
|
||||
key("i", "<c-y>", "<Cmd>lua clipboard_history()<CR>")
|
||||
key("n", "<Leader>s", ":Telescope current_buffer_fuzzy_find<CR>")
|
||||
key("n", "<Leader>gc", ":Telescope git_commits<CR>")
|
||||
key("n", "<Leader>gf", ":Telescope git_bcommits<CR>")
|
||||
key("n", "<Leader>gb", ":Telescope git_branches<CR>")
|
||||
key("n", "<Leader>gs", ":Telescope git_status<CR>")
|
||||
key("n", "<C-p>", "<Cmd>lua choose_project()<CR>")
|
||||
|
||||
-- Buffer tabs (tmux interferes)
|
||||
-- key("n", "<C-L>", "gt")
|
||||
-- key("i", "<C-L>", "<Esc>gt")
|
||||
-- key("n", "<C-H>", "gT")
|
||||
-- key("i", "<C-H>", "<Esc>gT")
|
||||
|
||||
-- LSP
|
||||
key("n", "gd", "<Cmd>lua vim.lsp.buf.definition()<CR>", { silent = true })
|
||||
key("n", "gT", "<Cmd>lua vim.lsp.buf.type_definition()<CR>", { silent = true })
|
||||
key("n", "gi", "<Cmd>lua vim.lsp.buf.implementation()<CR>", { silent = true })
|
||||
key("n", "gh", "<Cmd>lua vim.lsp.buf.hover()<CR>", { silent = true })
|
||||
key("n", "gr", "<Cmd>Telescope lsp_references<CR>", { silent = true })
|
||||
key("n", "<Leader>R", "<Cmd>lua vim.lsp.buf.rename()<CR>", { silent = true })
|
||||
key("n", "]e", "<Cmd>lua vim.diagnostic.goto_next()<CR>", { silent = true })
|
||||
key("n", "[e", "<Cmd>lua vim.diagnostic.goto_prev()<CR>", { silent = true })
|
||||
key("n", "<Leader>e", "<Cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR>", { silent = true })
|
||||
key("n", "<Leader>E", "<Cmd>lua vim.lsp.buf.code_action()<CR>", { silent = true })
|
||||
|
||||
-- File commands
|
||||
key("n", "<Leader>q", ":quit<CR>")
|
||||
key("n", "<Leader>Q", ":quitall<CR>")
|
||||
key("n", "<Leader>fs", ":write<CR>")
|
||||
key("n", "<Leader>fd", ":lcd %:p:h<CR>", { silent = true })
|
||||
key("n", "<Leader>fu", ":lcd ..<CR>", { silent = true })
|
||||
key("n", "<Leader><Tab>", ":b#<CR>", { silent = true })
|
||||
key("n", "<Leader>gr", ":!gh repo view -w<CR><CR>", { silent = true })
|
||||
key("n", "<Leader>tt", [[<Cmd>exe 'edit $NOTES_PATH/journal/'.strftime("%Y-%m-%d_%a").'.md'<CR>]])
|
||||
key("n", "<Leader>jj", ":!journal<CR>:e<CR>")
|
||||
|
||||
-- Window commands
|
||||
key("n", "<Leader>wv", ":vsplit<CR>")
|
||||
key("n", "<Leader>wh", ":split<CR>")
|
||||
key("n", "<Leader>wm", ":only<CR>")
|
||||
|
||||
-- Tabularize
|
||||
key("", "<Leader>ta", ":Tabularize /")
|
||||
key("", "<Leader>t#", ":Tabularize /#<CR>")
|
||||
key("", "<Leader>tl", ":Tabularize /---<CR>")
|
||||
|
||||
-- Vimrc editing
|
||||
key("n", "<Leader>fv", ":edit $DOTS/nvim.configlink/init.lua<CR>")
|
||||
key("n", "<Leader>rr", ":luafile $MYVIMRC<CR>")
|
||||
key("n", "<Leader>rp", ":luafile $MYVIMRC<CR>:PackerInstall<CR>:")
|
||||
key("n", "<Leader>rc", ":luafile $MYVIMRC<CR>:PackerCompile<CR>")
|
||||
|
||||
-- Keep cursor in place
|
||||
key("n", "n", "nzz")
|
||||
key("n", "N", "Nzz")
|
||||
key("n", "J", "mzJ`z") --- Mark and jump back to it
|
||||
|
||||
-- Add undo breakpoints
|
||||
key("i", ",", ",<C-g>u")
|
||||
key("i", ".", ".<C-g>u")
|
||||
key("i", "!", "!<C-g>u")
|
||||
key("i", "?", "?<C-g>u")
|
||||
|
||||
-- Other
|
||||
key("t", "<A-CR>", "<C-\\><C-n>") --- Exit terminal mode
|
||||
key("n", "<A-CR>", ":noh<CR>", { silent = true }) --- Clear search in VimWiki
|
||||
key("n", "Y", "y$") --- Copy to end of line
|
||||
key("v", "<C-r>", "y<Esc>:%s/<C-r>+//gc<left><left><left>") --- Substitute selected
|
||||
key("v", "D", "y'>gp") --- Duplicate selected
|
65
modules/editor/neovim/lsp.lua
Normal file
65
modules/editor/neovim/lsp.lua
Normal file
@ -0,0 +1,65 @@
|
||||
-- =======================================================================
|
||||
-- Language Server
|
||||
-- =======================================================================
|
||||
|
||||
-- Language server engine
|
||||
use({
|
||||
"neovim/nvim-lspconfig",
|
||||
requires = { "hrsh7th/cmp-nvim-lsp" },
|
||||
config = function()
|
||||
local capabilities = require("cmp_nvim_lsp").update_capabilities(vim.lsp.protocol.make_client_capabilities())
|
||||
require("lspconfig").rust_analyzer.setup({ capabilities = capabilities })
|
||||
require("lspconfig").tflint.setup({ capabilities = capabilities })
|
||||
require("lspconfig").terraformls.setup({ capabilities = capabilities })
|
||||
require("lspconfig").pyright.setup({
|
||||
on_attach = function()
|
||||
-- set keymaps (requires 0.7.0)
|
||||
-- vim.keymap.set("n", "", "", {buffer=0})
|
||||
end,
|
||||
capabilities = capabilities,
|
||||
})
|
||||
end,
|
||||
})
|
||||
|
||||
-- Pretty highlights
|
||||
use("folke/lsp-colors.nvim")
|
||||
|
||||
-- Linting
|
||||
use({
|
||||
"jose-elias-alvarez/null-ls.nvim",
|
||||
branch = "main",
|
||||
requires = {
|
||||
"nvim-lua/plenary.nvim",
|
||||
"neovim/nvim-lspconfig",
|
||||
},
|
||||
config = function()
|
||||
require("null-ls").setup({
|
||||
sources = {
|
||||
require("null-ls").builtins.formatting.stylua,
|
||||
require("null-ls").builtins.formatting.black,
|
||||
require("null-ls").builtins.formatting.fish_indent,
|
||||
require("null-ls").builtins.formatting.nixfmt,
|
||||
require("null-ls").builtins.formatting.rustfmt,
|
||||
require("null-ls").builtins.diagnostics.shellcheck,
|
||||
require("null-ls").builtins.formatting.shfmt.with({
|
||||
extra_args = { "-i", "4", "-ci" },
|
||||
}),
|
||||
require("null-ls").builtins.formatting.terraform_fmt,
|
||||
-- require("null-ls").builtins.diagnostics.luacheck,
|
||||
-- require("null-ls").builtins.diagnostics.markdownlint,
|
||||
-- require("null-ls").builtins.diagnostics.pylint,
|
||||
},
|
||||
-- Format on save
|
||||
on_attach = function(client)
|
||||
if client.resolved_capabilities.document_formatting then
|
||||
vim.cmd([[
|
||||
augroup LspFormatting
|
||||
autocmd! * <buffer>
|
||||
autocmd BufWritePre <buffer> lua vim.lsp.buf.formatting_seq_sync()
|
||||
augroup END
|
||||
]])
|
||||
end
|
||||
end,
|
||||
})
|
||||
end,
|
||||
})
|
112
modules/editor/neovim/packer-basics.lua
Normal file
112
modules/editor/neovim/packer-basics.lua
Normal file
@ -0,0 +1,112 @@
|
||||
-- Maintain plugin manager
|
||||
use("wbthomason/packer.nvim")
|
||||
|
||||
-- Startup speed hacks
|
||||
use({
|
||||
"lewis6991/impatient.nvim",
|
||||
config = function()
|
||||
require("impatient")
|
||||
end,
|
||||
})
|
||||
|
||||
-- Important tweaks
|
||||
use("tpope/vim-surround") --- Manipulate parentheses
|
||||
|
||||
-- Convenience tweaks
|
||||
use("tpope/vim-eunuch") --- File manipulation in Vim
|
||||
use("tpope/vim-vinegar") --- Fixes netrw file explorer
|
||||
use("tpope/vim-fugitive") --- Git commands and syntax
|
||||
use("tpope/vim-repeat") --- Actually repeat using .
|
||||
use("christoomey/vim-tmux-navigator") --- Hotkeys for tmux panes
|
||||
|
||||
-- Use gc or gcc to add comments
|
||||
use({
|
||||
"numToStr/Comment.nvim",
|
||||
config = function()
|
||||
require("Comment").setup()
|
||||
end,
|
||||
})
|
||||
|
||||
-- Git next to line numbers
|
||||
use({
|
||||
"lewis6991/gitsigns.nvim",
|
||||
branch = "main",
|
||||
requires = { "nvim-lua/plenary.nvim" },
|
||||
config = function()
|
||||
require("gitsigns").setup()
|
||||
end,
|
||||
})
|
||||
|
||||
-- Status bar
|
||||
use({
|
||||
"hoob3rt/lualine.nvim",
|
||||
requires = { "kyazdani42/nvim-web-devicons", opt = true },
|
||||
config = function()
|
||||
require("lualine").setup({
|
||||
options = {
|
||||
theme = "gruvbox",
|
||||
icons_enabled = true,
|
||||
},
|
||||
})
|
||||
end,
|
||||
})
|
||||
|
||||
-- Improve speed and filetype detection
|
||||
use({
|
||||
"nathom/filetype.nvim",
|
||||
config = function()
|
||||
-- Filetype for .env files
|
||||
local envfiletype = function()
|
||||
vim.bo.filetype = "text"
|
||||
vim.bo.syntax = "sh"
|
||||
end
|
||||
-- Force filetype patterns that Vim doesn't know about
|
||||
require("filetype").setup({
|
||||
overrides = {
|
||||
extensions = {
|
||||
Brewfile = "brewfile",
|
||||
muttrc = "muttrc",
|
||||
tfvars = "terraform",
|
||||
tf = "terraform",
|
||||
},
|
||||
literal = {
|
||||
Caskfile = "brewfile",
|
||||
[".gitignore"] = "gitignore",
|
||||
config = "config",
|
||||
},
|
||||
complex = {
|
||||
[".*git/config"] = "gitconfig",
|
||||
["tmux.conf%..*link"] = "tmux",
|
||||
["gitconfig%..*link"] = "gitconfig",
|
||||
[".*ignore%..*link"] = "gitignore",
|
||||
[".*%.toml%..*link"] = "toml",
|
||||
},
|
||||
function_extensions = {},
|
||||
function_literal = {
|
||||
[".envrc"] = envfiletype,
|
||||
[".env"] = envfiletype,
|
||||
[".env.dev"] = envfiletype,
|
||||
[".env.prod"] = envfiletype,
|
||||
[".env.example"] = envfiletype,
|
||||
},
|
||||
},
|
||||
})
|
||||
end,
|
||||
})
|
||||
|
||||
-- Alignment tool
|
||||
use("godlygeek/tabular")
|
||||
|
||||
-- Markdown renderer / wiki notes
|
||||
use("vimwiki/vimwiki")
|
||||
|
||||
-- Markdown pretty view
|
||||
use("ellisonleao/glow.nvim")
|
||||
|
||||
-- Hex color previews
|
||||
use({
|
||||
"norcalli/nvim-colorizer.lua",
|
||||
config = function()
|
||||
require("colorizer").setup()
|
||||
end,
|
||||
})
|
6
modules/editor/neovim/packer-sync.lua
Normal file
6
modules/editor/neovim/packer-sync.lua
Normal file
@ -0,0 +1,6 @@
|
||||
-- =======================================================================
|
||||
|
||||
-- Install on initial bootstrap
|
||||
if packer_bootstrap then
|
||||
require("packer").sync()
|
||||
end
|
116
modules/editor/neovim/settings.lua
Normal file
116
modules/editor/neovim/settings.lua
Normal file
@ -0,0 +1,116 @@
|
||||
-- ===========================================================================
|
||||
-- Settings
|
||||
-- ===========================================================================
|
||||
|
||||
vim.o.termguicolors = true --- Set to truecolor
|
||||
vim.o.hidden = true --- Don't unload buffers when leaving them
|
||||
vim.wo.number = true --- Show line numbers
|
||||
vim.wo.relativenumber = true --- Relative numbers instead of absolute
|
||||
vim.o.list = true --- Reveal whitespace with dashes
|
||||
vim.o.expandtab = true --- Tabs into spaces
|
||||
vim.o.shiftwidth = 4 --- Amount to shift with > key
|
||||
vim.o.softtabstop = 4 --- Amount to shift with <TAB> key
|
||||
vim.o.ignorecase = true --- Ignore case when searching
|
||||
vim.o.smartcase = true --- Check case when using capitals in search
|
||||
vim.o.infercase = true --- Don't match cases when completing suggestions
|
||||
vim.o.incsearch = true --- Search while typing
|
||||
vim.o.visualbell = true --- No sounds
|
||||
vim.o.scrolljump = 1 --- Number of lines to scroll
|
||||
vim.o.scrolloff = 3 --- Margin of lines to see while scrolling
|
||||
vim.o.splitright = true --- Vertical splits on the right side
|
||||
vim.o.splitbelow = true --- Horizontal splits on the bottom side
|
||||
vim.o.pastetoggle = "<F3>" --- Use F3 to enter raw paste mode
|
||||
vim.o.clipboard = "unnamedplus" --- Uses system clipboard for yanking
|
||||
vim.o.updatetime = 300 --- Faster diagnostics
|
||||
vim.o.mouse = "nv" --- Mouse interaction / scrolling
|
||||
|
||||
-- Neovim features
|
||||
vim.o.inccommand = "split" --- Live preview search and replace
|
||||
--- Required for nvim-cmp completion
|
||||
vim.opt.completeopt = {
|
||||
"menu",
|
||||
"menuone",
|
||||
"noselect",
|
||||
}
|
||||
-- Required until 0.6.0: do not source the default filetype.vim
|
||||
vim.g.did_load_filetypes = 1
|
||||
|
||||
-- Remember last position when reopening file
|
||||
vim.api.nvim_exec(
|
||||
[[
|
||||
au BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$") | exe "normal! g`\"" | endif
|
||||
]],
|
||||
false
|
||||
)
|
||||
|
||||
-- Better backup, swap and undo storage
|
||||
vim.o.backup = true --- Easier to recover and more secure
|
||||
vim.bo.swapfile = false --- Instead of swaps, create backups
|
||||
vim.bo.undofile = true --- Keeps undos after quit
|
||||
|
||||
-- Create backup directories if they don't exist
|
||||
-- Should be fixed in 0.6 by https://github.com/neovim/neovim/pull/15433
|
||||
vim.o.backupdir = vim.fn.stdpath("cache") .. "/backup"
|
||||
vim.api.nvim_exec(
|
||||
[[
|
||||
if !isdirectory(&backupdir)
|
||||
call mkdir(&backupdir, "p")
|
||||
endif
|
||||
]],
|
||||
false
|
||||
)
|
||||
|
||||
-- LaTeX options
|
||||
vim.api.nvim_exec(
|
||||
[[
|
||||
au FileType tex inoremap ;bf \textbf{}<Esc>i
|
||||
au BufWritePost *.tex silent! execute "!pdflatex -output-directory=%:p:h % >/dev/null 2>&1" | redraw!
|
||||
]],
|
||||
false
|
||||
)
|
||||
|
||||
-- Highlight when yanking
|
||||
vim.api.nvim_exec(
|
||||
[[
|
||||
au TextYankPost * silent! lua vim.highlight.on_yank { timeout = 250 }
|
||||
]],
|
||||
false
|
||||
)
|
||||
|
||||
-- Netrw
|
||||
vim.g.netrw_liststyle = 3 -- Change style to 'tree' view
|
||||
vim.g.netrw_banner = 0 -- Remove useless banner
|
||||
vim.g.netrw_winsize = 15 -- Explore window takes % of page
|
||||
vim.g.netrw_browse_split = 4 -- Open in previous window
|
||||
vim.g.netrw_altv = 1 -- Always split left
|
||||
|
||||
-- VimWiki
|
||||
vim.g.vimwiki_list = {
|
||||
{
|
||||
["path"] = "$NOTES_PATH",
|
||||
["syntax"] = "markdown",
|
||||
["index"] = "home",
|
||||
["ext"] = ".md",
|
||||
},
|
||||
}
|
||||
vim.g.vimwiki_key_mappings = {
|
||||
["all_maps"] = 1,
|
||||
["mouse"] = 1,
|
||||
}
|
||||
vim.g.vimwiki_auto_chdir = 1 -- Set local dir to Wiki when open
|
||||
vim.g.vimwiki_create_link = 0 -- Don't automatically create new links
|
||||
vim.g.vimwiki_listsyms = " x" -- Set checkbox symbol progression
|
||||
vim.g.vimwiki_table_mappings = 0 -- VimWiki table keybinds interfere with tab completion
|
||||
vim.api.nvim_exec(
|
||||
[[
|
||||
au FileType markdown inoremap ;tt <Esc>:AddTag<CR>
|
||||
|
||||
function! PInsert(item)
|
||||
let @z=a:item
|
||||
norm "zpx
|
||||
endfunction
|
||||
|
||||
command! AddTag call fzf#run({'source': 'rg "#[A-Za-z/]+[ |\$]" -o --no-filename --no-line-number | sort | uniq', 'sink': function('PInsert')})
|
||||
]],
|
||||
false
|
||||
)
|
31
modules/editor/neovim/syntax.lua
Normal file
31
modules/editor/neovim/syntax.lua
Normal file
@ -0,0 +1,31 @@
|
||||
-- =======================================================================
|
||||
-- Syntax
|
||||
-- =======================================================================
|
||||
|
||||
-- Syntax engine
|
||||
use({
|
||||
"nvim-treesitter/nvim-treesitter",
|
||||
run = ":TSUpdate",
|
||||
config = function()
|
||||
require("nvim-treesitter.configs").setup({
|
||||
ensure_installed = {
|
||||
"hcl",
|
||||
"python",
|
||||
"lua",
|
||||
"nix",
|
||||
"fish",
|
||||
"toml",
|
||||
"yaml",
|
||||
"json",
|
||||
},
|
||||
highlight = { enable = true },
|
||||
indent = { enable = true },
|
||||
})
|
||||
end,
|
||||
})
|
||||
|
||||
-- Additional syntax sources
|
||||
use("bfontaine/Brewfile.vim") --- Brewfile syntax
|
||||
use("chr4/nginx.vim") --- Nginx syntax
|
||||
use("towolf/vim-helm") --- Helm syntax
|
||||
use("rodjek/vim-puppet") --- Puppet syntax
|
67
modules/editor/neovim/telescope.lua
Normal file
67
modules/editor/neovim/telescope.lua
Normal file
@ -0,0 +1,67 @@
|
||||
-- =======================================================================
|
||||
-- Fuzzy Launcher
|
||||
-- =======================================================================
|
||||
|
||||
use({
|
||||
"nvim-telescope/telescope.nvim",
|
||||
branch = "master",
|
||||
requires = { "nvim-lua/plenary.nvim" },
|
||||
config = function()
|
||||
-- Telescope: quit instantly with escape
|
||||
local actions = require("telescope.actions")
|
||||
require("telescope").setup({
|
||||
defaults = {
|
||||
mappings = {
|
||||
i = {
|
||||
["<esc>"] = actions.close,
|
||||
["<C-h>"] = "which_key",
|
||||
},
|
||||
},
|
||||
},
|
||||
pickers = {
|
||||
find_files = { theme = "ivy" },
|
||||
oldfiles = { theme = "ivy" },
|
||||
buffers = { theme = "dropdown" },
|
||||
},
|
||||
extensions = {
|
||||
fzy_native = {},
|
||||
tmux = {},
|
||||
zoxide = {},
|
||||
--neoclip = {},
|
||||
project = {
|
||||
base_dirs = { "~/dev" },
|
||||
},
|
||||
},
|
||||
})
|
||||
end,
|
||||
})
|
||||
|
||||
-- Faster sorting
|
||||
use("nvim-telescope/telescope-fzy-native.nvim")
|
||||
|
||||
-- Jump around tmux sessions
|
||||
use("camgraff/telescope-tmux.nvim")
|
||||
|
||||
-- Jump directories
|
||||
use({
|
||||
"jvgrootveld/telescope-zoxide",
|
||||
requires = { "nvim-lua/popup.nvim" },
|
||||
})
|
||||
|
||||
-- Jump projects
|
||||
use({
|
||||
"nvim-telescope/telescope-project.nvim",
|
||||
requires = { "nvim-telescope/telescope.nvim" },
|
||||
config = function()
|
||||
require("telescope").load_extension("project")
|
||||
end,
|
||||
})
|
||||
|
||||
-- File browser
|
||||
use({
|
||||
"nvim-telescope/telescope-file-browser.nvim",
|
||||
requires = { "nvim-telescope/telescope.nvim" },
|
||||
config = function()
|
||||
require("telescope").load_extension("file_browser")
|
||||
end,
|
||||
})
|
11
modules/editor/notes.nix
Normal file
11
modules/editor/notes.nix
Normal file
@ -0,0 +1,11 @@
|
||||
{ config, ... }: {
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
home.sessionVariables = {
|
||||
NOTES_PATH = "${config.homePath}/dev/personal/notes";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
{ config, ... }: {
|
||||
|
||||
imports = [ ./leagueoflegends.nix ./lutris.nix ./steam.nix ./legendary.nix ];
|
||||
|
||||
config = {
|
||||
hardware.opengl = {
|
||||
enable = true;
|
@ -1,14 +1,30 @@
|
||||
{ config, pkgs, ... }:
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
{
|
||||
imports = [ ./common.nix ./lutris.nix ];
|
||||
options.gaming.leagueoflegends = lib.mkEnableOption "League of Legends";
|
||||
|
||||
config = {
|
||||
config = lib.mkIf config.gaming.leagueoflegends {
|
||||
|
||||
# League of Legends anti-cheat
|
||||
# League of Legends anti-cheat requirement
|
||||
boot.kernel.sysctl = { "abi.vsyscall32" = 0; };
|
||||
|
||||
environment.systemPackages = with pkgs; [ openssl dconf ];
|
||||
environment.systemPackages = with pkgs; [
|
||||
|
||||
# Lutris requirement to install the game
|
||||
lutris
|
||||
amdvlk
|
||||
wineWowPackages.stable
|
||||
# vulkan-tools
|
||||
|
||||
# Required according to https://lutris.net/games/league-of-legends/
|
||||
openssl
|
||||
gnome.zenity
|
||||
|
||||
# Don't remember if this is required
|
||||
dconf
|
||||
|
||||
];
|
||||
|
||||
environment.sessionVariables = { QT_X11_NO_MITSHM = "1"; };
|
||||
|
||||
};
|
||||
}
|
||||
|
56
modules/gaming/legendary.nix
Normal file
56
modules/gaming/legendary.nix
Normal file
@ -0,0 +1,56 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let home-packages = config.home-manager.users.${config.user}.home.packages;
|
||||
|
||||
in {
|
||||
|
||||
options.gaming.legendary =
|
||||
lib.mkEnableOption "Legendary - Epic Games Launcher";
|
||||
|
||||
config = lib.mkIf config.gaming.legendary {
|
||||
environment.systemPackages = with pkgs; [
|
||||
legendary-gl
|
||||
rare # GUI for Legendary (not working)
|
||||
wineWowPackages.stable # 32-bit and 64-bit wineWowPackages, see https://nixos.wiki/wiki/Wine
|
||||
];
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
xdg.configFile."legendary/config.ini".text = ''
|
||||
[Legendary]
|
||||
; Disables the automatic update check
|
||||
disable_update_check = false
|
||||
; Disables the notice about an available update on exit
|
||||
disable_update_notice = true
|
||||
; Set install directory
|
||||
install_dir = ${config.homePath}/media/games
|
||||
; Make output quiet
|
||||
log_level = error
|
||||
'';
|
||||
|
||||
home.file = let
|
||||
ignorePatterns = ''
|
||||
.wine/
|
||||
drive_c/'';
|
||||
in {
|
||||
".rgignore".text = ignorePatterns;
|
||||
".fdignore".text = ignorePatterns;
|
||||
};
|
||||
|
||||
programs.fish.functions =
|
||||
lib.mkIf (builtins.elem pkgs.fzf home-packages) {
|
||||
epic-games = {
|
||||
body = ''
|
||||
set game (legendary list 2>/dev/null \
|
||||
| awk '/^ \* / { print $0; }' \
|
||||
| sed -e 's/ (.*)$//' -e 's/ \* //' \
|
||||
| fzf)
|
||||
and legendary launch "$game" &> /dev/null
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
}
|
@ -1,9 +1,13 @@
|
||||
{ config, pkgs, ... }:
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
{
|
||||
options.gaming.lutris = lib.mkEnableOption "Lutris";
|
||||
|
||||
imports = [ ./common.nix ];
|
||||
|
||||
config = { environment.systemPackages = with pkgs; [ lutris amdvlk wine ]; };
|
||||
config = lib.mkIf config.gaming.lutris {
|
||||
environment.systemPackages = with pkgs; [
|
||||
lutris
|
||||
amdvlk # Vulkan drivers (probably already installed)
|
||||
wineWowPackages.stable # 32-bit and 64-bit wineWowPackages
|
||||
];
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,10 +1,19 @@
|
||||
{ config, pkgs, ... }: {
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
imports = [ ./common.nix ];
|
||||
options.gaming.steam = lib.mkEnableOption "Steam";
|
||||
|
||||
config = {
|
||||
config = lib.mkIf config.gaming.steam {
|
||||
hardware.steam-hardware.enable = true;
|
||||
environment.systemPackages = with pkgs; [ steam ];
|
||||
unfreePackages = [ "steam" "steam-original" "steamcmd" ];
|
||||
environment.systemPackages = with pkgs; [
|
||||
|
||||
steam
|
||||
|
||||
# Enable terminal interaction
|
||||
steamPackages.steamcmd
|
||||
steam-tui
|
||||
|
||||
];
|
||||
};
|
||||
|
||||
}
|
||||
|
55
modules/graphical/default.nix
Normal file
55
modules/graphical/default.nix
Normal file
@ -0,0 +1,55 @@
|
||||
{ lib, ... }: {
|
||||
|
||||
imports = [
|
||||
./xorg.nix
|
||||
./fonts.nix
|
||||
./i3.nix
|
||||
./polybar.nix
|
||||
./picom.nix
|
||||
# ./dmenu.nix
|
||||
./rofi.nix
|
||||
];
|
||||
|
||||
options = with lib; {
|
||||
|
||||
gui = {
|
||||
compositor.enable = mkEnableOption {
|
||||
description = "Enable transparency, blur, shadows";
|
||||
default = false;
|
||||
};
|
||||
launcherCommand = mkOption {
|
||||
type = types.str;
|
||||
description = "Command to use for launching";
|
||||
};
|
||||
systemdSearch = mkOption {
|
||||
type = types.str;
|
||||
description = "Command to use for interacting with systemd";
|
||||
};
|
||||
altTabCommand = mkOption {
|
||||
type = types.str;
|
||||
description = "Command to use for choosing windows";
|
||||
};
|
||||
toggleBarCommand = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Command to hide and show the status bar.";
|
||||
};
|
||||
gtk.theme = {
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
description = "Theme name for GTK applications";
|
||||
};
|
||||
package = mkOption {
|
||||
type = types.str;
|
||||
description = "Theme package name for GTK applications";
|
||||
default = "gnome-themes-extra";
|
||||
};
|
||||
};
|
||||
wallpaper = mkOption {
|
||||
type = types.path;
|
||||
description = "Wallpaper background image file";
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
12
modules/graphical/dmenu.nix
Normal file
12
modules/graphical/dmenu.nix
Normal file
@ -0,0 +1,12 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
|
||||
config = lib.mkIf config.services.xserver.enable {
|
||||
|
||||
home-manager.users.${config.user}.home.packages = [ pkgs.dmenu ];
|
||||
gui.launcherCommand = "${pkgs.dmenu}/bin/dmenu_run";
|
||||
|
||||
};
|
||||
|
||||
}
|
28
modules/graphical/fonts.nix
Normal file
28
modules/graphical/fonts.nix
Normal file
@ -0,0 +1,28 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let fontName = "Victor Mono";
|
||||
|
||||
in {
|
||||
|
||||
config = lib.mkIf config.gui.enable {
|
||||
|
||||
fonts.fonts = with pkgs; [
|
||||
victor-mono # Used for Vim and Terminal
|
||||
(nerdfonts.override { fonts = [ "Hack" ]; }) # For Polybar, Rofi
|
||||
];
|
||||
fonts.fontconfig.defaultFonts.monospace = [ fontName ];
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
xsession.windowManager.i3.config.fonts = {
|
||||
names = [ "pango:${fontName}" ];
|
||||
# style = "Regular";
|
||||
# size = 11.0;
|
||||
};
|
||||
services.polybar.config."bar/main".font-0 = "Hack Nerd Font:size=10;2";
|
||||
programs.rofi.font = "Hack Nerd Font 14";
|
||||
programs.alacritty.settings.font.normal.family = fontName;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
276
modules/graphical/i3.nix
Normal file
276
modules/graphical/i3.nix
Normal file
@ -0,0 +1,276 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
|
||||
lockCmd =
|
||||
"${pkgs.betterlockscreen}/bin/betterlockscreen --lock --display 1 --blur 0.5 --span";
|
||||
lockUpdate =
|
||||
"${pkgs.betterlockscreen}/bin/betterlockscreen --update ${config.gui.wallpaper} --display 1 --span";
|
||||
|
||||
in {
|
||||
|
||||
config = lib.mkIf config.services.xserver.enable {
|
||||
|
||||
services.xserver.windowManager = {
|
||||
i3 = {
|
||||
enable = true;
|
||||
package = pkgs.i3-gaps;
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
feh # Wallpaper
|
||||
playerctl # Media control
|
||||
];
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
xsession.windowManager.i3 = {
|
||||
enable = true;
|
||||
package = pkgs.i3-gaps;
|
||||
config = let
|
||||
modifier = "Mod4"; # Super key
|
||||
ws1 = "1:I";
|
||||
ws2 = "2:II";
|
||||
ws3 = "3:III";
|
||||
ws4 = "4:IV";
|
||||
ws5 = "5:V";
|
||||
ws6 = "6:VI";
|
||||
ws7 = "7:VII";
|
||||
ws8 = "8:VIII";
|
||||
ws9 = "9:IX";
|
||||
ws10 = "10:X";
|
||||
in {
|
||||
modifier = modifier;
|
||||
assigns = {
|
||||
"${ws1}" = [{ class = "Firefox"; }];
|
||||
"${ws2}" = [{ class = "Alacritty"; }];
|
||||
"${ws3}" = [{ class = "discord"; }];
|
||||
"${ws4}" = [{ class = "Steam"; }];
|
||||
};
|
||||
bars = [{ command = "echo"; }]; # Disable i3bar
|
||||
colors = let
|
||||
background = config.gui.colorscheme.base00;
|
||||
inactiveBackground = config.gui.colorscheme.base01;
|
||||
border = config.gui.colorscheme.base01;
|
||||
inactiveBorder = config.gui.colorscheme.base01;
|
||||
text = config.gui.colorscheme.base07;
|
||||
inactiveText = config.gui.colorscheme.base04;
|
||||
urgentBackground = config.gui.colorscheme.base08;
|
||||
indicator = "#00000000";
|
||||
in {
|
||||
background = config.gui.colorscheme.base00;
|
||||
focused = {
|
||||
inherit background indicator text border;
|
||||
childBorder = background;
|
||||
};
|
||||
focusedInactive = {
|
||||
inherit indicator;
|
||||
background = inactiveBackground;
|
||||
border = inactiveBorder;
|
||||
childBorder = inactiveBackground;
|
||||
text = inactiveText;
|
||||
};
|
||||
# placeholder = { };
|
||||
unfocused = {
|
||||
inherit indicator;
|
||||
background = inactiveBackground;
|
||||
border = inactiveBorder;
|
||||
childBorder = inactiveBackground;
|
||||
text = inactiveText;
|
||||
};
|
||||
urgent = {
|
||||
inherit text indicator;
|
||||
background = urgentBackground;
|
||||
border = urgentBackground;
|
||||
childBorder = urgentBackground;
|
||||
};
|
||||
};
|
||||
floating.modifier = modifier;
|
||||
focus = {
|
||||
mouseWarping = true;
|
||||
newWindow = "urgent";
|
||||
followMouse = false;
|
||||
};
|
||||
keybindings = {
|
||||
|
||||
# Adjust screen brightness
|
||||
"Shift+F12" =
|
||||
"exec ${pkgs.ddcutil}/bin/ddcutil --display 1 setvcp 10 + 30 && sleep 1; exec ${pkgs.ddcutil}/bin/ddcutil --display 2 setvcp 10 + 30";
|
||||
"Shift+F11" =
|
||||
"exec ${pkgs.ddcutil}/bin/ddcutil --display 1 setvcp 10 - 30 && sleep 1; exec ${pkgs.ddcutil}/bin/ddcutil --display 2 setvcp 10 - 30";
|
||||
"XF86MonBrightnessUp" =
|
||||
"exec ${pkgs.ddcutil}/bin/ddcutil --display 1 setvcp 10 + 30 && sleep 1; exec ${pkgs.ddcutil}/bin/ddcutil --display 2 setvcp 10 + 30";
|
||||
"XF86MonBrightnessDown" =
|
||||
"exec ${pkgs.ddcutil}/bin/ddcutil --display 1 setvcp 10 - 30 && sleep 1; exec ${pkgs.ddcutil}/bin/ddcutil --display 2 setvcp 10 - 30";
|
||||
|
||||
# Media player controls
|
||||
"XF86AudioPlay" = "exec ${pkgs.playerctl}/bin/playerctl play-pause";
|
||||
"XF86AudioStop" = "exec ${pkgs.playerctl}/bin/playerctl stop";
|
||||
"XF86AudioNext" = "exec ${pkgs.playerctl}/bin/playerctl next";
|
||||
"XF86AudioPrev" = "exec ${pkgs.playerctl}/bin/playerctl previous";
|
||||
|
||||
# Launchers
|
||||
"${modifier}+Return" =
|
||||
"exec --no-startup-id alacritty; workspace ${ws2}; layout tabbed";
|
||||
"${modifier}+space" =
|
||||
"exec --no-startup-id ${config.gui.launcherCommand}";
|
||||
"${modifier}+Shift+s" =
|
||||
"exec --no-startup-id ${config.gui.systemdSearch}";
|
||||
"Mod1+Tab" = "exec --no-startup-id ${config.gui.altTabCommand}";
|
||||
"${modifier}+Shift+c" = "reload";
|
||||
"${modifier}+Shift+r" = "restart";
|
||||
"${modifier}+Shift+q" = ''
|
||||
exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -B 'Yes, exit i3' 'i3-msg exit'"'';
|
||||
"${modifier}+Shift+x" = "exec ${lockCmd}";
|
||||
|
||||
# Window options
|
||||
"${modifier}+q" = "kill";
|
||||
"${modifier}+b" = "exec ${config.gui.toggleBarCommand}";
|
||||
"${modifier}+f" = "fullscreen toggle";
|
||||
"${modifier}+h" = "focus left";
|
||||
"${modifier}+j" = "focus down";
|
||||
"${modifier}+k" = "focus up";
|
||||
"${modifier}+l" = "focus right";
|
||||
"${modifier}+Left" = "focus left";
|
||||
"${modifier}+Down" = "focus down";
|
||||
"${modifier}+Up" = "focus up";
|
||||
"${modifier}+Right" = "focus right";
|
||||
"${modifier}+Shift+h" = "move left";
|
||||
"${modifier}+Shift+j" = "move down";
|
||||
"${modifier}+Shift+k" = "move up";
|
||||
"${modifier}+Shift+l" = "move right";
|
||||
"${modifier}+Shift+Left" = "move left";
|
||||
"${modifier}+Shift+Down" = "move down";
|
||||
"${modifier}+Shift+Up" = "move up";
|
||||
"${modifier}+Shift+Right" = "move right";
|
||||
|
||||
# Tiling
|
||||
"${modifier}+i" = "split h";
|
||||
"${modifier}+v" = "split v";
|
||||
"${modifier}+s" = "layout stacking";
|
||||
"${modifier}+t" = "layout tabbed";
|
||||
"${modifier}+e" = "layout toggle split";
|
||||
"${modifier}+Shift+space" = "floating toggle";
|
||||
"${modifier}+Control+space" = "focus mode_toggle";
|
||||
"${modifier}+a" = "focus parent";
|
||||
|
||||
# Workspaces
|
||||
"${modifier}+1" = "workspace ${ws1}";
|
||||
"${modifier}+2" = "workspace ${ws2}";
|
||||
"${modifier}+3" = "workspace ${ws3}";
|
||||
"${modifier}+4" = "workspace ${ws4}";
|
||||
"${modifier}+5" = "workspace ${ws5}";
|
||||
"${modifier}+6" = "workspace ${ws6}";
|
||||
"${modifier}+7" = "workspace ${ws7}";
|
||||
"${modifier}+8" = "workspace ${ws8}";
|
||||
"${modifier}+9" = "workspace ${ws9}";
|
||||
"${modifier}+0" = "workspace ${ws10}";
|
||||
|
||||
# Move windows
|
||||
"${modifier}+Shift+1" =
|
||||
"move container to workspace ${ws1}; workspace ${ws1}";
|
||||
"${modifier}+Shift+2" =
|
||||
"move container to workspace ${ws2}; workspace ${ws2}";
|
||||
"${modifier}+Shift+3" =
|
||||
"move container to workspace ${ws3}; workspace ${ws3}";
|
||||
"${modifier}+Shift+4" =
|
||||
"move container to workspace ${ws4}; workspace ${ws4}";
|
||||
"${modifier}+Shift+5" =
|
||||
"move container to workspace ${ws5}; workspace ${ws5}";
|
||||
"${modifier}+Shift+6" =
|
||||
"move container to workspace ${ws6}; workspace ${ws6}";
|
||||
"${modifier}+Shift+7" =
|
||||
"move container to workspace ${ws7}; workspace ${ws7}";
|
||||
"${modifier}+Shift+8" =
|
||||
"move container to workspace ${ws8}; workspace ${ws8}";
|
||||
"${modifier}+Shift+9" =
|
||||
"move container to workspace ${ws9}; workspace ${ws9}";
|
||||
"${modifier}+Shift+0" =
|
||||
"move container to workspace ${ws10}; workspace ${ws10}";
|
||||
|
||||
# Move screens
|
||||
"${modifier}+Control+l" = "move workspace to output right";
|
||||
"${modifier}+Control+h" = "move workspace to output left";
|
||||
|
||||
# Resizing
|
||||
"${modifier}+r" = ''mode "resize"'';
|
||||
"${modifier}+Control+Shift+h" =
|
||||
"resize shrink width 10 px or 10 ppt";
|
||||
"${modifier}+Control+Shift+j" =
|
||||
"resize grow height 10 px or 10 ppt";
|
||||
"${modifier}+Control+Shift+k" =
|
||||
"resize shrink height 10 px or 10 ppt";
|
||||
"${modifier}+Control+Shift+l" = "resize grow width 10 px or 10 ppt";
|
||||
};
|
||||
modes = { };
|
||||
startup = [
|
||||
{
|
||||
command = "feh --bg-fill ${config.gui.wallpaper}";
|
||||
always = true;
|
||||
notification = false;
|
||||
}
|
||||
{
|
||||
command = "i3-msg workspace ${ws1}";
|
||||
notification = false;
|
||||
}
|
||||
];
|
||||
window = {
|
||||
border = 0;
|
||||
hideEdgeBorders = "smart";
|
||||
titlebar = false;
|
||||
};
|
||||
workspaceAutoBackAndForth = false;
|
||||
workspaceOutputAssign = [ ];
|
||||
# gaps = {
|
||||
# bottom = 8;
|
||||
# top = 8;
|
||||
# left = 8;
|
||||
# right = 8;
|
||||
# horizontal = 15;
|
||||
# vertical = 15;
|
||||
# inner = 15;
|
||||
# outer = 0;
|
||||
# smartBorders = "off";
|
||||
# smartGaps = false;
|
||||
# };
|
||||
};
|
||||
extraConfig = "";
|
||||
};
|
||||
|
||||
programs.fish.functions = {
|
||||
update-lock-screen = {
|
||||
description = "Update lockscreen with wallpaper";
|
||||
body = lockUpdate;
|
||||
};
|
||||
};
|
||||
|
||||
# Update lock screen cache only if cache is empty
|
||||
home.activation.updateLockScreenCache =
|
||||
let cacheDir = "${config.homePath}/.cache/betterlockscreen/current";
|
||||
in config.home-manager.users.${config.user}.lib.dag.entryAfter
|
||||
[ "writeBoundary" ] ''
|
||||
if [ ! -d ${cacheDir} ] || [ -z "$(ls ${cacheDir})" ]; then
|
||||
$DRY_RUN_CMD ${lockUpdate}
|
||||
fi
|
||||
'';
|
||||
|
||||
};
|
||||
|
||||
# Ref: https://github.com/betterlockscreen/betterlockscreen/blob/next/system/betterlockscreen%40.service
|
||||
systemd.services.lock = {
|
||||
description = "Lock the screen on resume from suspend";
|
||||
before = [ "sleep.target" "suspend.target" ];
|
||||
serviceConfig = {
|
||||
User = config.user;
|
||||
Type = "simple";
|
||||
Environment = "DISPLAY=:0";
|
||||
TimeoutSec = "infinity";
|
||||
ExecStart = lockCmd;
|
||||
ExecStartPost = "${pkgs.coreutils-full}/bin/sleep 1";
|
||||
};
|
||||
wantedBy = [ "sleep.target" "suspend.target" ];
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
49
modules/graphical/picom.nix
Normal file
49
modules/graphical/picom.nix
Normal file
@ -0,0 +1,49 @@
|
||||
{ config, lib, ... }: {
|
||||
|
||||
config =
|
||||
lib.mkIf (config.services.xserver.enable && config.gui.compositor.enable) {
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
services.picom = {
|
||||
enable = true;
|
||||
blur = false;
|
||||
blurExclude = [ ];
|
||||
# extraOptions = ''
|
||||
# shadow-radius = 20
|
||||
# '';
|
||||
# extraOptions = ''
|
||||
# shadow-radius = 20
|
||||
# corner-radius = 10
|
||||
# blur-size = 20
|
||||
# rounded-corners-exclude = [
|
||||
# "window_type = 'dock'",
|
||||
# "class_g = 'i3-frame'"
|
||||
# ]
|
||||
# '';
|
||||
fade = false;
|
||||
experimentalBackends = true;
|
||||
inactiveDim = "0.05";
|
||||
inactiveOpacity = "1.0";
|
||||
menuOpacity = "1.0";
|
||||
noDNDShadow = false;
|
||||
noDockShadow = false;
|
||||
opacityRule = [
|
||||
"0:_NET_WM_STATE@[0]:32a = '_NET_WM_STATE_HIDDEN'" # Hide tabbed windows
|
||||
];
|
||||
shadow = false;
|
||||
shadowExclude = [ ];
|
||||
shadowOffsets = [ (-10) (-10) ];
|
||||
shadowOpacity = "0.5";
|
||||
vSync = true;
|
||||
};
|
||||
|
||||
xsession.windowManager.i3.config.startup = [{
|
||||
command = "systemctl --user restart picom";
|
||||
always = true;
|
||||
notification = false;
|
||||
}];
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
}
|
185
modules/graphical/polybar.nix
Normal file
185
modules/graphical/polybar.nix
Normal file
@ -0,0 +1,185 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
config = lib.mkIf config.services.xserver.enable {
|
||||
|
||||
gui.toggleBarCommand = "polybar-msg cmd toggle";
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
services.polybar = {
|
||||
enable = true;
|
||||
package = pkgs.polybar.override {
|
||||
i3GapsSupport = true;
|
||||
pulseSupport = true;
|
||||
githubSupport = true;
|
||||
};
|
||||
script = "polybar &";
|
||||
config = {
|
||||
"bar/main" = {
|
||||
bottom = false;
|
||||
width = "100%";
|
||||
height = "22pt";
|
||||
radius = 0;
|
||||
# offset-y = -5;
|
||||
# offset-y = "5%";
|
||||
# dpi = 96;
|
||||
background = config.gui.colorscheme.base01;
|
||||
foreground = config.gui.colorscheme.base05;
|
||||
line-size = "3pt";
|
||||
border-top-size = 0;
|
||||
border-right-size = 0;
|
||||
border-left-size = 0;
|
||||
border-bottom-size = "4pt";
|
||||
border-color = config.gui.colorscheme.base00;
|
||||
padding-left = 2;
|
||||
padding-right = 2;
|
||||
module-margin = 1;
|
||||
modules-left = "i3";
|
||||
modules-center = "xwindow";
|
||||
modules-right = "pulseaudio date";
|
||||
cursor-click = "pointer";
|
||||
cursor-scroll = "ns-resize";
|
||||
enable-ipc = true;
|
||||
tray-position = "right";
|
||||
# wm-restack = "generic";
|
||||
# wm-restack = "bspwm";
|
||||
# wm-restack = "i3";
|
||||
# override-redirect = true;
|
||||
};
|
||||
"module/i3" = let padding = 2;
|
||||
in {
|
||||
type = "internal/i3";
|
||||
pin-workspaces = false;
|
||||
show-urgent = true;
|
||||
strip-wsnumbers = true;
|
||||
index-sort = true;
|
||||
enable-click = true;
|
||||
wrapping-scroll = true;
|
||||
fuzzy-match = true;
|
||||
format = "<label-state> <label-mode>";
|
||||
label-focused = "%name%";
|
||||
label-focused-foreground = config.gui.colorscheme.base01;
|
||||
label-focused-background = config.gui.colorscheme.base05;
|
||||
label-focused-underline = config.gui.colorscheme.base03;
|
||||
label-focused-padding = padding;
|
||||
label-unfocused = "%name%";
|
||||
label-unfocused-padding = padding;
|
||||
label-visible = "%name%";
|
||||
label-visible-underline = config.gui.colorscheme.base01;
|
||||
label-visible-padding = padding;
|
||||
label-urgent = "%name%";
|
||||
label-urgent-foreground = config.gui.colorscheme.base00;
|
||||
label-urgent-background = config.gui.colorscheme.base08;
|
||||
label-urgent-underline = config.gui.colorscheme.base0F;
|
||||
label-urgent-padding = padding;
|
||||
};
|
||||
"module/xworkspaces" = {
|
||||
type = "internal/xworkspaces";
|
||||
label-active = "%name%";
|
||||
label-active-background = config.gui.colorscheme.base05;
|
||||
label-active-foreground = config.gui.colorscheme.base01;
|
||||
label-active-underline = config.gui.colorscheme.base03;
|
||||
label-active-padding = 1;
|
||||
label-occupied = "%name%";
|
||||
label-occupied-padding = 1;
|
||||
label-urgent = "%name%";
|
||||
label-urgent-background = config.gui.colorscheme.base08;
|
||||
label-urgent-padding = 1;
|
||||
label-empty = "%name%";
|
||||
label-empty-foreground = config.gui.colorscheme.base06;
|
||||
label-empty-padding = 1;
|
||||
};
|
||||
"module/xwindow" = {
|
||||
type = "internal/xwindow";
|
||||
label = "%title:0:60:...%";
|
||||
};
|
||||
# "module/filesystem" = {
|
||||
# type = "internal/fs";
|
||||
# interval = 25;
|
||||
# mount-0 = "/";
|
||||
# label-mounted = "%{F#F0C674}%mountpoint%%{F-} %percentage_used%%";
|
||||
# label-unmounted = "%mountpoint% not mounted";
|
||||
# label-unmounted-foreground = colors.disabled;
|
||||
# };
|
||||
"module/pulseaudio" = {
|
||||
type = "internal/pulseaudio";
|
||||
# format-volume-prefix = "VOL ";
|
||||
# format-volume-prefix-foreground = colors.primary;
|
||||
format-volume = "<ramp-volume> <label-volume>";
|
||||
# format-volume-background = colors.background;
|
||||
# label-volume-background = colors.background;
|
||||
format-volume-foreground = config.gui.colorscheme.base0B;
|
||||
label-volume = "%percentage%%";
|
||||
label-muted = "ﱝ ---";
|
||||
label-muted-foreground = config.gui.colorscheme.base03;
|
||||
ramp-volume-0 = "";
|
||||
ramp-volume-1 = "墳";
|
||||
ramp-volume-2 = "";
|
||||
};
|
||||
# "module/xkeyboard" = {
|
||||
# type = "internal/xkeyboard";
|
||||
# blacklist-0 = "num lock";
|
||||
# label-layout = "%layout%";
|
||||
# label-layout-foreground = colors.primary;
|
||||
# label-indicator-padding = 2;
|
||||
# label-indicator-margin = 1;
|
||||
# label-indicator-foreground = colors.background;
|
||||
# label-indicator-background = colors.secondary;
|
||||
# };
|
||||
# "module/memory" = {
|
||||
# type = "internal/memory";
|
||||
# interval = 2;
|
||||
# format-prefix = "RAM ";
|
||||
# format-prefix-foreground = colors.primary;
|
||||
# label = "%percentage_used:2%%";
|
||||
# };
|
||||
# "module/cpu" = {
|
||||
# type = "internal/cpu";
|
||||
# interval = 2;
|
||||
# format-prefix = "CPU ";
|
||||
# format-prefix-foreground = colors.primary;
|
||||
# label = "%percentage:2%%";
|
||||
# };
|
||||
# "network-base" = {
|
||||
# type = "internal/network";
|
||||
# interval = 5;
|
||||
# format-connected = "<label-connected>";
|
||||
# format-disconnected = "<label-disconnected>";
|
||||
# label-disconnected = "%{F#F0C674}%ifname%%{F#707880} disconnected";
|
||||
# };
|
||||
# "module/wlan" = {
|
||||
# "inherit" = "network-base";
|
||||
# interface-type = "wireless";
|
||||
# label-connected = "%{F#F0C674}%ifname%%{F-} %essid% %local_ip%";
|
||||
# };
|
||||
# "module/eth" = {
|
||||
# "inherit" = "network-base";
|
||||
# interface-type = "wired";
|
||||
# label-connected = "%{F#F0C674}%ifname%%{F-} %local_ip%";
|
||||
# };
|
||||
"module/date" = {
|
||||
type = "internal/date";
|
||||
interval = 1;
|
||||
date = "%d %b %l:%M %p";
|
||||
date-alt = "%Y-%m-%d %H:%M:%S";
|
||||
label = "%date%";
|
||||
label-foreground = config.gui.colorscheme.base0A;
|
||||
# format-background = colors.background;
|
||||
};
|
||||
"settings" = {
|
||||
screenchange-reload = true;
|
||||
pseudo-transparency = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
xsession.windowManager.i3.config.startup = [{
|
||||
command = "systemctl --user restart polybar";
|
||||
always = true;
|
||||
notification = false;
|
||||
}];
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
}
|
153
modules/graphical/rofi.nix
Normal file
153
modules/graphical/rofi.nix
Normal file
@ -0,0 +1,153 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
|
||||
config = lib.mkIf config.services.xserver.enable {
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
home.packages = with pkgs;
|
||||
[
|
||||
jq # Required for rofi-systemd
|
||||
];
|
||||
|
||||
programs.rofi = {
|
||||
enable = true;
|
||||
cycle = true;
|
||||
location = "center";
|
||||
pass = { };
|
||||
plugins = [ pkgs.rofi-calc pkgs.rofi-emoji pkgs.rofi-systemd ];
|
||||
theme = let
|
||||
inherit (config.home-manager.users.${config.user}.lib.formats.rasi)
|
||||
mkLiteral;
|
||||
in {
|
||||
|
||||
# Inspired by https://github.com/sherubthakur/dotfiles/blob/master/users/modules/desktop-environment/rofi/launcher.rasi
|
||||
|
||||
"*" = {
|
||||
background-color = mkLiteral config.gui.colorscheme.base00;
|
||||
foreground-color = mkLiteral config.gui.colorscheme.base07;
|
||||
text-color = mkLiteral config.gui.colorscheme.base07;
|
||||
border-color = mkLiteral config.gui.colorscheme.base04;
|
||||
};
|
||||
|
||||
# Holds the entire window
|
||||
"#window" = {
|
||||
transparency = "real";
|
||||
background-color = mkLiteral config.gui.colorscheme.base00;
|
||||
text-color = mkLiteral config.gui.colorscheme.base07;
|
||||
border = mkLiteral "4px";
|
||||
border-color = mkLiteral config.gui.colorscheme.base04;
|
||||
border-radius = mkLiteral "4px";
|
||||
width = mkLiteral "850px";
|
||||
padding = mkLiteral "15px";
|
||||
};
|
||||
|
||||
# Wrapper around bar and results
|
||||
"#mainbox" = {
|
||||
background-color = mkLiteral config.gui.colorscheme.base00;
|
||||
border = mkLiteral "0px";
|
||||
border-radius = mkLiteral "0px";
|
||||
border-color = mkLiteral config.gui.colorscheme.base04;
|
||||
children = map mkLiteral [ "inputbar" "listview" ];
|
||||
spacing = mkLiteral "10px";
|
||||
padding = mkLiteral "10px";
|
||||
};
|
||||
|
||||
# Unknown
|
||||
"#textbox-prompt-colon" = {
|
||||
expand = false;
|
||||
str = ":";
|
||||
margin = mkLiteral "0px 0.3em 0em 0em";
|
||||
text-color = mkLiteral config.gui.colorscheme.base07;
|
||||
};
|
||||
|
||||
# Command prompt left of the input
|
||||
"#prompt" = { enabled = false; };
|
||||
|
||||
# Actual text box
|
||||
"#entry" = {
|
||||
placeholder-color = mkLiteral config.gui.colorscheme.base03;
|
||||
expand = true;
|
||||
horizontal-align = "0";
|
||||
placeholder = "Launch Program";
|
||||
padding = mkLiteral "0px 0px 0px 5px";
|
||||
blink = true;
|
||||
};
|
||||
|
||||
# Top bar
|
||||
"#inputbar" = {
|
||||
children = map mkLiteral [ "prompt" "entry" ];
|
||||
border = mkLiteral "1px";
|
||||
border-radius = mkLiteral "4px";
|
||||
padding = mkLiteral "6px";
|
||||
};
|
||||
|
||||
# Results
|
||||
"#listview" = {
|
||||
background-color = mkLiteral config.gui.colorscheme.base00;
|
||||
padding = mkLiteral "0px";
|
||||
columns = 1;
|
||||
lines = 12;
|
||||
spacing = "5px";
|
||||
cycle = true;
|
||||
dynamic = true;
|
||||
layout = "vertical";
|
||||
};
|
||||
|
||||
# Each result
|
||||
"#element" = {
|
||||
orientation = "vertical";
|
||||
border-radius = mkLiteral "0px";
|
||||
padding = mkLiteral "5px 0px 5px 5px";
|
||||
};
|
||||
"#element.selected" = {
|
||||
border = mkLiteral "1px";
|
||||
border-radius = mkLiteral "4px";
|
||||
border-color = mkLiteral config.gui.colorscheme.base07;
|
||||
background-color = mkLiteral config.gui.colorscheme.base04;
|
||||
text-color = mkLiteral config.gui.colorscheme.base00;
|
||||
};
|
||||
|
||||
"#element-text" = {
|
||||
expand = true;
|
||||
# horizontal-align = mkLiteral "0.5";
|
||||
vertical-align = mkLiteral "0.5";
|
||||
margin = mkLiteral "0px 2.5px 0px 2.5px";
|
||||
};
|
||||
"#element-text.selected" = {
|
||||
background-color = mkLiteral config.gui.colorscheme.base04;
|
||||
text-color = mkLiteral config.gui.colorscheme.base00;
|
||||
};
|
||||
|
||||
# Not sure how to get icons
|
||||
"#element-icon" = {
|
||||
size = mkLiteral "18px";
|
||||
border = mkLiteral "0px";
|
||||
padding = mkLiteral "2px 5px 2px 2px";
|
||||
background-color = mkLiteral config.gui.colorscheme.base00;
|
||||
};
|
||||
"#element-icon.selected" = {
|
||||
background-color = mkLiteral config.gui.colorscheme.base04;
|
||||
text-color = mkLiteral config.gui.colorscheme.base00;
|
||||
};
|
||||
|
||||
};
|
||||
xoffset = 0;
|
||||
yoffset = -20;
|
||||
extraConfig = {
|
||||
show-icons = true;
|
||||
kb-cancel = "Escape,Super+space";
|
||||
modi = "window,run,ssh,emoji,calc,systemd";
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
gui.launcherCommand = "${pkgs.rofi}/bin/rofi -show run -modi run";
|
||||
gui.systemdSearch = "${pkgs.rofi-systemd}/bin/rofi-systemd";
|
||||
gui.altTabCommand = "${pkgs.rofi}/bin/rofi -show window -modi window";
|
||||
|
||||
};
|
||||
|
||||
}
|
10
modules/graphical/rofi/brightness.sh
Executable file
10
modules/graphical/rofi/brightness.sh
Executable file
@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# THEME="$HOME/.config/rofi/config.rasi"
|
||||
|
||||
ICON_UP=""
|
||||
ICON_DOWN=""
|
||||
ICON_OPT=""
|
||||
options="$ICON_UP\n$ICON_OPT\n$ICON_DOWN"
|
||||
chosen="$(echo -e "$options" | rofi -theme-str 'listview { layout:horizontal; }' -dmenu)"
|
||||
echo "$chosen"
|
65
modules/graphical/xorg.nix
Normal file
65
modules/graphical/xorg.nix
Normal file
@ -0,0 +1,65 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
|
||||
gtkTheme = {
|
||||
name = config.gui.gtk.theme.name;
|
||||
package = pkgs.${config.gui.gtk.theme.package};
|
||||
};
|
||||
|
||||
in {
|
||||
|
||||
config = lib.mkIf config.gui.enable {
|
||||
|
||||
# Enable the X11 windowing system.
|
||||
services.xserver = {
|
||||
enable = config.gui.enable;
|
||||
|
||||
# Enable touchpad support
|
||||
libinput.enable = true;
|
||||
|
||||
# Login screen
|
||||
displayManager = {
|
||||
lightdm = {
|
||||
enable = config.services.xserver.enable;
|
||||
background = config.gui.wallpaper;
|
||||
|
||||
# Make the login screen dark
|
||||
greeters.gtk.theme = gtkTheme;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs;
|
||||
[
|
||||
xclip # Clipboard
|
||||
];
|
||||
|
||||
# Required for setting GTK theme (for preferred-color-scheme in browser)
|
||||
services.dbus.packages = [ pkgs.dconf ];
|
||||
programs.dconf.enable = true;
|
||||
|
||||
environment.sessionVariables = { GTK_THEME = config.gui.gtk.theme.name; };
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
programs.fish.shellAliases = {
|
||||
pbcopy = "xclip -selection clipboard -in";
|
||||
pbpaste = "xclip -selection clipboard -out";
|
||||
};
|
||||
|
||||
gtk = let gtkExtraConfig = { gtk-application-prefer-dark-theme = true; };
|
||||
in {
|
||||
enable = true;
|
||||
theme = gtkTheme;
|
||||
gtk3.extraConfig = gtkExtraConfig;
|
||||
gtk4.extraConfig = gtkExtraConfig;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
77
modules/hardware/audio.nix
Normal file
77
modules/hardware/audio.nix
Normal file
@ -0,0 +1,77 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
|
||||
# These micro-scripts change the volume while also triggering the volume
|
||||
# notification widget
|
||||
|
||||
increaseVolume = pkgs.writeShellScriptBin "increaseVolume" ''
|
||||
${pkgs.pamixer}/bin/pamixer -i 2
|
||||
volume=$(${pkgs.pamixer}/bin/pamixer --get-volume)
|
||||
${pkgs.volnoti}/bin/volnoti-show $volume
|
||||
'';
|
||||
|
||||
decreaseVolume = pkgs.writeShellScriptBin "decreaseVolume" ''
|
||||
${pkgs.pamixer}/bin/pamixer -d 2
|
||||
volume=$(${pkgs.pamixer}/bin/pamixer --get-volume)
|
||||
${pkgs.volnoti}/bin/volnoti-show $volume
|
||||
'';
|
||||
|
||||
toggleMute = pkgs.writeShellScriptBin "toggleMute" ''
|
||||
${pkgs.pamixer}/bin/pamixer --toggle-mute
|
||||
mute=$(${pkgs.pamixer}/bin/pamixer --get-mute)
|
||||
if [ "$mute" == "true" ]; then
|
||||
${pkgs.volnoti}/bin/volnoti-show --mute
|
||||
else
|
||||
volume=$(${pkgs.pamixer}/bin/pamixer --get-volume)
|
||||
${pkgs.volnoti}/bin/volnoti-show $volume
|
||||
fi
|
||||
'';
|
||||
|
||||
in {
|
||||
|
||||
config = lib.mkIf config.gui.enable {
|
||||
sound.enable = true;
|
||||
|
||||
# Enable PulseAudio
|
||||
hardware.pulseaudio.enable = true;
|
||||
|
||||
# These aren't necessary, but helpful for the user
|
||||
environment.systemPackages = with pkgs; [
|
||||
pamixer # Audio control
|
||||
volnoti # Volume notifications
|
||||
];
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
# Graphical volume notifications
|
||||
services.volnoti.enable = true;
|
||||
|
||||
xsession.windowManager.i3.config = {
|
||||
|
||||
# Make sure that Volnoti actually starts (home-manager doesn't start
|
||||
# user daemon's automatically)
|
||||
startup = [{
|
||||
command = "systemctl --user restart volnoti";
|
||||
always = true;
|
||||
notification = false;
|
||||
}];
|
||||
|
||||
# i3 keybinds for changing the volume
|
||||
keybindings = {
|
||||
"XF86AudioRaiseVolume" =
|
||||
"exec --no-startup-id ${increaseVolume}/bin/increaseVolume";
|
||||
"XF86AudioLowerVolume" =
|
||||
"exec --no-startup-id ${decreaseVolume}/bin/decreaseVolume";
|
||||
"XF86AudioMute" = "exec --no-startup-id ${toggleMute}/bin/toggleMute";
|
||||
# We can mute the mic by adding "--default-source"
|
||||
"XF86AudioMicMute" =
|
||||
"exec --no-startup-id ${pkgs.pamixer}/bin/pamixer --default-source --toggle-mute";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
}
|
35
modules/hardware/boot.nix
Normal file
35
modules/hardware/boot.nix
Normal file
@ -0,0 +1,35 @@
|
||||
{ config, ... }: {
|
||||
|
||||
boot.loader = {
|
||||
grub = {
|
||||
enable = true;
|
||||
|
||||
# Not sure what this does, but it involves the UEFI/BIOS
|
||||
efiSupport = true;
|
||||
|
||||
# Check for other OSes and make them available
|
||||
useOSProber = true;
|
||||
|
||||
# Install GRUB onto the boot disk
|
||||
# device = config.fileSystems."/boot".device;
|
||||
|
||||
# Don't install GRUB, required for UEFI?
|
||||
device = "nodev";
|
||||
|
||||
# Display menu indefinitely if holding shift key
|
||||
extraConfig = ''
|
||||
if keystatus --shift ; then
|
||||
set timeout=-1
|
||||
else
|
||||
set timeout=0
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
# Always display menu indefinitely; default is 5 seconds
|
||||
# timeout = null;
|
||||
|
||||
# Allows GRUB to interact with the UEFI/BIOS I guess
|
||||
efi.canTouchEfiVariables = true;
|
||||
};
|
||||
}
|
14
modules/hardware/default.nix
Normal file
14
modules/hardware/default.nix
Normal file
@ -0,0 +1,14 @@
|
||||
{ ... }: {
|
||||
|
||||
imports = [
|
||||
./audio.nix
|
||||
./boot.nix
|
||||
./keyboard.nix
|
||||
./monitors.nix
|
||||
./mouse.nix
|
||||
./networking.nix
|
||||
./sleep.nix
|
||||
./wifi.nix
|
||||
];
|
||||
|
||||
}
|
16
modules/hardware/keyboard.nix
Normal file
16
modules/hardware/keyboard.nix
Normal file
@ -0,0 +1,16 @@
|
||||
{ ... }: {
|
||||
|
||||
services.xserver = {
|
||||
|
||||
layout = "us";
|
||||
|
||||
# Keyboard responsiveness
|
||||
autoRepeatDelay = 250;
|
||||
autoRepeatInterval = 40;
|
||||
|
||||
# Swap escape key with caps lock key
|
||||
xkbOptions = "eurosign:e,caps:swapescape";
|
||||
|
||||
};
|
||||
|
||||
}
|
53
modules/hardware/monitors.nix
Normal file
53
modules/hardware/monitors.nix
Normal file
@ -0,0 +1,53 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
# Timezone required for Redshift schedule
|
||||
imports = [ ../system/timezone.nix ];
|
||||
|
||||
config = lib.mkIf config.gui.enable {
|
||||
|
||||
environment.systemPackages = with pkgs;
|
||||
[
|
||||
ddcutil # Monitor brightness control
|
||||
];
|
||||
|
||||
# Reduce blue light at night
|
||||
services.redshift = {
|
||||
enable = true;
|
||||
brightness = {
|
||||
day = "1.0";
|
||||
night = "1.0";
|
||||
};
|
||||
};
|
||||
|
||||
# Detect monitors (brightness) for ddcutil
|
||||
hardware.i2c.enable = true;
|
||||
|
||||
# Grant main user access to external monitors
|
||||
users.users.${config.user}.extraGroups = [ "i2c" ];
|
||||
|
||||
services.xserver.displayManager = {
|
||||
|
||||
# Put the login screen on the left monitor
|
||||
lightdm.greeters.gtk.extraConfig = ''
|
||||
active-monitor=0
|
||||
'';
|
||||
|
||||
# Set up screen position and rotation
|
||||
setupCommands = ''
|
||||
${pkgs.xorg.xrandr}/bin/xrandr --output DisplayPort-0 \
|
||||
--mode 1920x1200 \
|
||||
--pos 1920x0 \
|
||||
--rotate left \
|
||||
--output HDMI-0 \
|
||||
--primary \
|
||||
--mode 1920x1080 \
|
||||
--pos 0x560 \
|
||||
--rotate normal \
|
||||
--output DVI-0 --off \
|
||||
--output DVI-1 --off \
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
21
modules/hardware/mouse.nix
Normal file
21
modules/hardware/mouse.nix
Normal file
@ -0,0 +1,21 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
config = lib.mkIf config.gui.enable {
|
||||
|
||||
# Mouse customization
|
||||
services.ratbagd.enable = true;
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
libratbag # Mouse adjustments
|
||||
piper # Mouse adjustments GUI
|
||||
];
|
||||
|
||||
services.xserver.libinput.mouse = {
|
||||
# Disable mouse acceleration
|
||||
accelProfile = "flat";
|
||||
accelSpeed = "1.15";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
10
modules/hardware/networking.nix
Normal file
10
modules/hardware/networking.nix
Normal file
@ -0,0 +1,10 @@
|
||||
{ ... }: {
|
||||
|
||||
# The global useDHCP flag is deprecated, therefore explicitly set to false here.
|
||||
# Per-interface useDHCP will be mandatory in the future, so this generated config
|
||||
# replicates the default behaviour.
|
||||
networking.useDHCP = false;
|
||||
networking.interfaces.enp0s31f6.useDHCP = true;
|
||||
networking.interfaces.wlp3s0.useDHCP = true;
|
||||
|
||||
}
|
8
modules/hardware/sleep.nix
Normal file
8
modules/hardware/sleep.nix
Normal file
@ -0,0 +1,8 @@
|
||||
{ ... }: {
|
||||
|
||||
# Prevent wake from keyboard
|
||||
powerManagement.powerDownCommands = ''
|
||||
for wakeup in /sys/bus/usb/devices/1-*/power/wakeup; do echo disabled > $wakeup; done
|
||||
'';
|
||||
|
||||
}
|
9
modules/hardware/wifi.nix
Normal file
9
modules/hardware/wifi.nix
Normal file
@ -0,0 +1,9 @@
|
||||
{ ... }: {
|
||||
|
||||
# Enables wireless support via wpa_supplicant.
|
||||
networking.wireless.enable = true;
|
||||
|
||||
# Allows the user to control the WiFi settings.
|
||||
networking.wireless.userControlled.enable = true;
|
||||
|
||||
}
|
88
modules/mail/himalaya.nix
Normal file
88
modules/mail/himalaya.nix
Normal file
@ -0,0 +1,88 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
options = {
|
||||
mailServer = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Server name for the email address.";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
programs.himalaya = { enable = true; };
|
||||
programs.mbsync = { enable = true; };
|
||||
services.mbsync = lib.mkIf pkgs.stdenv.isLinux {
|
||||
enable = true;
|
||||
frequency = "*:0/5";
|
||||
};
|
||||
|
||||
accounts.email = {
|
||||
maildirBasePath = "$HOME/mail";
|
||||
accounts = {
|
||||
home = let address = "${config.user}@${config.mailServer}";
|
||||
in {
|
||||
userName = address;
|
||||
realName = config.fullName;
|
||||
primary = true;
|
||||
inherit address;
|
||||
aliases = map (mailUser: "${mailUser}@${config.mailServer}") [
|
||||
"me"
|
||||
"hey"
|
||||
"admin"
|
||||
];
|
||||
alot = { };
|
||||
flavor = "plain";
|
||||
folders = { };
|
||||
getmail = { };
|
||||
himalaya = {
|
||||
enable = true;
|
||||
settings = {
|
||||
downloads-dir = config.userDirs.download;
|
||||
smtp-insecure = true;
|
||||
};
|
||||
};
|
||||
imap = {
|
||||
host = "imap.purelymail.com";
|
||||
port = 993;
|
||||
tls.enable = true;
|
||||
};
|
||||
imapnotify = {
|
||||
enable = false;
|
||||
boxes = [ ];
|
||||
onNotify = "";
|
||||
onNotifyPost = "";
|
||||
};
|
||||
maildir = { path = "main"; };
|
||||
mbsync = {
|
||||
enable = true;
|
||||
create = "maildir";
|
||||
expunge = "none";
|
||||
remove = "none";
|
||||
patterns = [ "*" ];
|
||||
extraConfig.channel = {
|
||||
CopyArrivalDate = "yes"; # Sync time of original message
|
||||
};
|
||||
};
|
||||
mu.enable = false;
|
||||
notmuch.enable = false;
|
||||
passwordCommand =
|
||||
"${pkgs.age}/bin/age --decrypt --identity ${config.homePath}/.ssh/id_ed25519 ${
|
||||
builtins.toString ./mailpass.age
|
||||
}";
|
||||
smtp = {
|
||||
host = "smtp.purelymail.com";
|
||||
port = 465;
|
||||
tls.enable = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
programs.fish.shellAbbrs = { hi = "himalaya"; };
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
}
|
5
modules/mail/mailpass.age
Normal file
5
modules/mail/mailpass.age
Normal file
@ -0,0 +1,5 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 MgHaOw 8h/ESNjn0gknNXoHM34UobHzPgmRunoP97H+KHOuGQM
|
||||
qowH+6TlCRECGCscRgKx6kswY+PZezYUD6E+x9e+5pM
|
||||
--- kFj1JzRdh/D13Uq9aNTzMJIFysEE+kzzthjewOIR2+o
|
||||
Ȳ<EFBFBD><EFBFBD>6<EFBFBD><EFBFBD><EFBFBD>}rC<72>z<><7A><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
16
modules/services/gnupg.nix
Normal file
16
modules/services/gnupg.nix
Normal file
@ -0,0 +1,16 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
programs.gpg.enable = true;
|
||||
services.gpg-agent = {
|
||||
enable = true;
|
||||
defaultCacheTtl = 86400; # Resets when used
|
||||
defaultCacheTtlSsh = 86400; # Resets when used
|
||||
maxCacheTtl = 34560000; # Can never reset
|
||||
maxCacheTtlSsh = 34560000; # Can never reset
|
||||
pinentryFlavor = "tty";
|
||||
};
|
||||
home = lib.mkIf config.gui.enable { packages = with pkgs; [ pinentry ]; };
|
||||
};
|
||||
|
||||
}
|
28
modules/services/keybase.nix
Normal file
28
modules/services/keybase.nix
Normal file
@ -0,0 +1,28 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
services.keybase.enable = true;
|
||||
services.kbfs = {
|
||||
enable = true;
|
||||
# enableRedirector = true;
|
||||
mountPoint = "/run/user/1000/keybase/kbfs";
|
||||
};
|
||||
security.wrappers.keybase-redirector = {
|
||||
setuid = true;
|
||||
owner = "root";
|
||||
group = "root";
|
||||
source = "${pkgs.kbfs}/bin/redirector";
|
||||
};
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
home.packages = [ (lib.mkIf config.gui.enable pkgs.keybase-gui) ];
|
||||
home.file = let
|
||||
ignorePatterns = ''
|
||||
keybase/
|
||||
kbfs/'';
|
||||
in {
|
||||
".rgignore".text = ignorePatterns;
|
||||
".fdignore".text = ignorePatterns;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
6
modules/services/mullvad.nix
Normal file
6
modules/services/mullvad.nix
Normal file
@ -0,0 +1,6 @@
|
||||
{ pkgs, ... }: {
|
||||
|
||||
services.mullvad-vpn.enable = true;
|
||||
environment.systemPackages = [ pkgs.mullvad-vpn ];
|
||||
|
||||
}
|
18
modules/services/wireguard.nix
Normal file
18
modules/services/wireguard.nix
Normal file
@ -0,0 +1,18 @@
|
||||
{ ... }: {
|
||||
networking.wireguard = {
|
||||
enable = true;
|
||||
interfaces = {
|
||||
wg0 = {
|
||||
ips = [ "10.66.127.235/32" "fc00:bbbb:bbbb:bb01::3:7fea/128" ];
|
||||
generatePrivateKeyFile = true;
|
||||
privateKeyFile = "/private/wireguard/wg0";
|
||||
peers = [{
|
||||
publicKey = "cVDIYPzNChIeANp+0jE12kWM5Ga1MbmNErT1Pmaf12A=";
|
||||
allowedIPs = [ "0.0.0.0/0" "::0/0" ];
|
||||
endpoint = "89.46.62.197:51820";
|
||||
persistentKeepalive = 25;
|
||||
}];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
5
modules/shell/age.nix
Normal file
5
modules/shell/age.nix
Normal file
@ -0,0 +1,5 @@
|
||||
{ config, pkgs, ... }: {
|
||||
|
||||
home-manager.users.${config.user}.home.packages = with pkgs; [ age ];
|
||||
|
||||
}
|
12
modules/shell/default.nix
Normal file
12
modules/shell/default.nix
Normal file
@ -0,0 +1,12 @@
|
||||
{ ... }: {
|
||||
imports = [
|
||||
./age.nix
|
||||
./direnv.nix
|
||||
./fish
|
||||
./fzf.nix
|
||||
./git.nix
|
||||
./github.nix
|
||||
./starship.nix
|
||||
./utilities.nix
|
||||
];
|
||||
}
|
9
modules/shell/direnv.nix
Normal file
9
modules/shell/direnv.nix
Normal file
@ -0,0 +1,9 @@
|
||||
{ config, ... }: {
|
||||
|
||||
home-manager.users.${config.user}.programs.direnv = {
|
||||
enable = true;
|
||||
nix-direnv.enable = true;
|
||||
config = { whitelist = { prefix = [ config.dotfilesPath ]; }; };
|
||||
};
|
||||
|
||||
}
|
155
modules/shell/fish/default.nix
Normal file
155
modules/shell/fish/default.nix
Normal file
@ -0,0 +1,155 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
users.users.${config.user}.shell = pkgs.fish;
|
||||
programs.fish.enable =
|
||||
true; # Needed for LightDM to remember username (TODO: fix)
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
# Packages used in abbreviations and aliases
|
||||
home.packages = with pkgs; [ curl ];
|
||||
|
||||
programs.fish = {
|
||||
enable = true;
|
||||
functions = {
|
||||
commandline-git-commits = {
|
||||
description = "Insert commit into commandline";
|
||||
body = builtins.readFile ./functions/commandline-git-commits.fish;
|
||||
};
|
||||
copy = {
|
||||
description = "Copy file contents into clipboard";
|
||||
body = "cat $argv | pbcopy"; # Need to fix for non-macOS
|
||||
};
|
||||
edit = {
|
||||
description = "Open a file in Vim";
|
||||
body = builtins.readFile ./functions/edit.fish;
|
||||
};
|
||||
envs = {
|
||||
description = "Evaluate a bash-like environment variables file";
|
||||
body = ''set -gx (cat $argv | tr "=" " " | string split ' ')'';
|
||||
};
|
||||
fcd = {
|
||||
description = "Jump to directory";
|
||||
argumentNames = "directory";
|
||||
body = builtins.readFile ./functions/fcd.fish;
|
||||
};
|
||||
fish_user_key_bindings = {
|
||||
body = builtins.readFile ./functions/fish_user_key_bindings.fish;
|
||||
};
|
||||
ip = { body = builtins.readFile ./functions/ip.fish; };
|
||||
json = {
|
||||
description = "Tidy up JSON using jq";
|
||||
body = "pbpaste | jq '.' | pbcopy"; # Need to fix for non-macOS
|
||||
};
|
||||
ls = { body = "${pkgs.exa}/bin/exa $argv"; };
|
||||
note = {
|
||||
description = "Edit or create a note";
|
||||
argumentNames = "filename";
|
||||
body = builtins.readFile ./functions/note.fish;
|
||||
};
|
||||
recent = {
|
||||
description = "Open a recent file in Vim";
|
||||
body = builtins.readFile ./functions/recent.fish;
|
||||
};
|
||||
syncnotes = {
|
||||
description = "Full git commit on notes";
|
||||
body = builtins.readFile ./functions/syncnotes.fish;
|
||||
};
|
||||
};
|
||||
interactiveShellInit = ''
|
||||
fish_vi_key_bindings
|
||||
bind yy fish_clipboard_copy
|
||||
bind Y fish_clipboard_copy
|
||||
bind -M visual y fish_clipboard_copy
|
||||
bind -M default p fish_clipboard_paste
|
||||
set -g fish_vi_force_cursor
|
||||
set -g fish_cursor_default block
|
||||
set -g fish_cursor_insert line
|
||||
set -g fish_cursor_visual block
|
||||
set -g fish_cursor_replace_one underscore
|
||||
'';
|
||||
loginShellInit = "";
|
||||
shellAliases = { };
|
||||
shellAbbrs = {
|
||||
|
||||
# Directory aliases
|
||||
l = "ls -lh";
|
||||
lh = "ls -lh";
|
||||
ll = "ls -alhF";
|
||||
la = "ls -a";
|
||||
c = "cd";
|
||||
"-" = "cd -";
|
||||
mkd = "mkdir -pv";
|
||||
|
||||
# System
|
||||
s = "sudo";
|
||||
sc = "systemctl";
|
||||
scs = "systemctl status";
|
||||
m = "make";
|
||||
|
||||
# Tmux
|
||||
ta = "tmux attach-session";
|
||||
tan = "tmux attach-session -t noah";
|
||||
tnn = "tmux new-session -s noah";
|
||||
|
||||
# Vim (overwritten by Neovim)
|
||||
v = "vim";
|
||||
vl = "vim -c 'normal! `0'";
|
||||
|
||||
# Notes
|
||||
sn = "syncnotes";
|
||||
|
||||
# Fun CLI Tools
|
||||
weather = "curl wttr.in/$WEATHER_CITY";
|
||||
moon = "curl wttr.in/Moon";
|
||||
|
||||
# Cheat Sheets
|
||||
ssl =
|
||||
"openssl req -new -newkey rsa:2048 -nodes -keyout server.key -out server.csr";
|
||||
fingerprint = "ssh-keyscan myhost.com | ssh-keygen -lf -";
|
||||
publickey = "ssh-keygen -y -f ~/.ssh/id_rsa > ~/.ssh/id_rsa.pub";
|
||||
forloop = "for i in (seq 1 100)";
|
||||
|
||||
# Docker
|
||||
dc = "$DOTS/bin/docker_cleanup";
|
||||
dr = "docker run --rm -it";
|
||||
db = "docker build . -t";
|
||||
|
||||
# Terraform
|
||||
te = "terraform";
|
||||
|
||||
# Kubernetes
|
||||
k = "kubectl";
|
||||
pods = "kubectl get pods -A";
|
||||
nodes = "kubectl get nodes";
|
||||
deploys = "kubectl get deployments -A";
|
||||
dash = "kube-dashboard";
|
||||
ks = "k9s";
|
||||
|
||||
# Python
|
||||
py = "python";
|
||||
po = "poetry";
|
||||
pr = "poetry run python";
|
||||
|
||||
# Rust
|
||||
ca = "cargo";
|
||||
|
||||
};
|
||||
shellInit = "";
|
||||
};
|
||||
|
||||
home.sessionVariables.fish_greeting = "";
|
||||
|
||||
programs.starship.enableFishIntegration = true;
|
||||
programs.zoxide.enableFishIntegration = true;
|
||||
programs.fzf.enableFishIntegration = true;
|
||||
|
||||
# Provides "command-not-found" options
|
||||
# Requires activating a manual download
|
||||
programs.nix-index = {
|
||||
enable = true;
|
||||
enableFishIntegration = true;
|
||||
};
|
||||
|
||||
};
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
set commit (git-commits)
|
||||
if [ $commit ]
|
||||
commandline -i "$commit"
|
||||
else
|
||||
commandline -i HEAD
|
||||
end
|
4
modules/shell/fish/functions/edit.fish
Normal file
4
modules/shell/fish/functions/edit.fish
Normal file
@ -0,0 +1,4 @@
|
||||
set vimfile (fzf)
|
||||
and set vimfile (echo $vimfile | tr -d '\r')
|
||||
and commandline -r "vim $vimfile"
|
||||
and commandline -f execute
|
10
modules/shell/fish/functions/fcd.fish
Normal file
10
modules/shell/fish/functions/fcd.fish
Normal file
@ -0,0 +1,10 @@
|
||||
if test -z $directory
|
||||
set directory "$HOME"
|
||||
end
|
||||
if ! test -d $directory
|
||||
echo "Directory not found: $directory"
|
||||
return 1
|
||||
end
|
||||
set jump (fd -t d . $directory | fzf)
|
||||
and cd $jump $argv
|
||||
and commandline -f execute
|
14
modules/shell/fish/functions/fish_user_key_bindings.fish
Normal file
14
modules/shell/fish/functions/fish_user_key_bindings.fish
Normal file
@ -0,0 +1,14 @@
|
||||
bind -M insert \co edit
|
||||
bind -M default \co edit
|
||||
bind -M insert \ca 'cd ~; and edit; and commandline -a "; cd -"; commandline -f execute'
|
||||
bind -M default \ca 'cd ~; and edit; and commandline -a "; cd -"; commandline -f execute'
|
||||
bind -M insert \ce recent
|
||||
bind -M default \ce recent
|
||||
bind -M insert \cg commandline-git-commits
|
||||
bind -M insert \cG 'commandline -i (git rev-parse --show-toplevel 2>/dev/null || echo ".")'
|
||||
bind -M insert \cf fcd
|
||||
bind -M default \cf fcd
|
||||
bind -M insert \cp projects
|
||||
bind -M default \cp projects
|
||||
bind -M insert \x1F accept-autosuggestion
|
||||
bind -M default \x1F accept-autosuggestion
|
122
modules/shell/fish/functions/fish_vi_cursor.fish
Normal file
122
modules/shell/fish/functions/fish_vi_cursor.fish
Normal file
@ -0,0 +1,122 @@
|
||||
#!/usr/local/bin/fish
|
||||
|
||||
function fish_vi_cursor -d 'Set cursor shape for different vi modes'
|
||||
# If we're not interactive, there is effectively no bind mode.
|
||||
if not status is-interactive
|
||||
return
|
||||
end
|
||||
|
||||
# This is hard to test in expect, since the exact sequences depend on the environment.
|
||||
# Instead disable it.
|
||||
if set -q FISH_UNIT_TESTS_RUNNING
|
||||
return
|
||||
end
|
||||
|
||||
# If this variable is set, skip all checks
|
||||
if not set -q fish_vi_force_cursor
|
||||
|
||||
# Emacs Makes All Cursors Suck
|
||||
if set -q INSIDE_EMACS
|
||||
return
|
||||
end
|
||||
|
||||
# vte-based terms set $TERM = xterm*, but only gained support in 2015.
|
||||
# From https://bugzilla.gnome.org/show_bug.cgi?id=720821, it appears it was version 0.40.0
|
||||
if set -q VTE_VERSION
|
||||
and test "$VTE_VERSION" -lt 4000 2>/dev/null
|
||||
return
|
||||
end
|
||||
|
||||
# Similarly, genuine XTerm can do it since v280.
|
||||
if set -q XTERM_VERSION
|
||||
and not test (string replace -r "XTerm\((\d+)\)" '$1' -- "$XTERM_VERSION") -ge 280 2>/dev/null
|
||||
return
|
||||
end
|
||||
|
||||
# We need one of these terms.
|
||||
# It would be lovely if we could rely on terminfo, but:
|
||||
# - The "Ss" entry isn't a thing in macOS' old and crusty terminfo
|
||||
# - It is set for xterm, and everyone and their dog claims to be xterm
|
||||
#
|
||||
# So we just don't care about $TERM, unless it is one of the few terminals that actually have their own entry.
|
||||
#
|
||||
# Note: Previous versions also checked $TMUX, and made sure that then $TERM was screen* or tmux*.
|
||||
# We don't care, since we *cannot* handle term-in-a-terms 100% correctly.
|
||||
if not set -q KONSOLE_PROFILE_NAME
|
||||
and not test -n "$KONSOLE_VERSION" -a "$KONSOLE_VERSION" -ge 200400 # konsole, but new.
|
||||
and not set -q ITERM_PROFILE
|
||||
and not set -q VTE_VERSION # which version is already checked above
|
||||
and not set -q WT_PROFILE_ID
|
||||
and not set -q XTERM_VERSION
|
||||
and not string match -rq '^st(-.*)$' -- $TERM
|
||||
and not string match -q 'xterm-kitty*' -- $TERM
|
||||
and not string match -q 'rxvt*' -- $TERM
|
||||
and not string match -q 'alacritty*' -- $TERM
|
||||
return
|
||||
end
|
||||
|
||||
# HACK: Explicitly disable on ITERM because of #3696, which is weirdness with multi-line prompts.
|
||||
# --force-iterm is now deprecated; set $fish_vi_force_cursor instead
|
||||
if contains -- $argv[1] --force-iterm
|
||||
set -e argv[1]
|
||||
else if set -q ITERM_PROFILE
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
set -l terminal $argv[1]
|
||||
set -q terminal[1]
|
||||
or set terminal auto
|
||||
|
||||
set -l function
|
||||
switch "$terminal"
|
||||
case auto
|
||||
# Nowadays, konsole does not set $KONSOLE_PROFILE_NAME anymore,
|
||||
# and it uses the xterm sequences.
|
||||
if set -q KONSOLE_PROFILE_NAME
|
||||
set function __fish_cursor_konsole
|
||||
else if set -q ITERM_PROFILE
|
||||
set function __fish_cursor_1337
|
||||
else
|
||||
set function __fish_cursor_xterm
|
||||
end
|
||||
case konsole
|
||||
set function __fish_cursor_konsole
|
||||
case xterm
|
||||
set function __fish_cursor_xterm
|
||||
end
|
||||
|
||||
set -l tmux_prefix
|
||||
set -l tmux_postfix
|
||||
if set -q TMUX
|
||||
set tmux_prefix echo -ne "'\ePtmux;\e'"
|
||||
set tmux_postfix echo -ne "'\e\\\\'"
|
||||
end
|
||||
|
||||
set -q fish_cursor_unknown
|
||||
or set -g fish_cursor_unknown block blink
|
||||
|
||||
echo "
|
||||
function fish_vi_cursor_handle --on-variable fish_bind_mode --on-event fish_postexec --on-event fish_focus_in
|
||||
set -l varname fish_cursor_\$fish_bind_mode
|
||||
if not set -q \$varname
|
||||
set varname fish_cursor_unknown
|
||||
end
|
||||
$tmux_prefix
|
||||
$function \$\$varname
|
||||
$tmux_postfix
|
||||
end
|
||||
" | source
|
||||
|
||||
echo "
|
||||
function fish_vi_cursor_handle_preexec --on-event fish_preexec
|
||||
set -l varname fish_cursor_default
|
||||
if not set -q \$varname
|
||||
set varname fish_cursor_unknown
|
||||
end
|
||||
$tmux_prefix
|
||||
$function \$\$varname
|
||||
$tmux_postfix
|
||||
end
|
||||
" | source
|
||||
end
|
14
modules/shell/fish/functions/git-add-fuzzy.fish
Normal file
14
modules/shell/fish/functions/git-add-fuzzy.fish
Normal file
@ -0,0 +1,14 @@
|
||||
set gitfile (git status -s \
|
||||
| fzf \
|
||||
--height 50% \
|
||||
-m \
|
||||
--preview-window right:70% \
|
||||
--layout reverse \
|
||||
--preview 'set -l IFS; set gd (git diff --color=always (echo {} | awk \'{$1=$1};1\' | cut -d" " -f2)); if test "$gd"; echo "$gd"; else; bat --color=always (echo {} | awk \'{$1=$1};1\' | cut -d" " -f2); end')
|
||||
and for gf in $gitfile
|
||||
set gf (echo $gf \
|
||||
| awk '{$1=$1};1' \
|
||||
| cut -d' ' -f2 \
|
||||
)
|
||||
and git add $gf
|
||||
end
|
8
modules/shell/fish/functions/git-commits.fish
Normal file
8
modules/shell/fish/functions/git-commits.fish
Normal file
@ -0,0 +1,8 @@
|
||||
set commitline (git log \
|
||||
--pretty="format:%C(auto)%ar %h%d %s" \
|
||||
| fzf \
|
||||
--height 50% \
|
||||
--preview 'git show --color=always (echo {} | cut -d" " -f4)' \
|
||||
)
|
||||
and set commit (echo $commitline | cut -d" " -f4)
|
||||
and echo $commit
|
10
modules/shell/fish/functions/git-fuzzy-branch.fish
Normal file
10
modules/shell/fish/functions/git-fuzzy-branch.fish
Normal file
@ -0,0 +1,10 @@
|
||||
set -l current (git rev-parse --abbrev-ref HEAD | tr -d '\n')
|
||||
set -l branch (git branch \
|
||||
--format "%(refname:short)" \
|
||||
| fzf \
|
||||
--height 50% \
|
||||
--header="On $current, $header" \
|
||||
--preview-window right:70% \
|
||||
--preview 'git log {} --color=always --pretty="format:%C(auto)%ar %h%d %s"' \
|
||||
)
|
||||
and echo $branch
|
14
modules/shell/fish/functions/git-history.fish
Normal file
14
modules/shell/fish/functions/git-history.fish
Normal file
@ -0,0 +1,14 @@
|
||||
if not count $argv >/dev/null
|
||||
echo "Must provide filename."
|
||||
return 1
|
||||
end
|
||||
set commitline ( git log \
|
||||
--follow \
|
||||
--pretty="format:%C(auto)%ar %h%d %s" \
|
||||
-- ./$argv \
|
||||
| fzf \
|
||||
--height 100% \
|
||||
--preview "git diff --color=always (echo {} | cut -d' ' -f4)^1..(echo {} | cut -d' ' -f4) -- ./$argv" \
|
||||
)
|
||||
and set commit (echo $commitline | cut -d" " -f4)
|
||||
and echo $commit
|
6
modules/shell/fish/functions/git-push-upstream.fish
Normal file
6
modules/shell/fish/functions/git-push-upstream.fish
Normal file
@ -0,0 +1,6 @@
|
||||
set -l branch (git branch 2>/dev/null | grep '^\*' | colrm 1 2)
|
||||
and set -l command "git push --set-upstream origin $branch"
|
||||
and commandline -r $command
|
||||
and commandline -f execute
|
||||
and echo "git push --set-upstream origin $branch"
|
||||
and git push --set-upstream origin $branch
|
6
modules/shell/fish/functions/git-show-fuzzy.fish
Normal file
6
modules/shell/fish/functions/git-show-fuzzy.fish
Normal file
@ -0,0 +1,6 @@
|
||||
set commitline (git log \
|
||||
--pretty="format:%C(auto)%ar %h%d %s" \
|
||||
| fzf \
|
||||
)
|
||||
and set commit (echo $commitline | cut -d" " -f4 )
|
||||
and git show $commit
|
37
modules/shell/fish/functions/git.fish
Normal file
37
modules/shell/fish/functions/git.fish
Normal file
@ -0,0 +1,37 @@
|
||||
if contains f $argv
|
||||
switch $argv[1]
|
||||
case checkout
|
||||
git-checkout-fuzzy
|
||||
case add
|
||||
git-add-fuzzy
|
||||
case show
|
||||
git-show-fuzzy
|
||||
case merge
|
||||
git-merge-fuzzy
|
||||
case branch
|
||||
if test "$argv[2]" = -d
|
||||
git-delete-fuzzy
|
||||
else if test "$argv[2]" = -D
|
||||
git-force-delete-fuzzy
|
||||
else
|
||||
echo "Not a fuzzy option."
|
||||
return 1
|
||||
end
|
||||
case reset
|
||||
set commit (git-commits)
|
||||
and if test "$argv[2]" = --hard
|
||||
git reset --hard $commit
|
||||
else
|
||||
git reset $commit
|
||||
end
|
||||
case "*"
|
||||
echo "No fuzzy option."
|
||||
return 1
|
||||
end
|
||||
else
|
||||
if count $argv >/dev/null
|
||||
command git $argv
|
||||
else
|
||||
command git status -sb
|
||||
end
|
||||
end
|
5
modules/shell/fish/functions/ip.fish
Normal file
5
modules/shell/fish/functions/ip.fish
Normal file
@ -0,0 +1,5 @@
|
||||
if count $argv >/dev/null
|
||||
curl ipinfo.io/$argv
|
||||
else
|
||||
curl checkip.amazonaws.com
|
||||
end
|
8
modules/shell/fish/functions/note.fish
Normal file
8
modules/shell/fish/functions/note.fish
Normal file
@ -0,0 +1,8 @@
|
||||
if test -n "$filename"
|
||||
vim $NOTES_PATH/$filename.md
|
||||
else
|
||||
set file (ls $NOTES_PATH | fzf)
|
||||
if [ $status -eq 0 ]
|
||||
vim $NOTES_PATH/$file
|
||||
end
|
||||
end
|
4
modules/shell/fish/functions/recent.fish
Normal file
4
modules/shell/fish/functions/recent.fish
Normal file
@ -0,0 +1,4 @@
|
||||
set vimfile (fd -t f --exec stat -f "%m%t%N" | sort -nr | cut -f2 | fzf)
|
||||
and set vimfile (echo $vimfile | tr -d '\r')
|
||||
and commandline -r "vim $vimfile"
|
||||
and commandline -f execute
|
7
modules/shell/fish/functions/syncnotes.fish
Normal file
7
modules/shell/fish/functions/syncnotes.fish
Normal file
@ -0,0 +1,7 @@
|
||||
set current_dir $PWD
|
||||
cd $NOTES_PATH
|
||||
git pull
|
||||
git add -A
|
||||
git commit -m autosync
|
||||
git push
|
||||
cd $current_dir
|
11
modules/shell/fish/functions/uncommitted.fish
Normal file
11
modules/shell/fish/functions/uncommitted.fish
Normal file
@ -0,0 +1,11 @@
|
||||
set current_dir (pwd)
|
||||
cd $HOME/dev
|
||||
find . -type d -name '.git' | while read dir
|
||||
cd $dir/../
|
||||
and if test -n (echo (git status -s))
|
||||
pwd
|
||||
git status -s
|
||||
end
|
||||
cd -
|
||||
end
|
||||
cd $current_dir
|
31
modules/shell/fzf.nix
Normal file
31
modules/shell/fzf.nix
Normal file
@ -0,0 +1,31 @@
|
||||
{ config, ... }: {
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
programs.fzf.enable = true;
|
||||
|
||||
programs.fish = {
|
||||
functions = {
|
||||
projects = {
|
||||
description = "Jump to a project";
|
||||
body = ''
|
||||
set projdir (ls ${config.homePath}/dev/personal | fzf)
|
||||
and cd ${config.homePath}/dev/personal/$projdir
|
||||
and commandline -f execute
|
||||
'';
|
||||
};
|
||||
};
|
||||
shellAbbrs = { lf = "ls -lh | fzf"; };
|
||||
};
|
||||
|
||||
# Global fzf configuration
|
||||
home.sessionVariables = let fzfCommand = "fd --type file";
|
||||
in {
|
||||
FZF_DEFAULT_COMMAND = fzfCommand;
|
||||
FZF_CTRL_T_COMMAND = fzfCommand;
|
||||
FZF_DEFAULT_OPTS = "-m --height 50% --border";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
125
modules/shell/git.nix
Normal file
125
modules/shell/git.nix
Normal file
@ -0,0 +1,125 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let home-packages = config.home-manager.users.${config.user}.home.packages;
|
||||
|
||||
in {
|
||||
|
||||
options = {
|
||||
fullName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Human readable name of the user";
|
||||
};
|
||||
gitEmail = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Email to use for git commits";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
|
||||
home-manager.users.root.programs.git = {
|
||||
enable = true;
|
||||
extraConfig.safe.directory = config.dotfilesPath;
|
||||
};
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
programs.git = {
|
||||
enable = true;
|
||||
userName = config.fullName;
|
||||
userEmail = config.gitEmail;
|
||||
extraConfig = {
|
||||
pager = { branch = "false"; };
|
||||
safe = { directory = config.dotfilesPath; };
|
||||
pull = { ff = "only"; };
|
||||
init = { defaultBranch = "master"; };
|
||||
};
|
||||
};
|
||||
|
||||
programs.fish.shellAbbrs = {
|
||||
g = "git";
|
||||
gs = "git status";
|
||||
gd = "git diff";
|
||||
gds = "git diff --staged";
|
||||
gdp = "git diff HEAD^";
|
||||
ga = "git add";
|
||||
gaa = "git add -A";
|
||||
gac = "git commit -am";
|
||||
gc = "git commit -m";
|
||||
gca = "git commit --amend --no-edit";
|
||||
gcae = "git commit --amend";
|
||||
gu = "git pull";
|
||||
gp = "git push";
|
||||
gpp = "git-push-upstream";
|
||||
gl = "git log --graph --decorate --oneline -20";
|
||||
gll = "git log --graph --decorate --oneline";
|
||||
gco = "git checkout";
|
||||
gcom = ''
|
||||
git switch (git symbolic-ref refs/remotes/origin/HEAD | cut -d"/" -f4)'';
|
||||
gcob = "git switch -c";
|
||||
gb = "git branch";
|
||||
gbd = "git branch -d";
|
||||
gbD = "git branch -D";
|
||||
gr = "git reset";
|
||||
grh = "git reset --hard";
|
||||
gm = "git merge";
|
||||
gcp = "git cherry-pick";
|
||||
cdg = "cd (git rev-parse --show-toplevel)";
|
||||
};
|
||||
|
||||
programs.fish.functions = lib.mkIf (builtins.elem pkgs.fzf home-packages
|
||||
&& builtins.elem pkgs.bat home-packages) {
|
||||
git = { body = builtins.readFile ./fish/functions/git.fish; };
|
||||
git-add-fuzzy = {
|
||||
body = builtins.readFile ./fish/functions/git-add-fuzzy.fish;
|
||||
};
|
||||
git-fuzzy-branch = {
|
||||
argumentNames = "header";
|
||||
body = builtins.readFile ./fish/functions/git-fuzzy-branch.fish;
|
||||
};
|
||||
git-checkout-fuzzy = {
|
||||
body = ''
|
||||
set branch (git-fuzzy-branch "checkout branch...")
|
||||
and git checkout $branch
|
||||
'';
|
||||
};
|
||||
git-delete-fuzzy = {
|
||||
body = ''
|
||||
set branch (git-fuzzy-branch "delete branch...")
|
||||
and git branch -d $branch
|
||||
'';
|
||||
};
|
||||
git-force-delete-fuzzy = {
|
||||
body = ''
|
||||
set branch (git-fuzzy-branch "force delete branch...")
|
||||
and git branch -D $branch
|
||||
'';
|
||||
};
|
||||
git-merge-fuzzy = {
|
||||
body = ''
|
||||
set branch (git-fuzzy-branch "merge from...")
|
||||
and git merge $branch
|
||||
'';
|
||||
};
|
||||
git-show-fuzzy = {
|
||||
body = builtins.readFile ./fish/functions/git-show-fuzzy.fish;
|
||||
};
|
||||
git-commits = {
|
||||
body = builtins.readFile ./fish/functions/git-commits.fish;
|
||||
};
|
||||
git-history = {
|
||||
body = builtins.readFile ./fish/functions/git-history.fish;
|
||||
};
|
||||
git-push-upstream = {
|
||||
description = "Create upstream branch";
|
||||
body = builtins.readFile ./fish/functions/git-push-upstream.fish;
|
||||
};
|
||||
uncommitted = {
|
||||
description = "Find uncommitted git repos";
|
||||
body = builtins.readFile ./fish/functions/uncommitted.fish;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
36
modules/shell/github.nix
Normal file
36
modules/shell/github.nix
Normal file
@ -0,0 +1,36 @@
|
||||
{ config, pkgs, lib, ... }: {
|
||||
|
||||
home-manager.users.${config.user} = {
|
||||
|
||||
programs.gh =
|
||||
lib.mkIf config.home-manager.users.${config.user}.programs.git.enable {
|
||||
enable = true;
|
||||
enableGitCredentialHelper = true;
|
||||
settings.git_protocol = "https";
|
||||
};
|
||||
|
||||
programs.fish =
|
||||
lib.mkIf config.home-manager.users.${config.user}.programs.gh.enable {
|
||||
shellAbbrs = {
|
||||
ghr = "gh repo view -w";
|
||||
gha =
|
||||
"gh run list | head -1 | awk '{ print $(NF-2) }' | xargs gh run view";
|
||||
grw = "gh run watch";
|
||||
grf = "gh run view --log-failed";
|
||||
grl = "gh run view --log";
|
||||
};
|
||||
functions = {
|
||||
repos = {
|
||||
description = "Clone GitHub repositories";
|
||||
argumentNames = "organization";
|
||||
body = ''
|
||||
set directory (gh-repos $organization)
|
||||
and cd $directory
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
54
modules/shell/starship.nix
Normal file
54
modules/shell/starship.nix
Normal file
@ -0,0 +1,54 @@
|
||||
{ config, lib, ... }: {
|
||||
|
||||
home-manager.users.${config.user}.programs.starship = {
|
||||
enable = true;
|
||||
settings = {
|
||||
add_newline = false; # Don't print new line at the start of the prompt
|
||||
format = lib.concatStrings [
|
||||
"$directory"
|
||||
"$git_branch"
|
||||
"$git_commit"
|
||||
"$git_status"
|
||||
"$python"
|
||||
"$cmd_duration"
|
||||
"$character"
|
||||
];
|
||||
character = {
|
||||
success_symbol = "[❯](bold green)";
|
||||
error_symbol = "[❯](bold red)";
|
||||
vicmd_symbol = "[❮](bold green)";
|
||||
};
|
||||
cmd_duration = {
|
||||
min_time = 5000;
|
||||
show_notifications = true;
|
||||
min_time_to_notify = 30000;
|
||||
format = "[$duration]($style) ";
|
||||
};
|
||||
directory = {
|
||||
truncate_to_repo = true;
|
||||
truncation_length = 100;
|
||||
};
|
||||
git_branch = { format = "[$symbol$branch]($style)"; };
|
||||
git_commit = {
|
||||
format = "( @ [$hash]($style) )";
|
||||
only_detached = false;
|
||||
};
|
||||
git_status = {
|
||||
format = "([$all_status$ahead_behind]($style) )";
|
||||
conflicted = "=";
|
||||
ahead = "⇡";
|
||||
behind = "⇣";
|
||||
diverged = "⇕";
|
||||
untracked = "⋄";
|
||||
stashed = "⩮";
|
||||
modified = "∽";
|
||||
staged = "+";
|
||||
renamed = "»";
|
||||
deleted = "✘";
|
||||
style = "red";
|
||||
};
|
||||
python = { format = "[\\($virtualenv\\)]($style)"; };
|
||||
};
|
||||
};
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user