refactor: implement component-based architecture for enhanced maintainability
- Reorganize directory structure into core/, features/, and themes/ - Colocate application Nix logic, configs, scripts, and theme overrides - Implement 'Inversion of Control' for theming: apps now pull theme-specific layouts - Update flake.nix and shared library paths to match the new structure - Document the new Feature-Centric architecture in README.md
This commit is contained in:
25
features/apps/alacritty/config/alacritty.toml
Normal file
25
features/apps/alacritty/config/alacritty.toml
Normal file
@@ -0,0 +1,25 @@
|
||||
general.import = [ "~/.config/nomarchy/current/theme/alacritty.toml" ]
|
||||
|
||||
[env]
|
||||
TERM = "xterm-256color"
|
||||
|
||||
[terminal]
|
||||
osc52 = "CopyPaste"
|
||||
|
||||
[font]
|
||||
normal = { family = "JetBrainsMono Nerd Font", style = "Regular" }
|
||||
bold = { family = "JetBrainsMono Nerd Font", style = "Bold" }
|
||||
italic = { family = "JetBrainsMono Nerd Font", style = "Italic" }
|
||||
size = 9
|
||||
|
||||
[window]
|
||||
padding.x = 14
|
||||
padding.y = 14
|
||||
decorations = "None"
|
||||
|
||||
[keyboard]
|
||||
bindings = [
|
||||
{ key = "Insert", mods = "Shift", action = "Paste" },
|
||||
{ key = "Insert", mods = "Control", action = "Copy" },
|
||||
{ key = "Return", mods = "Shift", chars = "\u001B\r" }
|
||||
]
|
||||
26
features/apps/alacritty/default.nix
Normal file
26
features/apps/alacritty/default.nix
Normal file
@@ -0,0 +1,26 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
programs.alacritty = {
|
||||
enable = lib.mkDefault true;
|
||||
settings = lib.mkDefault {
|
||||
env = {
|
||||
TERM = "xterm-256color";
|
||||
};
|
||||
terminal = {
|
||||
osc52 = "CopyPaste";
|
||||
};
|
||||
window = {
|
||||
padding = { x = 14; y = 14; };
|
||||
decorations = "None";
|
||||
};
|
||||
keyboard = {
|
||||
bindings = [
|
||||
{ key = "Insert"; mods = "Shift"; action = "Paste"; }
|
||||
{ key = "Insert"; mods = "Control"; action = "Copy"; }
|
||||
{ key = "Return"; mods = "Shift"; chars = "\\u001B\\r"; }
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
30
features/apps/browser.nix
Normal file
30
features/apps/browser.nix
Normal file
@@ -0,0 +1,30 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
nomarchyLib = import ../lib { inherit lib; };
|
||||
activeThemeName = config.nomarchy.system.theme;
|
||||
currentPalette = nomarchyLib.getPalette activeThemeName;
|
||||
|
||||
# Hex color for browser theme (base00 is background)
|
||||
themeColor = "#${currentPalette.base00}";
|
||||
|
||||
# Detect light mode from theme name or palette
|
||||
isLightTheme = nomarchyLib.isThemeLightMode {
|
||||
themeName = activeThemeName;
|
||||
assetsPath = ../../assets/themes;
|
||||
};
|
||||
|
||||
browserPolicy = {
|
||||
BrowserThemeColor = themeColor;
|
||||
BrowserColorScheme = if isLightTheme then "light" else "dark";
|
||||
};
|
||||
in
|
||||
{
|
||||
# Chromium policies
|
||||
programs.chromium.extraOpts = lib.mkDefault browserPolicy;
|
||||
|
||||
# Brave browser policies via managed policy file
|
||||
environment.etc."brave/policies/managed/nomarchy.json".text = lib.mkDefault (
|
||||
builtins.toJSON browserPolicy
|
||||
);
|
||||
}
|
||||
246
features/apps/btop/config/btop.conf
Normal file
246
features/apps/btop/config/btop.conf
Normal file
@@ -0,0 +1,246 @@
|
||||
#? Config file for btop
|
||||
|
||||
#* Name of a btop++/bpytop/bashtop formatted ".theme" file, "Default" and "TTY" for builtin themes.
|
||||
#* Themes should be placed in "../share/btop/themes" relative to binary or "$HOME/.config/btop/themes"
|
||||
color_theme = "current"
|
||||
|
||||
#* If the theme set background should be shown, set to False if you want terminal background transparency.
|
||||
theme_background = True
|
||||
|
||||
#* Sets if 24-bit truecolor should be used, will convert 24-bit colors to 256 color (6x6x6 color cube) if false.
|
||||
truecolor = True
|
||||
|
||||
#* Set to true to force tty mode regardless if a real tty has been detected or not.
|
||||
#* Will force 16-color mode and TTY theme, set all graph symbols to "tty" and swap out other non tty friendly symbols.
|
||||
force_tty = False
|
||||
|
||||
#* Define presets for the layout of the boxes. Preset 0 is always all boxes shown with default settings. Max 9 presets.
|
||||
#* Format: "box_name:P:G,box_name:P:G" P=(0 or 1) for alternate positions, G=graph symbol to use for box.
|
||||
#* Use whitespace " " as separator between different presets.
|
||||
#* Example: "cpu:0:default,mem:0:tty,proc:1:default cpu:0:braille,proc:0:tty"
|
||||
presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty"
|
||||
|
||||
#* Set to True to enable "h,j,k,l,g,G" keys for directional control in lists.
|
||||
#* Conflicting keys for h:"help" and k:"kill" is accessible while holding shift.
|
||||
vim_keys = True
|
||||
|
||||
#* Rounded corners on boxes, is ignored if TTY mode is ON.
|
||||
rounded_corners = True
|
||||
|
||||
#* Default symbols to use for graph creation, "braille", "block" or "tty".
|
||||
#* "braille" offers the highest resolution but might not be included in all fonts.
|
||||
#* "block" has half the resolution of braille but uses more common characters.
|
||||
#* "tty" uses only 3 different symbols but will work with most fonts and should work in a real TTY.
|
||||
#* Note that "tty" only has half the horizontal resolution of the other two, so will show a shorter historical view.
|
||||
graph_symbol = "braille"
|
||||
|
||||
# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
|
||||
graph_symbol_cpu = "default"
|
||||
|
||||
# Graph symbol to use for graphs in gpu box, "default", "braille", "block" or "tty".
|
||||
graph_symbol_gpu = "default"
|
||||
|
||||
# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
|
||||
graph_symbol_mem = "default"
|
||||
|
||||
# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
|
||||
graph_symbol_net = "default"
|
||||
|
||||
# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
|
||||
graph_symbol_proc = "default"
|
||||
|
||||
#* Manually set which boxes to show. Available values are "cpu mem net proc" and "gpu0" through "gpu5", separate values with whitespace.
|
||||
shown_boxes = "cpu mem net proc"
|
||||
|
||||
#* Update time in milliseconds, recommended 2000 ms or above for better sample times for graphs.
|
||||
update_ms = 2000
|
||||
|
||||
#* Processes sorting, "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu direct",
|
||||
#* "cpu lazy" sorts top process over time (easier to follow), "cpu direct" updates top process directly.
|
||||
proc_sorting = "cpu lazy"
|
||||
|
||||
#* Reverse sorting order, True or False.
|
||||
proc_reversed = False
|
||||
|
||||
#* Show processes as a tree.
|
||||
proc_tree = False
|
||||
|
||||
#* Use the cpu graph colors in the process list.
|
||||
proc_colors = True
|
||||
|
||||
#* Use a darkening gradient in the process list.
|
||||
proc_gradient = True
|
||||
|
||||
#* If process cpu usage should be of the core it's running on or usage of the total available cpu power.
|
||||
proc_per_core = False
|
||||
|
||||
#* Show process memory as bytes instead of percent.
|
||||
proc_mem_bytes = True
|
||||
|
||||
#* Show cpu graph for each process.
|
||||
proc_cpu_graphs = True
|
||||
|
||||
#* Use /proc/[pid]/smaps for memory information in the process info box (very slow but more accurate)
|
||||
proc_info_smaps = False
|
||||
|
||||
#* Show proc box on left side of screen instead of right.
|
||||
proc_left = False
|
||||
|
||||
#* (Linux) Filter processes tied to the Linux kernel(similar behavior to htop).
|
||||
proc_filter_kernel = False
|
||||
|
||||
#* In tree-view, always accumulate child process resources in the parent process.
|
||||
proc_aggregate = False
|
||||
|
||||
#* Sets the CPU stat shown in upper half of the CPU graph, "total" is always available.
|
||||
#* Select from a list of detected attributes from the options menu.
|
||||
cpu_graph_upper = "Auto"
|
||||
|
||||
#* Sets the CPU stat shown in lower half of the CPU graph, "total" is always available.
|
||||
#* Select from a list of detected attributes from the options menu.
|
||||
cpu_graph_lower = "Auto"
|
||||
|
||||
#* If gpu info should be shown in the cpu box. Available values = "Auto", "On" and "Off".
|
||||
show_gpu_info = "Auto"
|
||||
|
||||
#* Toggles if the lower CPU graph should be inverted.
|
||||
cpu_invert_lower = True
|
||||
|
||||
#* Set to True to completely disable the lower CPU graph.
|
||||
cpu_single_graph = False
|
||||
|
||||
#* Show cpu box at bottom of screen instead of top.
|
||||
cpu_bottom = False
|
||||
|
||||
#* Shows the system uptime in the CPU box.
|
||||
show_uptime = True
|
||||
|
||||
#* Show cpu temperature.
|
||||
check_temp = True
|
||||
|
||||
#* Which sensor to use for cpu temperature, use options menu to select from list of available sensors.
|
||||
cpu_sensor = "Auto"
|
||||
|
||||
#* Show temperatures for cpu cores also if check_temp is True and sensors has been found.
|
||||
show_coretemp = True
|
||||
|
||||
#* Set a custom mapping between core and coretemp, can be needed on certain cpus to get correct temperature for correct core.
|
||||
#* Use lm-sensors or similar to see which cores are reporting temperatures on your machine.
|
||||
#* Format "x:y" x=core with wrong temp, y=core with correct temp, use space as separator between multiple entries.
|
||||
#* Example: "4:0 5:1 6:3"
|
||||
cpu_core_map = ""
|
||||
|
||||
#* Which temperature scale to use, available values: "celsius", "fahrenheit", "kelvin" and "rankine".
|
||||
temp_scale = "celsius"
|
||||
|
||||
#* Use base 10 for bits/bytes sizes, KB = 1000 instead of KiB = 1024.
|
||||
base_10_sizes = False
|
||||
|
||||
#* Show CPU frequency.
|
||||
show_cpu_freq = True
|
||||
|
||||
#* Draw a clock at top of screen, formatting according to strftime, empty string to disable.
|
||||
#* Special formatting: /host = hostname | /user = username | /uptime = system uptime
|
||||
clock_format = "%X"
|
||||
|
||||
#* Update main ui in background when menus are showing, set this to false if the menus is flickering too much for comfort.
|
||||
background_update = True
|
||||
|
||||
#* Custom cpu model name, empty string to disable.
|
||||
custom_cpu_name = ""
|
||||
|
||||
#* Optional filter for shown disks, should be full path of a mountpoint, separate multiple values with whitespace " ".
|
||||
#* Begin line with "exclude=" to change to exclude filter, otherwise defaults to "most include" filter. Example: disks_filter="exclude=/boot /home/user".
|
||||
disks_filter = ""
|
||||
|
||||
#* Show graphs instead of meters for memory values.
|
||||
mem_graphs = True
|
||||
|
||||
#* Show mem box below net box instead of above.
|
||||
mem_below_net = False
|
||||
|
||||
#* Count ZFS ARC in cached and available memory.
|
||||
zfs_arc_cached = True
|
||||
|
||||
#* If swap memory should be shown in memory box.
|
||||
show_swap = True
|
||||
|
||||
#* Show swap as a disk, ignores show_swap value above, inserts itself after first disk.
|
||||
swap_disk = True
|
||||
|
||||
#* If mem box should be split to also show disks info.
|
||||
show_disks = True
|
||||
|
||||
#* Filter out non physical disks. Set this to False to include network disks, RAM disks and similar.
|
||||
only_physical = True
|
||||
|
||||
#* Read disks list from /etc/fstab. This also disables only_physical.
|
||||
use_fstab = True
|
||||
|
||||
#* Setting this to True will hide all datasets, and only show ZFS pools. (IO stats will be calculated per-pool)
|
||||
zfs_hide_datasets = False
|
||||
|
||||
#* Set to true to show available disk space for privileged users.
|
||||
disk_free_priv = False
|
||||
|
||||
#* Toggles if io activity % (disk busy time) should be shown in regular disk usage view.
|
||||
show_io_stat = True
|
||||
|
||||
#* Toggles io mode for disks, showing big graphs for disk read/write speeds.
|
||||
io_mode = False
|
||||
|
||||
#* Set to True to show combined read/write io graphs in io mode.
|
||||
io_graph_combined = False
|
||||
|
||||
#* Set the top speed for the io graphs in MiB/s (100 by default), use format "mountpoint:speed" separate disks with whitespace " ".
|
||||
#* Example: "/mnt/media:100 /:20 /boot:1".
|
||||
io_graph_speeds = ""
|
||||
|
||||
#* Set fixed values for network graphs in Mebibits. Is only used if net_auto is also set to False.
|
||||
net_download = 100
|
||||
|
||||
net_upload = 100
|
||||
|
||||
#* Use network graphs auto rescaling mode, ignores any values set above and rescales down to 10 Kibibytes at the lowest.
|
||||
net_auto = True
|
||||
|
||||
#* Sync the auto scaling for download and upload to whichever currently has the highest scale.
|
||||
net_sync = True
|
||||
|
||||
#* Starts with the Network Interface specified here.
|
||||
net_iface = ""
|
||||
|
||||
#* Show battery stats in top right if battery is present.
|
||||
show_battery = True
|
||||
|
||||
#* Which battery to use if multiple are present. "Auto" for auto detection.
|
||||
selected_battery = "Auto"
|
||||
|
||||
#* Set loglevel for "~/.config/btop/btop.log" levels are: "ERROR" "WARNING" "INFO" "DEBUG".
|
||||
#* The level set includes all lower levels, i.e. "DEBUG" will show all logging info.
|
||||
log_level = "WARNING"
|
||||
|
||||
#* Measure PCIe throughput on NVIDIA cards, may impact performance on certain cards.
|
||||
nvml_measure_pcie_speeds = True
|
||||
|
||||
#* Horizontally mirror the GPU graph.
|
||||
gpu_mirror_graph = True
|
||||
|
||||
#* Custom gpu0 model name, empty string to disable.
|
||||
custom_gpu_name0 = ""
|
||||
|
||||
#* Custom gpu1 model name, empty string to disable.
|
||||
custom_gpu_name1 = ""
|
||||
|
||||
#* Custom gpu2 model name, empty string to disable.
|
||||
custom_gpu_name2 = ""
|
||||
|
||||
#* Custom gpu3 model name, empty string to disable.
|
||||
custom_gpu_name3 = ""
|
||||
|
||||
#* Custom gpu4 model name, empty string to disable.
|
||||
custom_gpu_name4 = ""
|
||||
|
||||
#* Custom gpu5 model name, empty string to disable.
|
||||
custom_gpu_name5 = ""
|
||||
|
||||
15
features/apps/chromium/config/Default/Preferences
Normal file
15
features/apps/chromium/config/Default/Preferences
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"extensions": {
|
||||
"theme": {
|
||||
"id": "",
|
||||
"use_system": false,
|
||||
"use_custom": false
|
||||
}
|
||||
},
|
||||
"browser": {
|
||||
"theme": {
|
||||
"color_scheme": 2,
|
||||
"user_color": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
1
features/apps/elephant/config/calc.toml
Normal file
1
features/apps/elephant/config/calc.toml
Normal file
@@ -0,0 +1 @@
|
||||
async = false
|
||||
3
features/apps/elephant/config/desktopapplications.toml
Normal file
3
features/apps/elephant/config/desktopapplications.toml
Normal file
@@ -0,0 +1,3 @@
|
||||
show_actions = false
|
||||
only_search_title = true
|
||||
history = false
|
||||
1
features/apps/elephant/config/symbols.toml
Normal file
1
features/apps/elephant/config/symbols.toml
Normal file
@@ -0,0 +1 @@
|
||||
command = 'wl-copy && hyprctl dispatch sendshortcut "SHIFT, Insert,"'
|
||||
37
features/apps/ghostty/config/config
Normal file
37
features/apps/ghostty/config/config
Normal file
@@ -0,0 +1,37 @@
|
||||
# Dynamic theme colors
|
||||
config-file = ?"~/.config/nomarchy/current/theme/ghostty.conf"
|
||||
|
||||
# Font
|
||||
font-family = "JetBrainsMono Nerd Font"
|
||||
font-style = Regular
|
||||
font-size = 9
|
||||
|
||||
# Window
|
||||
window-theme = ghostty
|
||||
window-padding-x = 14
|
||||
window-padding-y = 14
|
||||
confirm-close-surface=false
|
||||
resize-overlay = never
|
||||
gtk-toolbar-style = flat
|
||||
|
||||
# Cursor styling
|
||||
cursor-style = "block"
|
||||
cursor-style-blink = false
|
||||
|
||||
# Cursor styling + SSH session terminfo
|
||||
# (all shell integration options must be passed together)
|
||||
shell-integration-features = no-cursor,ssh-env
|
||||
|
||||
# Keyboard bindings
|
||||
keybind = shift+insert=paste_from_clipboard
|
||||
keybind = control+insert=copy_to_clipboard
|
||||
keybind = super+control+shift+alt+arrow_down=resize_split:down,100
|
||||
keybind = super+control+shift+alt+arrow_up=resize_split:up,100
|
||||
keybind = super+control+shift+alt+arrow_left=resize_split:left,100
|
||||
keybind = super+control+shift+alt+arrow_right=resize_split:right,100
|
||||
|
||||
# Slowdown mouse scrolling
|
||||
mouse-scroll-multiplier = 0.95
|
||||
|
||||
# Fix general slowness on hyprland (https://github.com/ghostty-org/ghostty/discussions/3224)
|
||||
async-backend = epoll
|
||||
30
features/apps/kitty/config/kitty.conf
Normal file
30
features/apps/kitty/config/kitty.conf
Normal file
@@ -0,0 +1,30 @@
|
||||
include ~/.config/nomarchy/current/theme/kitty.conf
|
||||
|
||||
# Font
|
||||
font_family JetBrainsMono Nerd Font
|
||||
bold_italic_font auto
|
||||
font_size 9.0
|
||||
|
||||
# Window
|
||||
window_padding_width 14
|
||||
hide_window_decorations yes
|
||||
confirm_os_window_close 0
|
||||
|
||||
# Keybindings
|
||||
map ctrl+insert copy_to_clipboard
|
||||
map shift+insert paste_from_clipboard
|
||||
|
||||
# Allow remote access
|
||||
allow_remote_control yes
|
||||
|
||||
# Aesthetics
|
||||
cursor_shape block
|
||||
cursor_blink_interval 0
|
||||
shell_integration no-cursor
|
||||
enable_audio_bell no
|
||||
|
||||
# Minimal Tab bar styling
|
||||
tab_bar_edge bottom
|
||||
tab_bar_style powerline
|
||||
tab_powerline_style slanted
|
||||
tab_title_template {title}{' :{}:'.format(num_windows) if num_windows > 1 else ''}
|
||||
0
features/apps/lazygit/config/config.yml
Normal file
0
features/apps/lazygit/config/config.yml
Normal file
25
features/apps/makima.nix
Normal file
25
features/apps/makima.nix
Normal file
@@ -0,0 +1,25 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.nomarchy.system.features.makima;
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg {
|
||||
# If the user has makima-bin available in their overlays (as they originally used a custom package),
|
||||
# this will install it. Otherwise, it will fail evaluation if not available in nixpkgs.
|
||||
environment.systemPackages = [ pkgs.makima-bin ];
|
||||
|
||||
environment.etc."makima/AT Translated Set 2 keyboard.toml".source = ../../assets/makima + "/AT Translated Set 2 keyboard.toml";
|
||||
|
||||
systemd.services.makima = {
|
||||
description = "Makima key remapping service";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
User = config.services.displayManager.autoLogin.user;
|
||||
Environment = "MAKIMA_CONFIG=/etc/makima";
|
||||
ExecStart = "${pkgs.makima-bin}/bin/makima";
|
||||
Restart = "on-failure";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
7
features/apps/makima/AT Translated Set 2 keyboard.toml
Normal file
7
features/apps/makima/AT Translated Set 2 keyboard.toml
Normal file
@@ -0,0 +1,7 @@
|
||||
# Run nomarchy-restart-makima after any changes
|
||||
|
||||
[remap]
|
||||
KEY_LEFTMETA-KEY_LEFTSHIFT-KEY_F23 = ["KEY_LEFTMETA", "KEY_LEFTALT", "KEY_SPACE"]
|
||||
|
||||
[settings]
|
||||
GRAB_DEVICE = "true"
|
||||
5
features/apps/opencode/config/opencode.json
Normal file
5
features/apps/opencode/config/opencode.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"theme": "system",
|
||||
"autoupdate": false
|
||||
}
|
||||
5
features/apps/scripts/nomarchy-launch-about
Executable file
5
features/apps/scripts/nomarchy-launch-about
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Launch the fastfetch TUI that gives information about the current system.
|
||||
|
||||
exec nomarchy-launch-or-focus-tui "bash -c 'fastfetch; read -n 1 -s'"
|
||||
5
features/apps/scripts/nomarchy-launch-audio
Executable file
5
features/apps/scripts/nomarchy-launch-audio
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Launch the Nomarchy audio controls TUI (provided by wiremix).
|
||||
|
||||
nomarchy-launch-or-focus-tui wiremix
|
||||
7
features/apps/scripts/nomarchy-launch-bluetooth
Executable file
7
features/apps/scripts/nomarchy-launch-bluetooth
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Launch the Nomarchy bluetooth controls TUI (provided by bluetui).
|
||||
# Also attempts to unblock bluetooth service if rfkill had blocked it.
|
||||
|
||||
rfkill unblock bluetooth
|
||||
exec nomarchy-launch-or-focus-tui bluetui
|
||||
17
features/apps/scripts/nomarchy-launch-browser
Executable file
17
features/apps/scripts/nomarchy-launch-browser
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Launch the default browser as determined by xdg-settings.
|
||||
# Automatically converts --private into the correct flag for the given browser.
|
||||
|
||||
default_browser=$(xdg-settings get default-web-browser)
|
||||
browser_exec=$(sed -n 's/^Exec=\([^ ]*\).*/\1/p' {~/.local,~/.nix-profile,/usr}/share/applications/$default_browser 2>/dev/null | head -1)
|
||||
|
||||
if $browser_exec --help | grep -q MOZ_LOG; then
|
||||
private_flag="--private-window"
|
||||
elif [[ $browser_exec =~ edge ]]; then
|
||||
private_flag="--inprivate"
|
||||
else
|
||||
private_flag="--incognito"
|
||||
fi
|
||||
|
||||
exec setsid uwsm-app -- "$browser_exec" "${@/--private/$private_flag}"
|
||||
15
features/apps/scripts/nomarchy-launch-editor
Executable file
15
features/apps/scripts/nomarchy-launch-editor
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Launch the default editor as determined by $EDITOR (set via ~/.config/uwsm/default) (or nvim if missing).
|
||||
# Starts suitable editors in a terminal window and otherwise as a regular application.
|
||||
|
||||
nomarchy-cmd-present "$EDITOR" || EDITOR=nvim
|
||||
|
||||
case "$EDITOR" in
|
||||
nvim | vim | nano | micro | hx | helix | fresh)
|
||||
exec nomarchy-launch-tui "$EDITOR" "$@"
|
||||
;;
|
||||
*)
|
||||
exec setsid uwsm-app -- "$EDITOR" "$@"
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Launch a floating terminal with the Nomarchy logo presentation, then execute the command passed in, and finally end with the nomarchy-show-done presentation.
|
||||
# Used by actions such as Update System.
|
||||
|
||||
cmd="$*"
|
||||
exec setsid uwsm-app -- xdg-terminal-exec --app-id=org.nomarchy.terminal --title=Nomarchy -e bash -c "nomarchy-show-logo; $cmd; if (( \$? != 130 )); then nomarchy-show-done; fi"
|
||||
19
features/apps/scripts/nomarchy-launch-or-focus
Executable file
19
features/apps/scripts/nomarchy-launch-or-focus
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Launch or focus on a given command identified by the passed in window-pattern.
|
||||
# Use by some default bindings, like the one for Spotify, to ensure there is only one instance of the application open.
|
||||
|
||||
if (($# == 0)); then
|
||||
echo "Usage: nomarchy-launch-or-focus [window-pattern] [launch-command]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
WINDOW_PATTERN="$1"
|
||||
LAUNCH_COMMAND="${2:-"uwsm-app -- $WINDOW_PATTERN"}"
|
||||
WINDOW_ADDRESS=$(hyprctl clients -j | jq -r --arg p "$WINDOW_PATTERN" '.[]|select((.class|test("\\b" + $p + "\\b";"i")) or (.title|test("\\b" + $p + "\\b";"i")))|.address' | head -n1)
|
||||
|
||||
if [[ -n $WINDOW_ADDRESS ]]; then
|
||||
hyprctl dispatch focuswindow "address:$WINDOW_ADDRESS"
|
||||
else
|
||||
eval exec setsid $LAUNCH_COMMAND
|
||||
fi
|
||||
9
features/apps/scripts/nomarchy-launch-or-focus-tui
Executable file
9
features/apps/scripts/nomarchy-launch-or-focus-tui
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Launch or focus on a given TUI identified by the passed in as the command.
|
||||
# Use by commands like nomarchy-launch-wifi to ensure there is only one wifi configuration screen open.
|
||||
|
||||
APP_ID="org.nomarchy.$(basename "$1")"
|
||||
LAUNCH_COMMAND="nomarchy-launch-tui $@"
|
||||
|
||||
exec nomarchy-launch-or-focus "$APP_ID" "$LAUNCH_COMMAND"
|
||||
15
features/apps/scripts/nomarchy-launch-or-focus-webapp
Executable file
15
features/apps/scripts/nomarchy-launch-or-focus-webapp
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Launch or focus on a given web app identified by the window-pattern.
|
||||
# Use by some default bindings, like the one for WhatsApp, to ensure there is only one instance of the application open.
|
||||
|
||||
if (($# == 0)); then
|
||||
echo "Usage: nomarchy-launch-or-focus-webapp [window-pattern] [url-and-flags...]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
WINDOW_PATTERN="$1"
|
||||
shift
|
||||
LAUNCH_COMMAND="nomarchy-launch-webapp $@"
|
||||
|
||||
exec nomarchy-launch-or-focus "$WINDOW_PATTERN" "$LAUNCH_COMMAND"
|
||||
56
features/apps/scripts/nomarchy-launch-screensaver
Executable file
56
features/apps/scripts/nomarchy-launch-screensaver
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Launch the Nomarchy screensaver in the default terminal on the system with the correct font configuration.
|
||||
|
||||
# Exit early if we don't have the tte show
|
||||
if ! command -v tte &>/dev/null; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Exit early if screensave is already running
|
||||
pgrep -f org.nomarchy.screensaver && exit 0
|
||||
|
||||
# Allow screensaver to be turned off but also force started
|
||||
# Skip if screensaver is disabled in configuration
|
||||
if [[ $NNOMARCHY_TOGGLE_SCREENSAVER == "false" ]] && [[ $1 != "force" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
# Silently quit Walker on overlay
|
||||
walker -q
|
||||
|
||||
focused=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true).name')
|
||||
terminal=$(xdg-terminal-exec --print-id)
|
||||
|
||||
for m in $(hyprctl monitors -j | jq -r '.[] | .name'); do
|
||||
hyprctl dispatch focusmonitor $m
|
||||
|
||||
case $terminal in
|
||||
*Alacritty*)
|
||||
hyprctl dispatch exec -- \
|
||||
alacritty --class=org.nomarchy.screensaver \
|
||||
--config-file ~/.local/share/nomarchy/default/alacritty/screensaver.toml \
|
||||
-e nomarchy-cmd-screensaver
|
||||
;;
|
||||
*ghostty*)
|
||||
hyprctl dispatch exec -- \
|
||||
ghostty --class=org.nomarchy.screensaver \
|
||||
--config-file=~/.local/share/nomarchy/default/ghostty/screensaver \
|
||||
--font-size=18 \
|
||||
-e nomarchy-cmd-screensaver
|
||||
;;
|
||||
*kitty*)
|
||||
hyprctl dispatch exec -- \
|
||||
kitty --class=org.nomarchy.screensaver \
|
||||
--override font_size=18 \
|
||||
--override window_padding_width=0 \
|
||||
-e nomarchy-cmd-screensaver
|
||||
;;
|
||||
*)
|
||||
notify-send -u low "✋ Screensaver only runs in Alacritty, Ghostty, or Kitty"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
hyprctl dispatch focusmonitor $focused
|
||||
5
features/apps/scripts/nomarchy-launch-tui
Executable file
5
features/apps/scripts/nomarchy-launch-tui
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Launch the TUI command passed in as an argument in the default terminal with an org.nomarchy.COMMAND app id for styling.
|
||||
|
||||
exec setsid uwsm-app -- xdg-terminal-exec --app-id=org.nomarchy.$(basename $1) -e "$1" "${@:2}"
|
||||
15
features/apps/scripts/nomarchy-launch-walker
Executable file
15
features/apps/scripts/nomarchy-launch-walker
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Launch the Walker application launcher while ensuring that it's data provider (called elephant) is running first.
|
||||
|
||||
# Ensure elephant is running before launching walker
|
||||
if ! pgrep -x elephant > /dev/null; then
|
||||
setsid uwsm-app -- elephant &
|
||||
fi
|
||||
|
||||
# Ensure walker service is running
|
||||
if ! pgrep -f "walker --gapplication-service" > /dev/null; then
|
||||
setsid uwsm-app -- walker --gapplication-service &
|
||||
fi
|
||||
|
||||
exec walker --width 644 --maxheight 300 --minheight 300 "$@"
|
||||
12
features/apps/scripts/nomarchy-launch-webapp
Executable file
12
features/apps/scripts/nomarchy-launch-webapp
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Launch the passed in URL as a web app in the default browser (or chromium if the default doesn't support --app).
|
||||
|
||||
browser=$(xdg-settings get default-web-browser)
|
||||
|
||||
case $browser in
|
||||
google-chrome* | brave-browser* | microsoft-edge* | opera* | vivaldi* | helium*) ;;
|
||||
*) browser="chromium.desktop" ;;
|
||||
esac
|
||||
|
||||
exec setsid uwsm-app -- $(sed -n 's/^Exec=\([^ ]*\).*/\1/p' {~/.local,~/.nix-profile,/usr}/share/applications/$browser 2>/dev/null | head -1) --app="$1" "${@:2}"
|
||||
7
features/apps/scripts/nomarchy-launch-wifi
Executable file
7
features/apps/scripts/nomarchy-launch-wifi
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Launch the Nomarchy wifi controls (provided by the Impala TUI).
|
||||
# Attempts to unblock the wifi service first in case it should be been blocked.
|
||||
|
||||
rfkill unblock wifi
|
||||
nomarchy-launch-or-focus-tui impala
|
||||
7
features/apps/scripts/nomarchy-restart-app
Executable file
7
features/apps/scripts/nomarchy-restart-app
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Restart an application by killing it and relaunching via uwsm.
|
||||
# Usage: nomarchy-restart-app <application-name> [application-args...]
|
||||
|
||||
pkill -x $1
|
||||
setsid uwsm-app -- "$@" >/dev/null 2>&1 &
|
||||
5
features/apps/scripts/nomarchy-restart-btop
Executable file
5
features/apps/scripts/nomarchy-restart-btop
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Reload btop configuration (used by the Nomarchy theme switching).
|
||||
|
||||
pkill -SIGUSR2 btop
|
||||
7
features/apps/scripts/nomarchy-restart-opencode
Executable file
7
features/apps/scripts/nomarchy-restart-opencode
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Reload opencode configuration (used by the Nomarchy theme switching).
|
||||
|
||||
if pgrep -x opencode >/dev/null; then
|
||||
killall -SIGUSR2 opencode
|
||||
fi
|
||||
13
features/apps/scripts/nomarchy-restart-terminal
Executable file
13
features/apps/scripts/nomarchy-restart-terminal
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ -f ~/.config/alacritty/alacritty.toml ]]; then
|
||||
touch ~/.config/alacritty/alacritty.toml
|
||||
fi
|
||||
|
||||
if pgrep -x kitty >/dev/null; then
|
||||
killall -SIGUSR1 kitty >/dev/null
|
||||
fi
|
||||
|
||||
if pgrep -x ghostty >/dev/null; then
|
||||
killall -SIGUSR2 ghostty
|
||||
fi
|
||||
7
features/apps/scripts/nomarchy-restart-tmux
Executable file
7
features/apps/scripts/nomarchy-restart-tmux
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Restart tmux if running with the latest configuration
|
||||
|
||||
if pgrep -x tmux; then
|
||||
tmux source-file ~/.config/tmux/tmux.conf
|
||||
fi
|
||||
59
features/apps/scripts/nomarchy-tui-install
Executable file
59
features/apps/scripts/nomarchy-tui-install
Executable file
@@ -0,0 +1,59 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if (( $# != 4 )); then
|
||||
echo -e "\e[32mLet's create a TUI shortcut you can start with the app launcher.\n\e[0m"
|
||||
APP_NAME=$(gum input --prompt "Name> " --placeholder "My TUI")
|
||||
APP_EXEC=$(gum input --prompt "Launch Command> " --placeholder "lazydocker or bash -c 'dust; read -n 1 -s'")
|
||||
WINDOW_STYLE=$(gum choose --header "Window style" float tile)
|
||||
ICON_URL=$(gum input --prompt "Icon URL> " --placeholder "See https://dashboardicons.com (must use PNG or SVG!)")
|
||||
else
|
||||
APP_NAME="$1"
|
||||
APP_EXEC="$2"
|
||||
WINDOW_STYLE="$3"
|
||||
ICON_URL="$4"
|
||||
fi
|
||||
|
||||
if [[ -z $APP_NAME || -z $APP_EXEC || -z $ICON_URL ]]; then
|
||||
echo "You must set app name, app command, and icon URL!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ICON_DIR="$HOME/.local/share/applications/icons"
|
||||
DESKTOP_FILE="$HOME/.local/share/applications/$APP_NAME.desktop"
|
||||
|
||||
if [[ ! $ICON_URL =~ ^https?:// ]] && [[ -f $ICON_URL ]]; then
|
||||
ICON_PATH="$ICON_URL"
|
||||
else
|
||||
ICON_PATH="$ICON_DIR/$APP_NAME.png"
|
||||
mkdir -p "$ICON_DIR"
|
||||
if ! curl -sL -o "$ICON_PATH" "$ICON_URL"; then
|
||||
echo "Error: Failed to download icon."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $WINDOW_STYLE == "float" ]]; then
|
||||
APP_CLASS="TUI.float"
|
||||
else
|
||||
APP_CLASS="TUI.tile"
|
||||
fi
|
||||
|
||||
cat >"$DESKTOP_FILE" <<EOF
|
||||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Name=$APP_NAME
|
||||
Comment=$APP_NAME
|
||||
Exec=xdg-terminal-exec --app-id=$APP_CLASS -e $APP_EXEC
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Icon=$ICON_PATH
|
||||
StartupNotify=true
|
||||
EOF
|
||||
|
||||
chmod +x "$DESKTOP_FILE"
|
||||
|
||||
if (( $# != 4 )); then
|
||||
echo -e "You can now find $APP_NAME using the app launcher (SUPER + SPACE)\n"
|
||||
fi
|
||||
43
features/apps/scripts/nomarchy-tui-remove
Executable file
43
features/apps/scripts/nomarchy-tui-remove
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
ICON_DIR="$HOME/.local/share/applications/icons"
|
||||
DESKTOP_DIR="$HOME/.local/share/applications/"
|
||||
|
||||
if (( $# == 0 )); then
|
||||
# Find all TUIs
|
||||
while IFS= read -r -d '' file; do
|
||||
if grep -qE '^Exec=.*(\$TERMINAL|xdg-terminal-exec).*-e' "$file"; then
|
||||
TUIS+=("$(basename "${file%.desktop}")")
|
||||
fi
|
||||
done < <(find "$DESKTOP_DIR" -name '*.desktop' -print0)
|
||||
|
||||
if ((${#TUIS[@]})); then
|
||||
IFS=$'\n' SORTED_TUIS=($(sort <<<"${TUIS[*]}"))
|
||||
unset IFS
|
||||
APP_NAMES_STRING=$(gum choose --no-limit --header "Select TUI to remove..." --selected-prefix="✗ " "${SORTED_TUIS[@]}")
|
||||
# Convert newline-separated string to array
|
||||
APP_NAMES=()
|
||||
while IFS= read -r line; do
|
||||
[[ -n $line ]] && APP_NAMES+=("$line")
|
||||
done <<< "$APP_NAMES_STRING"
|
||||
else
|
||||
echo "No TUIs to remove."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Use array to preserve spaces in app names
|
||||
APP_NAMES=("$@")
|
||||
fi
|
||||
|
||||
if (( ${#APP_NAMES[@]} == 0 )); then
|
||||
echo "You must provide TUI names."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for APP_NAME in "${APP_NAMES[@]}"; do
|
||||
rm -f "$DESKTOP_DIR/$APP_NAME.desktop"
|
||||
rm -f "$ICON_DIR/$APP_NAME.png"
|
||||
echo "Removed $APP_NAME"
|
||||
done
|
||||
36
features/apps/scripts/nomarchy-tui-remove-all
Executable file
36
features/apps/scripts/nomarchy-tui-remove-all
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Remove all TUIs installed via nomarchy-tui-install.
|
||||
# Identifies TUIs by their Exec pattern (xdg-terminal-exec --app-id=TUI.).
|
||||
|
||||
set -e
|
||||
|
||||
APP_DIR="${1:-$HOME/.local/share/applications}"
|
||||
ICON_DIR="$HOME/.local/share/applications/icons"
|
||||
|
||||
echo "Scanning for TUIs in $APP_DIR..."
|
||||
|
||||
tui_desktop_files=()
|
||||
while IFS= read -r -d '' file; do
|
||||
if grep -q "Exec=xdg-terminal-exec --app-id=TUI\." "$file" 2>/dev/null; then
|
||||
tui_desktop_files+=("$file")
|
||||
fi
|
||||
done < <(find "$APP_DIR" -maxdepth 1 -name "*.desktop" -print0 2>/dev/null)
|
||||
|
||||
if (( ${#tui_desktop_files[@]} == 0 )); then
|
||||
echo "No TUIs found."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for file in "${tui_desktop_files[@]}"; do
|
||||
app_name=$(basename "$file" .desktop)
|
||||
echo "Removing TUI: $app_name"
|
||||
rm -f "$file"
|
||||
rm -f "$ICON_DIR/$app_name.png"
|
||||
done
|
||||
|
||||
if command -v update-desktop-database &>/dev/null; then
|
||||
update-desktop-database "$APP_DIR" &>/dev/null || true
|
||||
fi
|
||||
|
||||
echo "TUIs removed successfully."
|
||||
6
features/apps/scripts/nomarchy-voxtype-config
Executable file
6
features/apps/scripts/nomarchy-voxtype-config
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Used by Voxtype waybar module to open config on right click
|
||||
|
||||
exec nomarchy-launch-editor ~/.config/voxtype/config.toml
|
||||
21
features/apps/scripts/nomarchy-voxtype-install
Executable file
21
features/apps/scripts/nomarchy-voxtype-install
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Install voxtype and configure it for use.
|
||||
|
||||
if gum confirm "Install Voxtype + AI model (~150MB) to enable dictation?"; then
|
||||
nomarchy-pkg-add wtype voxtype-bin
|
||||
|
||||
# Setup voxtype
|
||||
mkdir -p ~/.config/voxtype
|
||||
cp ~/.config/nomarchy/default/voxtype/config.toml ~/.config/voxtype/
|
||||
|
||||
voxtype setup --download --no-post-install
|
||||
if nomarchy-hw-vulkan; then
|
||||
voxtype setup gpu --enable || true
|
||||
fi
|
||||
voxtype setup systemd
|
||||
|
||||
nomarchy-restart-waybar
|
||||
notify-send " Voxtype Dictation Ready" "Press Super + Ctrl + X to toggle dictation.\nEdit ~/.config/voxtype/config.toml for options." -t 10000
|
||||
fi
|
||||
5
features/apps/scripts/nomarchy-voxtype-model
Executable file
5
features/apps/scripts/nomarchy-voxtype-model
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
nomarchy-launch-floating-terminal-with-presentation "voxtype setup model"
|
||||
nomarchy-restart-waybar
|
||||
20
features/apps/scripts/nomarchy-voxtype-remove
Executable file
20
features/apps/scripts/nomarchy-voxtype-remove
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Remove voxtype and its configurations.
|
||||
|
||||
if nomarchy-cmd-present voxtype; then
|
||||
echo "Uninstall Voxtype to remove dictation."
|
||||
|
||||
# Remove services
|
||||
systemctl --user stop voxtype.service 2>/dev/null || true
|
||||
rm -f ~/.config/systemd/user/voxtype*
|
||||
systemctl --user daemon-reload
|
||||
|
||||
# Remove packages and configs
|
||||
nomarchy-pkg-drop wtype voxtype-bin
|
||||
rm -rf ~/.config/voxtype
|
||||
rm -rf ~/.local/share/voxtype
|
||||
else
|
||||
echo "Voxtype was not installed."
|
||||
fi
|
||||
9
features/apps/scripts/nomarchy-voxtype-status
Executable file
9
features/apps/scripts/nomarchy-voxtype-status
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
if nomarchy-cmd-present voxtype; then
|
||||
voxtype status --follow --extended --format json | while read -r line; do
|
||||
echo "$line" | jq -c '. + {alt: .class}'
|
||||
done
|
||||
else
|
||||
echo '{"alt": "", "tooltip": ""}'
|
||||
fi
|
||||
11
features/apps/scripts/nomarchy-webapp-handler-hey
Executable file
11
features/apps/scripts/nomarchy-webapp-handler-hey
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
url="$1"
|
||||
web_url="https://app.hey.com"
|
||||
|
||||
# Handle mailto: URLs
|
||||
if [[ $url =~ ^mailto: ]]; then
|
||||
email=$(echo "$url" | sed 's/mailto://')
|
||||
web_url="https://app.hey.com/messages/new?to=$email"
|
||||
fi
|
||||
|
||||
exec nomarchy-launch-webapp "$web_url"
|
||||
20
features/apps/scripts/nomarchy-webapp-handler-zoom
Executable file
20
features/apps/scripts/nomarchy-webapp-handler-zoom
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
url="$1"
|
||||
web_url="https://app.zoom.us/wc/home"
|
||||
|
||||
if [[ $url =~ ^zoom(mtg|us):// ]]; then
|
||||
confno=$(echo "$url" | sed -n 's/.*[?&]confno=\([^&]*\).*/\1/p')
|
||||
|
||||
if [[ -n $confno ]]; then
|
||||
pwd=$(echo "$url" | sed -n 's/.*[?&]pwd=\([^&]*\).*/\1/p')
|
||||
|
||||
if [[ -n $pwd ]]; then
|
||||
web_url="https://app.zoom.us/wc/join/$confno?pwd=$pwd"
|
||||
else
|
||||
web_url="https://app.zoom.us/wc/join/$confno"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
exec nomarchy-launch-webapp "$web_url"
|
||||
89
features/apps/scripts/nomarchy-webapp-install
Executable file
89
features/apps/scripts/nomarchy-webapp-install
Executable file
@@ -0,0 +1,89 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
ICON_DIR="$HOME/.local/share/applications/icons"
|
||||
|
||||
if (( $# < 3 )); then
|
||||
echo -e "\e[32mLet's create a new web app you can start with the app launcher.\n\e[0m"
|
||||
APP_NAME=$(gum input --prompt "Name> " --placeholder "My favorite web app")
|
||||
APP_URL=$(gum input --prompt "URL> " --placeholder "https://example.com")
|
||||
if [[ ! $APP_URL =~ ^[a-zA-Z][a-zA-Z0-9+.-]*: ]]; then
|
||||
APP_URL="https://$APP_URL"
|
||||
fi
|
||||
|
||||
# Try to fetch favicon automatically first.
|
||||
FAVICON_URL="https://www.google.com/s2/favicons?domain=${APP_URL}&sz=128"
|
||||
mkdir -p "$ICON_DIR"
|
||||
if curl -fsSL -o "$ICON_DIR/$APP_NAME.png" "$FAVICON_URL" && [[ -s $ICON_DIR/$APP_NAME.png ]]; then
|
||||
ICON_REF="$APP_NAME.png"
|
||||
else
|
||||
ICON_REF=$(gum input --prompt "Icon URL> " --placeholder "Could not fetch favicon automatically. Enter PNG icon URL (see https://dashboardicons.com)")
|
||||
fi
|
||||
|
||||
CUSTOM_EXEC=""
|
||||
MIME_TYPES=""
|
||||
INTERACTIVE_MODE=true
|
||||
else
|
||||
APP_NAME="$1"
|
||||
APP_URL="$2"
|
||||
if [[ ! $APP_URL =~ ^[a-zA-Z][a-zA-Z0-9+.-]*: ]]; then
|
||||
APP_URL="https://$APP_URL"
|
||||
fi
|
||||
ICON_REF="$3"
|
||||
CUSTOM_EXEC="$4" # Optional custom exec command
|
||||
MIME_TYPES="$5" # Optional mime types
|
||||
INTERACTIVE_MODE=false
|
||||
fi
|
||||
|
||||
# Ensure valid execution
|
||||
if [[ -z $APP_NAME || -z $APP_URL ]]; then
|
||||
echo "You must set app name and app URL!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Resolve icon from URL or from a local icon name.
|
||||
mkdir -p "$ICON_DIR"
|
||||
|
||||
if [[ -z $ICON_REF ]]; then
|
||||
ICON_REF="https://www.google.com/s2/favicons?domain=${APP_URL}&sz=128"
|
||||
fi
|
||||
|
||||
if [[ $ICON_REF =~ ^https?:// ]]; then
|
||||
ICON_PATH="$ICON_DIR/$APP_NAME.png"
|
||||
if ! curl -fsSL -o "$ICON_PATH" "$ICON_REF" || [[ ! -s $ICON_PATH ]]; then
|
||||
echo "Error: Failed to download icon."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
ICON_PATH="$ICON_DIR/$ICON_REF"
|
||||
fi
|
||||
|
||||
# Use custom exec if provided, otherwise default behavior
|
||||
EXEC_COMMAND="${CUSTOM_EXEC:-nomarchy-launch-webapp $APP_URL}"
|
||||
|
||||
# Create application .desktop file
|
||||
DESKTOP_FILE="$HOME/.local/share/applications/$APP_NAME.desktop"
|
||||
|
||||
cat >"$DESKTOP_FILE" <<EOF
|
||||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Name=$APP_NAME
|
||||
Comment=$APP_NAME
|
||||
Exec=$EXEC_COMMAND
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Icon=$ICON_PATH
|
||||
StartupNotify=true
|
||||
EOF
|
||||
|
||||
# Add mime types if provided
|
||||
if [[ -n $MIME_TYPES ]]; then
|
||||
echo "MimeType=$MIME_TYPES" >>"$DESKTOP_FILE"
|
||||
fi
|
||||
|
||||
chmod +x "$DESKTOP_FILE"
|
||||
|
||||
if [[ $INTERACTIVE_MODE == "true" ]]; then
|
||||
echo -e "You can now find $APP_NAME using the app launcher (SUPER + SPACE)\n"
|
||||
fi
|
||||
43
features/apps/scripts/nomarchy-webapp-remove
Executable file
43
features/apps/scripts/nomarchy-webapp-remove
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
ICON_DIR="$HOME/.local/share/applications/icons"
|
||||
DESKTOP_DIR="$HOME/.local/share/applications/"
|
||||
|
||||
if (( $# == 0 )); then
|
||||
# Find all web apps
|
||||
while IFS= read -r -d '' file; do
|
||||
if grep -q '^Exec=.*\(nomarchy-launch-webapp\|nomarchy-webapp-handler\).*' "$file"; then
|
||||
WEB_APPS+=("$(basename "${file%.desktop}")")
|
||||
fi
|
||||
done < <(find "$DESKTOP_DIR" -name '*.desktop' -print0)
|
||||
|
||||
if ((${#WEB_APPS[@]})); then
|
||||
IFS=$'\n' SORTED_WEB_APPS=($(sort <<<"${WEB_APPS[*]}"))
|
||||
unset IFS
|
||||
APP_NAMES_STRING=$(gum choose --no-limit --header "Select web app to remove..." --selected-prefix="✗ " "${SORTED_WEB_APPS[@]}")
|
||||
# Convert newline-separated string to array
|
||||
APP_NAMES=()
|
||||
while IFS= read -r line; do
|
||||
[[ -n $line ]] && APP_NAMES+=("$line")
|
||||
done <<< "$APP_NAMES_STRING"
|
||||
else
|
||||
echo "No web apps to remove."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Use array to preserve spaces in app names
|
||||
APP_NAMES=("$@")
|
||||
fi
|
||||
|
||||
if (( ${#APP_NAMES[@]} == 0 )); then
|
||||
echo "You must select at least one web app to remove."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for APP_NAME in "${APP_NAMES[@]}"; do
|
||||
rm -f "$DESKTOP_DIR/$APP_NAME.desktop"
|
||||
rm -f "$ICON_DIR/$APP_NAME.png"
|
||||
echo "Removed $APP_NAME"
|
||||
done
|
||||
36
features/apps/scripts/nomarchy-webapp-remove-all
Executable file
36
features/apps/scripts/nomarchy-webapp-remove-all
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Remove all web apps installed via nomarchy-webapp-install.
|
||||
# Identifies web apps by their Exec pattern (nomarchy-launch-webapp or nomarchy-webapp-handler).
|
||||
|
||||
set -e
|
||||
|
||||
APP_DIR="${1:-$HOME/.local/share/applications}"
|
||||
ICON_DIR="$HOME/.local/share/applications/icons"
|
||||
|
||||
echo "Scanning for web apps in $APP_DIR..."
|
||||
|
||||
webapp_desktop_files=()
|
||||
while IFS= read -r -d '' file; do
|
||||
if grep -q "Exec=nomarchy-launch-webapp\|Exec=nomarchy-webapp-handler" "$file" 2>/dev/null; then
|
||||
webapp_desktop_files+=("$file")
|
||||
fi
|
||||
done < <(find "$APP_DIR" -maxdepth 1 -name "*.desktop" -print0 2>/dev/null)
|
||||
|
||||
if (( ${#webapp_desktop_files[@]} == 0 )); then
|
||||
echo "No web apps found."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for file in "${webapp_desktop_files[@]}"; do
|
||||
app_name=$(basename "$file" .desktop)
|
||||
echo "Removing web app: $app_name"
|
||||
rm -f "$file"
|
||||
rm -f "$ICON_DIR/$app_name.png"
|
||||
done
|
||||
|
||||
if command -v update-desktop-database &>/dev/null; then
|
||||
update-desktop-database "$APP_DIR" &>/dev/null || true
|
||||
fi
|
||||
|
||||
echo "Web apps removed successfully."
|
||||
448
features/apps/scripts/nomarchy-windows-vm
Executable file
448
features/apps/scripts/nomarchy-windows-vm
Executable file
@@ -0,0 +1,448 @@
|
||||
#!/bin/bash
|
||||
COMPOSE_FILE="$HOME/.config/windows/docker-compose.yml"
|
||||
|
||||
check_prerequisites() {
|
||||
local DISK_SIZE_GB=${1:-64}
|
||||
local REQUIRED_SPACE=$((DISK_SIZE_GB + 10)) # Add 10GB for Windows ISO and overhead
|
||||
|
||||
# Check for KVM support
|
||||
if [[ ! -e /dev/kvm ]]; then
|
||||
gum style \
|
||||
--border normal \
|
||||
--padding "1 2" \
|
||||
--margin "1" \
|
||||
"❌ KVM virtualization not available!" \
|
||||
"" \
|
||||
"Please enable virtualization in BIOS or run:" \
|
||||
" sudo modprobe kvm-intel # for Intel CPUs" \
|
||||
" sudo modprobe kvm-amd # for AMD CPUs"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check disk space
|
||||
AVAILABLE_SPACE=$(df "$HOME" | awk 'NR==2 {print int($4/1024/1024)}')
|
||||
if (( AVAILABLE_SPACE < REQUIRED_SPACE )); then
|
||||
echo "❌ Insufficient disk space!"
|
||||
echo " Available: ${AVAILABLE_SPACE}GB"
|
||||
echo " Required: ${REQUIRED_SPACE}GB (${DISK_SIZE_GB}GB disk + 10GB for Windows image)"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
install_windows() {
|
||||
# Set up trap to handle Ctrl+C
|
||||
trap "echo ''; echo 'Installation cancelled by user'; exit 1" INT
|
||||
|
||||
check_prerequisites
|
||||
|
||||
nomarchy-pkg-add freerdp openbsd-netcat gum
|
||||
|
||||
mkdir -p "$HOME/.windows"
|
||||
mkdir -p "$HOME/.config/windows"
|
||||
mkdir -p "$HOME/.local/share/applications/icons"
|
||||
|
||||
# Install Windows VM icon and desktop file
|
||||
if [[ -f $NOMARCHY_PATH/applications/icons/windows.png ]]; then
|
||||
cp "$NOMARCHY_PATH/applications/icons/windows.png" "$HOME/.local/share/applications/icons/windows.png"
|
||||
fi
|
||||
|
||||
cat << EOF | tee "$HOME/.local/share/applications/windows-vm.desktop" > /dev/null
|
||||
[Desktop Entry]
|
||||
Name=Windows
|
||||
Comment=Start Windows VM via Docker and connect with RDP
|
||||
Exec=uwsm app -- nomarchy-windows-vm launch
|
||||
Icon=$HOME/.local/share/applications/icons/windows.png
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=System;Virtualization;
|
||||
EOF
|
||||
|
||||
# Get system resources
|
||||
TOTAL_RAM=$(free -h | awk 'NR==2 {print $2}')
|
||||
TOTAL_RAM_GB=$(awk 'NR==1 {printf "%d", $2/1024/1024}' /proc/meminfo)
|
||||
TOTAL_CORES=$(nproc)
|
||||
|
||||
echo ""
|
||||
echo "System Resources Detected:"
|
||||
echo " Total RAM: $TOTAL_RAM"
|
||||
echo " Total CPU Cores: $TOTAL_CORES"
|
||||
echo ""
|
||||
|
||||
RAM_OPTIONS=""
|
||||
for size in 2 4 8 16 32 64; do
|
||||
if (( size <= TOTAL_RAM_GB )); then
|
||||
RAM_OPTIONS="$RAM_OPTIONS ${size}G"
|
||||
fi
|
||||
done
|
||||
|
||||
SELECTED_RAM=$(echo $RAM_OPTIONS | tr ' ' '\n' | gum choose --selected="4G" --header="How much RAM would you like to allocate to Windows VM?")
|
||||
|
||||
# Check if user cancelled
|
||||
if [[ -z $SELECTED_RAM ]]; then
|
||||
echo "Installation cancelled by user"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SELECTED_CORES=$(gum input --placeholder="Number of CPU cores (1-$TOTAL_CORES)" --value="2" --header="How many CPU cores would you like to allocate to Windows VM?" --char-limit=2)
|
||||
|
||||
# Check if user cancelled (Ctrl+C in gum input returns empty string)
|
||||
if [[ -z $SELECTED_CORES ]]; then
|
||||
echo "Installation cancelled by user"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [[ $SELECTED_CORES =~ ^[0-9]+$ ]] || (( SELECTED_CORES < 1 )) || (( SELECTED_CORES > TOTAL_CORES )); then
|
||||
echo "Invalid input. Using default: 2 cores"
|
||||
SELECTED_CORES=2
|
||||
fi
|
||||
|
||||
AVAILABLE_SPACE=$(df "$HOME" | awk 'NR==2 {print int($4/1024/1024)}')
|
||||
MAX_DISK_GB=$((AVAILABLE_SPACE - 10)) # Leave 10GB for Windows image
|
||||
|
||||
# Check if we have enough space for minimum
|
||||
if (( MAX_DISK_GB < 32 )); then
|
||||
echo "❌ Insufficient disk space for Windows VM!"
|
||||
echo " Available: ${AVAILABLE_SPACE}GB"
|
||||
echo " Minimum required: 42GB (32GB disk + 10GB for Windows image)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DISK_OPTIONS=""
|
||||
for size in 32 64 128 256 512; do
|
||||
if (( size <= MAX_DISK_GB )); then
|
||||
DISK_OPTIONS="$DISK_OPTIONS ${size}G"
|
||||
fi
|
||||
done
|
||||
|
||||
# Default to 64G if available, otherwise 32G
|
||||
DEFAULT_DISK="64G"
|
||||
if ! echo "$DISK_OPTIONS" | grep -q "64G"; then
|
||||
DEFAULT_DISK="32G"
|
||||
fi
|
||||
|
||||
SELECTED_DISK=$(echo $DISK_OPTIONS | tr ' ' '\n' | gum choose --selected="$DEFAULT_DISK" --header="How much disk space would you like to give Windows VM? (64GB+ recommended)")
|
||||
|
||||
# Check if user cancelled
|
||||
if [[ -z $SELECTED_DISK ]]; then
|
||||
echo "Installation cancelled by user"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract just the number for prerequisite check
|
||||
DISK_SIZE_NUM=$(echo "$SELECTED_DISK" | sed 's/G//')
|
||||
|
||||
# Re-check prerequisites with selected disk size
|
||||
check_prerequisites "$DISK_SIZE_NUM"
|
||||
|
||||
# Prompt for username and password
|
||||
USERNAME=$(gum input --placeholder="Username (Press enter to use default: docker)" --header="Enter Windows username:")
|
||||
if [[ -z $USERNAME ]]; then
|
||||
USERNAME="docker"
|
||||
fi
|
||||
|
||||
PASSWORD=$(gum input --placeholder="Password (Press enter to use default: admin)" --password --header="Enter Windows password:")
|
||||
if [[ -z $PASSWORD ]]; then
|
||||
PASSWORD="admin"
|
||||
PASSWORD_DISPLAY="(default)"
|
||||
else
|
||||
PASSWORD_DISPLAY="(user-defined)"
|
||||
fi
|
||||
|
||||
# Display configuration summary
|
||||
gum style \
|
||||
--border normal \
|
||||
--padding "1 2" \
|
||||
--margin "1" \
|
||||
--align left \
|
||||
--bold \
|
||||
"Windows VM Configuration" \
|
||||
"" \
|
||||
"RAM: $SELECTED_RAM" \
|
||||
"CPU: $SELECTED_CORES cores" \
|
||||
"Disk: $SELECTED_DISK" \
|
||||
"Username: $USERNAME" \
|
||||
"Password: $PASSWORD_DISPLAY"
|
||||
|
||||
# Ask for confirmation
|
||||
echo ""
|
||||
if ! gum confirm "Proceed with this configuration?"; then
|
||||
echo "Installation cancelled by user"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p $HOME/Windows
|
||||
|
||||
# Create docker-compose.yml in user config directory
|
||||
cat << EOF | tee "$COMPOSE_FILE" > /dev/null
|
||||
services:
|
||||
windows:
|
||||
image: dockurr/windows
|
||||
container_name: nomarchy-windows
|
||||
environment:
|
||||
VERSION: "11"
|
||||
RAM_SIZE: "$SELECTED_RAM"
|
||||
CPU_CORES: "$SELECTED_CORES"
|
||||
DISK_SIZE: "$SELECTED_DISK"
|
||||
USERNAME: "$USERNAME"
|
||||
PASSWORD: "$PASSWORD"
|
||||
TZ: "$(timedatectl show -p Timezone --value 2>/dev/null || echo UTC)"
|
||||
ARGUMENTS: "-rtc base=localtime,clock=host,driftfix=slew"
|
||||
devices:
|
||||
- /dev/kvm
|
||||
- /dev/net/tun
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
ports:
|
||||
- 127.0.0.1:8006:8006
|
||||
- 127.0.0.1:3389:3389/tcp
|
||||
- 127.0.0.1:3389:3389/udp
|
||||
volumes:
|
||||
- $HOME/.windows:/storage
|
||||
- $HOME/Windows:/shared
|
||||
restart: unless-stopped
|
||||
stop_grace_period: 2m
|
||||
EOF
|
||||
|
||||
echo ""
|
||||
echo "Starting Windows VM installation..."
|
||||
echo "This will download a Windows 11 image (may take 10-15 minutes)."
|
||||
echo ""
|
||||
echo "Monitor installation progress at: http://127.0.0.1:8006"
|
||||
echo ""
|
||||
|
||||
# Start docker-compose with user's config
|
||||
echo "Starting Windows VM with docker-compose..."
|
||||
if ! docker-compose -f "$COMPOSE_FILE" up -d 2>&1; then
|
||||
echo "❌ Failed to start Windows VM!"
|
||||
echo " Common issues:"
|
||||
echo " - Docker daemon not running: sudo systemctl start docker"
|
||||
echo " - Port already in use: check if another VM is running"
|
||||
echo " - Permission issues: make sure you're in the docker group"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Windows VM is starting up!"
|
||||
echo ""
|
||||
echo "Opening browser to monitor installation..."
|
||||
|
||||
# Open browser to monitor installation
|
||||
sleep 3
|
||||
xdg-open "http://127.0.0.1:8006"
|
||||
|
||||
echo ""
|
||||
echo "Installation is running in the background."
|
||||
echo "You can monitor progress at: http://127.0.0.1:8006"
|
||||
echo ""
|
||||
echo "Once finished, launch 'Windows' via Super + Space"
|
||||
echo ""
|
||||
echo "To stop the VM: nomarchy-windows-vm stop"
|
||||
echo "To change resources: ~/.config/windows/docker-compose.yml"
|
||||
echo ""
|
||||
}
|
||||
|
||||
remove_windows() {
|
||||
if ! gum confirm --default=false "Remove Windows VM and delete all associated data?"; then
|
||||
echo "Removal cancelled by user"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Removing Windows VM..."
|
||||
|
||||
docker-compose -f "$COMPOSE_FILE" down 2>/dev/null || true
|
||||
|
||||
docker rmi dockurr/windows 2>/dev/null || echo "Image already removed or not found"
|
||||
|
||||
rm "$HOME/.local/share/applications/windows-vm.desktop"
|
||||
rm -rf "$HOME/.config/windows"
|
||||
rm -rf "$HOME/.windows"
|
||||
|
||||
echo ""
|
||||
echo "Windows VM removal completed!"
|
||||
}
|
||||
|
||||
launch_windows() {
|
||||
KEEP_ALIVE=false
|
||||
if [[ $1 = "--keep-alive" ]] || [[ $1 = "-k" ]]; then
|
||||
KEEP_ALIVE=true
|
||||
fi
|
||||
|
||||
# Check if config exists
|
||||
if [[ ! -f $COMPOSE_FILE ]]; then
|
||||
echo "Windows VM not configured. Please run: nomarchy-windows-vm install"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract credentials from compose file
|
||||
WIN_USER=$(grep "USERNAME:" "$COMPOSE_FILE" | sed 's/.*USERNAME: "\(.*\)"/\1/')
|
||||
WIN_PASS=$(grep "PASSWORD:" "$COMPOSE_FILE" | sed 's/.*PASSWORD: "\(.*\)"/\1/')
|
||||
|
||||
# Use defaults if not found
|
||||
[[ -z $WIN_USER ]] && WIN_USER="docker"
|
||||
[[ -z $WIN_PASS ]] && WIN_PASS="admin"
|
||||
|
||||
# Check if container is already running
|
||||
CONTAINER_STATUS=$(docker inspect --format='{{.State.Status}}' nomarchy-windows 2>/dev/null)
|
||||
|
||||
if [[ $CONTAINER_STATUS != "running" ]]; then
|
||||
echo "Starting Windows VM..."
|
||||
|
||||
# Send desktop notification
|
||||
notify-send " Starting Windows VM" " This can take 15-30 seconds" -t 15000
|
||||
|
||||
if ! docker-compose -f "$COMPOSE_FILE" up -d 2>&1; then
|
||||
echo "❌ Failed to start Windows VM!"
|
||||
echo " Try checking: nomarchy-windows-vm status"
|
||||
echo " View logs: docker logs nomarchy-windows"
|
||||
notify-send -u critical "Windows VM" "Failed to start Windows VM"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Waiting for Windows VM to start..."
|
||||
WAIT_COUNT=0
|
||||
until docker logs nomarchy-windows 2>&1 | grep -qi "windows started successfully"; do
|
||||
sleep 2
|
||||
WAIT_COUNT=$((WAIT_COUNT + 1))
|
||||
if (( WAIT_COUNT > 60 )); then # 2 minutes timeout
|
||||
echo ""
|
||||
echo "❌ Timeout: Windows VM failed to start within 2 minutes"
|
||||
echo " Check logs: docker logs nomarchy-windows"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Build the connection info
|
||||
if [[ $KEEP_ALIVE = "true" ]]; then
|
||||
LIFECYCLE="VM will keep running after RDP closes
|
||||
To stop: nomarchy-windows-vm stop"
|
||||
else
|
||||
LIFECYCLE="VM will auto-stop when RDP closes"
|
||||
fi
|
||||
|
||||
gum style \
|
||||
--border normal \
|
||||
--padding "1 2" \
|
||||
--margin "1" \
|
||||
--align center \
|
||||
"Connecting to Windows VM" \
|
||||
"" \
|
||||
"$LIFECYCLE"
|
||||
|
||||
# Detect display scale from Hyprland
|
||||
HYPR_SCALE=$(hyprctl monitors -j | jq -r '.[] | select (.focused == true) | .scale')
|
||||
SCALE_PERCENT=$(echo "$HYPR_SCALE" | awk '{print int($1 * 100)}')
|
||||
|
||||
RDP_SCALE=""
|
||||
if (( SCALE_PERCENT >= 170 )); then
|
||||
RDP_SCALE="/scale:180"
|
||||
elif (( SCALE_PERCENT >= 130 )); then
|
||||
RDP_SCALE="/scale:140"
|
||||
fi
|
||||
# If scale is less than 130%, don't set any scale (use default 100)
|
||||
|
||||
# Connect with RDP in fullscreen (auto-detects resolution)
|
||||
xfreerdp3 /u:"$WIN_USER" /p:"$WIN_PASS" /v:127.0.0.1:3389 -grab-keyboard /sound /microphone /clipboard /cert:ignore /title:"Windows VM - Nomarchy" /dynamic-resolution /gfx:AVC444 /floatbar:sticky:off,default:visible,show:fullscreen $RDP_SCALE
|
||||
|
||||
# After RDP closes, stop the container unless --keep-alive was specified
|
||||
if [[ $KEEP_ALIVE = "false" ]]; then
|
||||
echo ""
|
||||
echo "RDP session closed. Stopping Windows VM..."
|
||||
docker-compose -f "$COMPOSE_FILE" down
|
||||
echo "Windows VM stopped."
|
||||
else
|
||||
echo ""
|
||||
echo "RDP session closed. Windows VM is still running."
|
||||
echo "To stop it: nomarchy-windows-vm stop"
|
||||
fi
|
||||
}
|
||||
|
||||
stop_windows() {
|
||||
if [[ ! -f $COMPOSE_FILE ]]; then
|
||||
echo "Windows VM not configured."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Stopping Windows VM..."
|
||||
docker-compose -f "$COMPOSE_FILE" down
|
||||
echo "Windows VM stopped."
|
||||
}
|
||||
|
||||
status_windows() {
|
||||
if [[ ! -f $COMPOSE_FILE ]]; then
|
||||
echo "Windows VM not configured."
|
||||
echo "To set up: nomarchy-windows-vm install"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CONTAINER_STATUS=$(docker inspect --format='{{.State.Status}}' nomarchy-windows 2>/dev/null)
|
||||
|
||||
if [[ -z $CONTAINER_STATUS ]]; then
|
||||
echo "Windows VM container not found."
|
||||
echo "To start: nomarchy-windows-vm launch"
|
||||
elif [[ $CONTAINER_STATUS = "running" ]]; then
|
||||
gum style \
|
||||
--border normal \
|
||||
--padding "1 2" \
|
||||
--margin "1" \
|
||||
--align left \
|
||||
"Windows VM Status: RUNNING" \
|
||||
"" \
|
||||
"Web interface: http://127.0.0.1:8006" \
|
||||
"RDP available: port 3389" \
|
||||
"" \
|
||||
"To connect: nomarchy-windows-vm launch" \
|
||||
"To stop: nomarchy-windows-vm stop"
|
||||
else
|
||||
echo "Windows VM is stopped (status: $CONTAINER_STATUS)"
|
||||
echo "To start: nomarchy-windows-vm launch"
|
||||
fi
|
||||
}
|
||||
|
||||
show_usage() {
|
||||
echo "Usage: nomarchy-windows-vm [command] [options]"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " install Install and configure Windows VM"
|
||||
echo " remove Remove Windows VM and optionally its data"
|
||||
echo " launch [options] Start Windows VM (if needed) and connect via RDP"
|
||||
echo " Options:"
|
||||
echo " --keep-alive, -k Keep VM running after RDP closes"
|
||||
echo " stop Stop the running Windows VM"
|
||||
echo " status Show current VM status"
|
||||
echo " help Show this help message"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " nomarchy-windows-vm install # Set up Windows VM for first time"
|
||||
echo " nomarchy-windows-vm launch # Connect to VM (auto-stop on exit)"
|
||||
echo " nomarchy-windows-vm launch -k # Connect to VM (keep running)"
|
||||
echo " nomarchy-windows-vm stop # Shut down the VM"
|
||||
}
|
||||
|
||||
# Main command dispatcher
|
||||
case "$1" in
|
||||
install)
|
||||
install_windows
|
||||
;;
|
||||
remove)
|
||||
remove_windows
|
||||
;;
|
||||
launch|start)
|
||||
launch_windows "$2"
|
||||
;;
|
||||
stop|down)
|
||||
stop_windows
|
||||
;;
|
||||
status)
|
||||
status_windows
|
||||
;;
|
||||
help|--help|-h|"")
|
||||
show_usage
|
||||
;;
|
||||
*)
|
||||
echo "Unknown command: $1" >&2
|
||||
echo "" >&2
|
||||
show_usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
41
features/apps/swayosd.nix
Normal file
41
features/apps/swayosd.nix
Normal file
@@ -0,0 +1,41 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
services.swayosd = {
|
||||
enable = lib.mkDefault true;
|
||||
stylePath = lib.mkDefault "${config.home.homeDirectory}/.config/swayosd/style.css";
|
||||
};
|
||||
|
||||
xdg.configFile."swayosd/style.css".text = lib.mkDefault ''
|
||||
@define-color background-color #${config.colorScheme.palette.base00};
|
||||
@define-color border-color #${config.colorScheme.palette.base0E};
|
||||
@define-color label #${config.colorScheme.palette.base05};
|
||||
@define-color image #${config.colorScheme.palette.base05};
|
||||
@define-color progress #${config.colorScheme.palette.base0B};
|
||||
|
||||
window {
|
||||
border-radius: 0;
|
||||
opacity: 0.97;
|
||||
border: 2px solid @border-color;
|
||||
background-color: @background-color;
|
||||
}
|
||||
|
||||
label {
|
||||
font-family: '${config.nomarchy.fonts.monospace}';
|
||||
font-size: 11pt;
|
||||
color: @label;
|
||||
}
|
||||
|
||||
image {
|
||||
color: @image;
|
||||
}
|
||||
|
||||
progressbar {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
progress {
|
||||
background-color: @progress;
|
||||
}
|
||||
'';
|
||||
}
|
||||
94
features/apps/tmux/config/tmux.conf
Normal file
94
features/apps/tmux/config/tmux.conf
Normal file
@@ -0,0 +1,94 @@
|
||||
# Prefix
|
||||
set -g prefix C-Space
|
||||
set -g prefix2 C-b
|
||||
bind C-Space send-prefix
|
||||
|
||||
# Reload config
|
||||
bind q source-file ~/.config/tmux/tmux.conf \; display "Configuration reloaded"
|
||||
|
||||
# Vi mode for copy
|
||||
setw -g mode-keys vi
|
||||
bind -T copy-mode-vi v send -X begin-selection
|
||||
bind -T copy-mode-vi y send -X copy-selection-and-cancel
|
||||
|
||||
# Pane Controls
|
||||
bind h split-window -v -c "#{pane_current_path}"
|
||||
bind v split-window -h -c "#{pane_current_path}"
|
||||
bind x kill-pane
|
||||
|
||||
bind -n C-M-Left select-pane -L
|
||||
bind -n C-M-Right select-pane -R
|
||||
bind -n C-M-Up select-pane -U
|
||||
bind -n C-M-Down select-pane -D
|
||||
|
||||
bind -n C-M-S-Left resize-pane -L 5
|
||||
bind -n C-M-S-Down resize-pane -D 5
|
||||
bind -n C-M-S-Up resize-pane -U 5
|
||||
bind -n C-M-S-Right resize-pane -R 5
|
||||
|
||||
# Window navigation
|
||||
bind r command-prompt -I "#W" "rename-window -- '%%'"
|
||||
bind c new-window -c "#{pane_current_path}"
|
||||
bind k kill-window
|
||||
|
||||
bind -n M-1 select-window -t 1
|
||||
bind -n M-2 select-window -t 2
|
||||
bind -n M-3 select-window -t 3
|
||||
bind -n M-4 select-window -t 4
|
||||
bind -n M-5 select-window -t 5
|
||||
bind -n M-6 select-window -t 6
|
||||
bind -n M-7 select-window -t 7
|
||||
bind -n M-8 select-window -t 8
|
||||
bind -n M-9 select-window -t 9
|
||||
|
||||
bind -n M-Left select-window -t -1
|
||||
bind -n M-Right select-window -t +1
|
||||
bind -n M-S-Left swap-window -t -1 \; select-window -t -1
|
||||
bind -n M-S-Right swap-window -t +1 \; select-window -t +1
|
||||
|
||||
# Session controls
|
||||
bind R command-prompt -I "#S" "rename-session -- '%%'"
|
||||
bind C new-session -c "#{pane_current_path}"
|
||||
bind K kill-session
|
||||
bind P switch-client -p
|
||||
bind N switch-client -n
|
||||
|
||||
bind -n M-Up switch-client -p
|
||||
bind -n M-Down switch-client -n
|
||||
|
||||
# General
|
||||
set -g default-terminal "tmux-256color"
|
||||
set -ag terminal-overrides ",*:RGB"
|
||||
set -g mouse on
|
||||
set -g base-index 1
|
||||
setw -g pane-base-index 1
|
||||
set -g renumber-windows on
|
||||
set -g history-limit 50000
|
||||
set -g escape-time 0
|
||||
set -g focus-events on
|
||||
set -g set-clipboard on
|
||||
set -g allow-passthrough on
|
||||
setw -g aggressive-resize on
|
||||
set -g detach-on-destroy off
|
||||
|
||||
# Status bar
|
||||
set -g status-position top
|
||||
set -g status-interval 5
|
||||
set -g status-left-length 30
|
||||
set -g status-right-length 50
|
||||
set -g window-status-separator ""
|
||||
set -gw automatic-rename on
|
||||
set -gw automatic-rename-format '#{b:pane_current_path}'
|
||||
|
||||
# Theme
|
||||
set -g status-style "bg=default,fg=default"
|
||||
set -g status-left "#[fg=black,bg=blue,bold] #S #[bg=default] "
|
||||
set -g status-right "#[fg=blue]#{?pane_in_mode,COPY ,}#{?client_prefix,PREFIX ,}#{?window_zoomed_flag,ZOOM ,}#[fg=brightblack]#h "
|
||||
set -g window-status-format "#[fg=brightblack] #I:#W "
|
||||
set -g window-status-current-format "#[fg=blue,bold] #I:#W "
|
||||
set -g pane-border-style "fg=brightblack"
|
||||
set -g pane-active-border-style "fg=blue"
|
||||
set -g message-style "bg=default,fg=blue"
|
||||
set -g message-command-style "bg=default,fg=blue"
|
||||
set -g mode-style "bg=blue,fg=black"
|
||||
setw -g clock-mode-colour blue
|
||||
53
features/apps/vscode.nix
Normal file
53
features/apps/vscode.nix
Normal file
@@ -0,0 +1,53 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
themeConfig = builtins.fromJSON (builtins.readFile (../../assets/themes + "/${config.nomarchy.theme}/vscode.json"));
|
||||
|
||||
# Development extensions that match the system theme
|
||||
devExtensions = with pkgs.vscode-extensions; [
|
||||
# Language support
|
||||
ms-python.python
|
||||
rust-lang.rust-analyzer
|
||||
golang.go
|
||||
jnoortheen.nix-ide
|
||||
|
||||
# Git integration
|
||||
eamodio.gitlens
|
||||
|
||||
# Editor enhancements
|
||||
esbenp.prettier-vscode
|
||||
dbaeumer.vscode-eslint
|
||||
bradlc.vscode-tailwindcss
|
||||
|
||||
# Theme extensions (provide color themes matching nomarchy palettes)
|
||||
catppuccin.catppuccin-vsc
|
||||
enkia.tokyo-night
|
||||
arcticicestudio.nord-visual-studio-code
|
||||
sainnhe.everforest
|
||||
mvllow.rose-pine
|
||||
];
|
||||
in
|
||||
{
|
||||
options.nomarchy.vscode = {
|
||||
devExtensions = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Whether to install development extensions for VSCode.";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
programs.vscode = {
|
||||
enable = lib.mkDefault true;
|
||||
package = lib.mkDefault pkgs.vscode;
|
||||
userSettings = lib.mkDefault {
|
||||
"update.mode" = "none";
|
||||
"workbench.colorTheme" = themeConfig.name;
|
||||
"window.titleBarStyle" = "custom";
|
||||
"editor.fontFamily" = "'${config.nomarchy.fonts.monospace}', 'Droid Sans Mono', monospace";
|
||||
"terminal.integrated.fontFamily" = config.nomarchy.fonts.monospace;
|
||||
};
|
||||
extensions = lib.mkIf config.nomarchy.vscode.devExtensions (lib.mkDefault devExtensions);
|
||||
};
|
||||
};
|
||||
}
|
||||
56
features/apps/walker.nix
Normal file
56
features/apps/walker.nix
Normal file
@@ -0,0 +1,56 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
programs.walker = {
|
||||
enable = lib.mkDefault true;
|
||||
runAsService = lib.mkDefault true;
|
||||
config = lib.mkDefault {
|
||||
theme = "nomarchy";
|
||||
ui = {
|
||||
anchors = {
|
||||
top = true;
|
||||
};
|
||||
};
|
||||
selection_wrap = true;
|
||||
hide_action_hints = true;
|
||||
placeholders = {
|
||||
"default" = { input = " Search..."; list = "No Results"; };
|
||||
};
|
||||
keybinds = {
|
||||
quick_activate = [];
|
||||
};
|
||||
columns = {
|
||||
symbols = 1;
|
||||
};
|
||||
providers = {
|
||||
max_results = 256;
|
||||
default = [
|
||||
"desktopapplications"
|
||||
"websearch"
|
||||
];
|
||||
prefixes = [
|
||||
{ prefix = "/"; provider = "providerlist"; }
|
||||
{ prefix = "."; provider = "files"; }
|
||||
{ prefix = ":"; provider = "symbols"; }
|
||||
{ prefix = "="; provider = "calc"; }
|
||||
{ prefix = "@"; provider = "websearch"; }
|
||||
{ prefix = "$"; provider = "clipboard"; }
|
||||
];
|
||||
};
|
||||
};
|
||||
themes."nomarchy" = lib.mkDefault {
|
||||
style = ''
|
||||
* {
|
||||
color: #${config.colorScheme.palette.base05};
|
||||
}
|
||||
#window {
|
||||
background-color: #${config.colorScheme.palette.base00};
|
||||
}
|
||||
.item.active {
|
||||
background-color: #${config.colorScheme.palette.base03};
|
||||
color: #${config.colorScheme.palette.base0B};
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user