Compare commits
14 Commits
refactor-p
...
sddm-uki-c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52a2081f0a | ||
|
|
4b5f310e51 | ||
|
|
6a2b68c9d2 | ||
|
|
a4a94ff948 | ||
|
|
35c3a38074 | ||
|
|
48004cf741 | ||
|
|
93fe3b27e1 | ||
|
|
0b172dbef1 | ||
|
|
a84bc4b256 | ||
|
|
ad8d028d3f | ||
|
|
f70a7bc5db | ||
|
|
b64bd47939 | ||
|
|
bdb2ea50ed | ||
|
|
a823d5e835 |
@@ -1,9 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
3
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -1,5 +1,5 @@
|
||||
name: Bug
|
||||
description: Report a validated bug -- NOT FOR SUPPORT REQUESTS
|
||||
description: Report a problem
|
||||
labels: [bug]
|
||||
body:
|
||||
- type: markdown
|
||||
@@ -19,6 +19,5 @@ body:
|
||||
id: steps
|
||||
attributes:
|
||||
label: What's wrong?
|
||||
description: Describe the issue, include steps to recreate it if possible, and attach the output of `omarchy-debug` if possible
|
||||
validations:
|
||||
required: true
|
||||
|
||||
7
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,8 +1 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Suggestion
|
||||
url: https://github.com/basecamp/omarchy/discussions/categories/suggestions
|
||||
about: Suggest a new feature, change to existing feature, or other ideas in Discussions.
|
||||
- name: Support
|
||||
url: https://omarchy.org/discord
|
||||
about: Need help? Join our Discord community for support with any issues. GitHub issues should be used for verified bugs only.
|
||||
|
||||
15
.github/ISSUE_TEMPLATE/documentation.yml
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
name: Documentation
|
||||
description: New pages or changes to existing
|
||||
labels: [documentation]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Remember: Omarchy is an open source gift, not a product you bought from a vendor
|
||||
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: What correction or addition do we need?
|
||||
validations:
|
||||
required: true
|
||||
15
.github/ISSUE_TEMPLATE/enhancement.yml
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
name: Enhancement
|
||||
description: Feature or change
|
||||
labels: [enhancement]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Remember: Omarchy is an open source gift, not a product you bought from a vendor
|
||||
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: What do you need?
|
||||
validations:
|
||||
required: true
|
||||
@@ -1,9 +1,10 @@
|
||||
# Omarchy
|
||||
|
||||
Omarchy is a beautiful, modern & opinionated Linux distribution by DHH.
|
||||
Turn a fresh Arch installation into a fully-configured, beautiful, and modern web development system based on Hyprland by running a single command. That's the one-line pitch for Omarchy (like it was for Omakub). No need to write bespoke configs for every essential tool just to get started or to be up on all the latest command-line tools. Omarchy is an opinionated take on what Linux can be at its best.
|
||||
|
||||
Read more at [omarchy.org](https://omarchy.org).
|
||||
|
||||
## License
|
||||
|
||||
Omarchy is released under the [MIT License](https://opensource.org/licenses/MIT).
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
TryExec=alacritty
|
||||
Exec=alacritty
|
||||
Icon=Alacritty
|
||||
Terminal=false
|
||||
Categories=System;TerminalEmulator;
|
||||
Name=Alacritty
|
||||
GenericName=Terminal
|
||||
Comment=A fast, cross-platform, OpenGL terminal emulator
|
||||
StartupNotify=true
|
||||
StartupWMClass=Alacritty
|
||||
Actions=New;
|
||||
X-TerminalArgExec=-e
|
||||
X-TerminalArgAppId=--class=
|
||||
X-TerminalArgTitle=--title=
|
||||
X-TerminalArgDir=--working-directory=
|
||||
|
||||
[Desktop Action New]
|
||||
Name=New Terminal
|
||||
Exec=alacritty
|
||||
@@ -1,2 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Hidden=true
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 75 KiB |
12
applications/nvim.desktop
Normal file
@@ -0,0 +1,12 @@
|
||||
[Desktop Entry]
|
||||
Name=Neovim
|
||||
GenericName=Text Editor
|
||||
Comment=Edit text files
|
||||
Exec=sh -c "$TERMINAL --class=nvim --title=nvim -e nvim -- %F"
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Keywords=Text;editor;
|
||||
Icon=nvim
|
||||
Categories=Utility;TextEditor;
|
||||
StartupNotify=false
|
||||
MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;
|
||||
@@ -4,20 +4,33 @@
|
||||
|
||||
BATTERY_THRESHOLD=10
|
||||
NOTIFICATION_FLAG="/run/user/$UID/omarchy_battery_notified"
|
||||
BATTERY_LEVEL=$(omarchy-battery-remaining)
|
||||
BATTERY_STATE=$(upower -i $(upower -e | grep 'BAT') | grep -E "state" | awk '{print $2}')
|
||||
|
||||
get_battery_percentage() {
|
||||
upower -i "$(upower -e | grep 'BAT')" \
|
||||
| awk -F: '/percentage/ {
|
||||
gsub(/[%[:space:]]/, "", $2);
|
||||
val=$2;
|
||||
printf("%d\n", (val+0.5))
|
||||
exit
|
||||
}'
|
||||
}
|
||||
|
||||
get_battery_state() {
|
||||
upower -i $(upower -e | grep 'BAT') | grep -E "state" | awk '{print $2}'
|
||||
}
|
||||
|
||||
send_notification() {
|
||||
notify-send -u critical " Time to recharge!" "Battery is down to ${1}%" -i battery-caution -t 30000
|
||||
}
|
||||
|
||||
if [[ -n "$BATTERY_LEVEL" && "$BATTERY_LEVEL" =~ ^[0-9]+$ ]]; then
|
||||
if [[ $BATTERY_STATE == "discharging" && $BATTERY_LEVEL -le $BATTERY_THRESHOLD ]]; then
|
||||
if [[ ! -f $NOTIFICATION_FLAG ]]; then
|
||||
send_notification $BATTERY_LEVEL
|
||||
touch $NOTIFICATION_FLAG
|
||||
fi
|
||||
else
|
||||
rm -f $NOTIFICATION_FLAG
|
||||
BATTERY_LEVEL=$(get_battery_percentage)
|
||||
BATTERY_STATE=$(get_battery_state)
|
||||
|
||||
if [[ "$BATTERY_STATE" == "discharging" && "$BATTERY_LEVEL" -le "$BATTERY_THRESHOLD" ]]; then
|
||||
if [[ ! -f "$NOTIFICATION_FLAG" ]]; then
|
||||
send_notification "$BATTERY_LEVEL"
|
||||
touch "$NOTIFICATION_FLAG"
|
||||
fi
|
||||
else
|
||||
rm -f "$NOTIFICATION_FLAG"
|
||||
fi
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Returns the battery percentage remaining as an integer.
|
||||
|
||||
upower -i $(upower -e | grep BAT) \
|
||||
| awk -F: '/percentage/ {
|
||||
gsub(/[%[:space:]]/, "", $2);
|
||||
val=$2;
|
||||
printf("%d\n", (val+0.5))
|
||||
exit
|
||||
}'
|
||||
@@ -3,12 +3,5 @@
|
||||
if [[ $# -eq 0 ]]; then
|
||||
echo "Adjust Apple Display Brightness by passing +5000 or -5000 (or any range from 0-60000)"
|
||||
else
|
||||
DEVICE="$(sudo asdcontrol --detect /dev/usb/hiddev* | grep ^/dev/usb/hiddev | cut -d: -f1)"
|
||||
sudo asdcontrol "$DEVICE" -- "$1" >/dev/null
|
||||
VALUE="$(sudo asdcontrol "$DEVICE" | awk -F= '/BRIGHTNESS=/{print $2+0}')"
|
||||
swayosd-client \
|
||||
--monitor "$(hyprctl monitors -j | jq -r '.[]|select(.focused==true).name')" \
|
||||
--custom-icon display-brightness \
|
||||
--custom-progress "$(awk -v v="$VALUE" 'BEGIN{printf "%.2f", v/60000}')" \
|
||||
--custom-progress-text "$(( VALUE * 100 / 60000 ))%"
|
||||
sudo asdcontrol $(sudo asdcontrol --detect /dev/usb/hiddev* | grep ^/dev/usb/hiddev | cut -d: -f1) -- "$1"
|
||||
fi
|
||||
|
||||
@@ -23,13 +23,7 @@ fi
|
||||
|
||||
next_sink=$(echo "$sinks" | jq -r ".[$next_sink_index]")
|
||||
next_sink_name=$(echo "$next_sink" | jq -r '.name')
|
||||
|
||||
next_sink_description=$(echo "$next_sink" | jq -r '.description')
|
||||
if [ "$next_sink_description" = "(null)" ] || [ "$next_sink_description" = "null" ] || [ -z "$next_sink_description" ]; then
|
||||
sink_id=$(echo "$next_sink" | jq -r '.properties."object.id"')
|
||||
next_sink_description=$(wpctl status | grep -E "\s+\*?\s+${sink_id}\." | sed -E 's/^.*[0-9]+\.\s+//' | sed -E 's/\s+\[.*$//')
|
||||
fi
|
||||
|
||||
next_sink_volume=$(echo "$next_sink" | jq -r \
|
||||
'.volume | to_entries[0].value.value_percent | sub("%"; "")')
|
||||
next_sink_is_muted=$(echo "$next_sink" | jq -r '.mute')
|
||||
|
||||
@@ -8,12 +8,10 @@ if [[ -f "$FIRST_RUN_MODE" ]]; then
|
||||
rm -f "$FIRST_RUN_MODE"
|
||||
|
||||
bash "$OMARCHY_PATH/install/first-run/battery-monitor.sh"
|
||||
bash "$OMARCHY_PATH/install/first-run/cleanup-reboot-sudoers.sh"
|
||||
bash "$OMARCHY_PATH/install/first-run/firewall.sh"
|
||||
bash "$OMARCHY_PATH/install/first-run/dns-resolver.sh"
|
||||
bash "$OMARCHY_PATH/install/first-run/gnome-theme.sh"
|
||||
sudo rm -f /etc/sudoers.d/first-run
|
||||
|
||||
bash "$OMARCHY_PATH/install/first-run/welcome.sh"
|
||||
bash "$OMARCHY_PATH/install/first-run/wifi.sh"
|
||||
bash "$OMARCHY_PATH/install/first-run/welcome.sh"
|
||||
fi
|
||||
|
||||
@@ -8,82 +8,31 @@ if [[ ! -d "$OUTPUT_DIR" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SCOPE=""
|
||||
AUDIO="false"
|
||||
WEBCAM="false"
|
||||
# Selects region or output
|
||||
SCOPE="$1"
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--with-audio) AUDIO="true" ;;
|
||||
--with-webcam) WEBCAM="true" ;;
|
||||
output|region) SCOPE="$arg" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
cleanup_webcam() {
|
||||
pkill -f "WebcamOverlay" 2>/dev/null
|
||||
}
|
||||
|
||||
start_webcam_overlay() {
|
||||
cleanup_webcam
|
||||
|
||||
# Get monitor scale
|
||||
local scale=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .scale')
|
||||
|
||||
# Target width (base 360px, scaled to monitor)
|
||||
local target_width=$(awk "BEGIN {printf \"%.0f\", 360 * $scale}")
|
||||
|
||||
# Try preferred 16:9 resolutions in order, use first available
|
||||
local preferred_resolutions=("640x360" "1280x720" "1920x1080")
|
||||
local video_size_arg=""
|
||||
local available_formats=$(v4l2-ctl --list-formats-ext -d /dev/video0 2>/dev/null)
|
||||
|
||||
for resolution in "${preferred_resolutions[@]}"; do
|
||||
if echo "$available_formats" | grep -q "$resolution"; then
|
||||
video_size_arg="-video_size $resolution"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
ffplay -f v4l2 $video_size_arg -framerate 30 /dev/video0 \
|
||||
-vf "scale=${target_width}:-1" \
|
||||
-window_title "WebcamOverlay" \
|
||||
-noborder \
|
||||
-fflags nobuffer -flags low_delay \
|
||||
-probesize 32 -analyzeduration 0 \
|
||||
-loglevel quiet &
|
||||
sleep 1
|
||||
}
|
||||
# Selects audio inclusion or not
|
||||
AUDIO=$([[ $2 == "audio" ]] && echo "--audio")
|
||||
|
||||
start_screenrecording() {
|
||||
local filename="$OUTPUT_DIR/screenrecording-$(date +'%Y-%m-%d_%H-%M-%S').mp4"
|
||||
local audio_args=""
|
||||
|
||||
# Merge audio tracks into one - separate tracks only play one at a time in most players
|
||||
[[ "$AUDIO" == "true" ]] && audio_args="-a default_output|default_input"
|
||||
if lspci | grep -qi 'nvidia'; then
|
||||
wf-recorder $AUDIO -f "$filename" -c libx264 -p crf=23 -p preset=medium -p movflags=+faststart "$@" &
|
||||
else
|
||||
wl-screenrec $AUDIO -f "$filename" --ffmpeg-encoder-options="-c:v libx264 -crf 23 -preset medium -movflags +faststart" "$@" &
|
||||
fi
|
||||
|
||||
gpu-screen-recorder -w "$@" -f 60 -c mp4 -o "$filename" $audio_args &
|
||||
toggle_screenrecording_indicator
|
||||
}
|
||||
|
||||
stop_screenrecording() {
|
||||
pkill -SIGINT -f "gpu-screen-recorder" # SIGINT required to save video properly
|
||||
pkill -x wl-screenrec
|
||||
pkill -x wf-recorder
|
||||
|
||||
# Wait a maximum of 5 seconds to finish before hard killing
|
||||
local count=0
|
||||
while pgrep -f "gpu-screen-recorder" >/dev/null && [ $count -lt 50 ]; do
|
||||
sleep 0.1
|
||||
count=$((count + 1))
|
||||
done
|
||||
notify-send "Screen recording saved to $OUTPUT_DIR" -t 2000
|
||||
|
||||
if pgrep -f "gpu-screen-recorder" >/dev/null; then
|
||||
pkill -9 -f "gpu-screen-recorder"
|
||||
cleanup_webcam
|
||||
notify-send "Screen recording error" "Recording process had to be force-killed. Video may be corrupted." -u critical -t 5000
|
||||
else
|
||||
cleanup_webcam
|
||||
notify-send "Screen recording saved to $OUTPUT_DIR" -t 2000
|
||||
fi
|
||||
sleep 0.2 # ensures the process is actually dead before we check
|
||||
toggle_screenrecording_indicator
|
||||
}
|
||||
|
||||
@@ -92,51 +41,15 @@ toggle_screenrecording_indicator() {
|
||||
}
|
||||
|
||||
screenrecording_active() {
|
||||
pgrep -f "gpu-screen-recorder" >/dev/null || pgrep -x slurp >/dev/null || pgrep -f "WebcamOverlay" >/dev/null
|
||||
pgrep -x wl-screenrec >/dev/null || pgrep -x wf-recorder >/dev/null
|
||||
}
|
||||
|
||||
if screenrecording_active; then
|
||||
if pgrep -x slurp >/dev/null; then
|
||||
pkill -x slurp 2>/dev/null
|
||||
elif pgrep -f "WebcamOverlay" >/dev/null && ! pgrep -f "gpu-screen-recorder" >/dev/null; then
|
||||
cleanup_webcam
|
||||
else
|
||||
stop_screenrecording
|
||||
fi
|
||||
stop_screenrecording
|
||||
elif [[ "$SCOPE" == "output" ]]; then
|
||||
[[ "$WEBCAM" == "true" ]] && start_webcam_overlay
|
||||
|
||||
if ! output=$(slurp -o -f "%o"); then
|
||||
[[ "$WEBCAM" == "true" ]] && cleanup_webcam
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "$output" ]]; then
|
||||
notify-send "Error" "Could not detect monitor" -u critical
|
||||
[[ "$WEBCAM" == "true" ]] && cleanup_webcam
|
||||
exit 1
|
||||
fi
|
||||
|
||||
start_screenrecording "$output"
|
||||
output=$(slurp -o) || exit 1
|
||||
start_screenrecording -g "$output"
|
||||
else
|
||||
[[ "$WEBCAM" == "true" ]] && start_webcam_overlay
|
||||
|
||||
scale=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .scale')
|
||||
|
||||
if ! region=$(slurp -f "%wx%h+%x+%y"); then
|
||||
[[ "$WEBCAM" == "true" ]] && cleanup_webcam
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$region" =~ ^([0-9]+)x([0-9]+)\+([0-9]+)\+([0-9]+)$ ]]; then
|
||||
w=$(awk "BEGIN {printf \"%.0f\", ${BASH_REMATCH[1]} * $scale}")
|
||||
h=$(awk "BEGIN {printf \"%.0f\", ${BASH_REMATCH[2]} * $scale}")
|
||||
x=$(awk "BEGIN {printf \"%.0f\", ${BASH_REMATCH[3]} * $scale}")
|
||||
y=$(awk "BEGIN {printf \"%.0f\", ${BASH_REMATCH[4]} * $scale}")
|
||||
scaled_region="${w}x${h}+${x}+${y}"
|
||||
else
|
||||
scaled_region="$region"
|
||||
fi
|
||||
|
||||
start_screenrecording region -region "$scaled_region"
|
||||
region=$(slurp) || exit 1
|
||||
start_screenrecording -g "$region"
|
||||
fi
|
||||
|
||||
@@ -13,12 +13,12 @@ exit_screensaver() {
|
||||
|
||||
trap exit_screensaver SIGINT SIGTERM SIGHUP SIGQUIT
|
||||
|
||||
hyprctl keyword cursor:invisible true &>/dev/null
|
||||
hyprctl keyword cursor:invisible true
|
||||
|
||||
while true; do
|
||||
effect=$(tte 2>&1 | grep -oP '{\K[^}]+' | tr ',' ' ' | tr ' ' '\n' | sed -n '/^beams$/,$p' | sort -u | shuf -n1)
|
||||
tte -i ~/.config/omarchy/branding/screensaver.txt \
|
||||
--frame-rate 240 --canvas-width 0 --canvas-height $(($(tput lines) - 2)) --anchor-canvas c --anchor-text c \
|
||||
--frame-rate 240 --canvas-width 0 --canvas-height $(($(tput lines) - 1)) --anchor-canvas c --anchor-text c \
|
||||
"$effect" &
|
||||
|
||||
while pgrep -x tte >/dev/null; do
|
||||
|
||||
@@ -8,76 +8,10 @@ if [[ ! -d "$OUTPUT_DIR" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
pkill slurp && exit 0
|
||||
|
||||
MODE="${1:-smart}"
|
||||
PROCESSING="${2:-slurp}"
|
||||
|
||||
get_rectangles() {
|
||||
local active_workspace=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .activeWorkspace.id')
|
||||
hyprctl monitors -j | jq -r --arg ws "$active_workspace" '.[] | select(.activeWorkspace.id == ($ws | tonumber)) | "\(.x),\(.y) \((.width / .scale) | floor)x\((.height / .scale) | floor)"'
|
||||
hyprctl clients -j | jq -r --arg ws "$active_workspace" '.[] | select(.workspace.id == ($ws | tonumber)) | "\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"'
|
||||
}
|
||||
|
||||
# Select based on mode
|
||||
case "$MODE" in
|
||||
region)
|
||||
wayfreeze & PID=$!
|
||||
sleep .1
|
||||
SELECTION=$(slurp 2>/dev/null)
|
||||
kill $PID 2>/dev/null
|
||||
;;
|
||||
windows)
|
||||
wayfreeze & PID=$!
|
||||
sleep .1
|
||||
SELECTION=$(get_rectangles | slurp -r 2>/dev/null)
|
||||
kill $PID 2>/dev/null
|
||||
;;
|
||||
fullscreen)
|
||||
SELECTION=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true) | "\(.x),\(.y) \((.width / .scale) | floor)x\((.height / .scale) | floor)"')
|
||||
;;
|
||||
smart|*)
|
||||
RECTS=$(get_rectangles)
|
||||
wayfreeze & PID=$!
|
||||
sleep .1
|
||||
SELECTION=$(echo "$RECTS" | slurp 2>/dev/null)
|
||||
kill $PID 2>/dev/null
|
||||
|
||||
# If the selction area is L * W < 20, we'll assume you were trying to select whichever
|
||||
# window or output it was inside of to prevent accidental 2px snapshots
|
||||
if [[ "$SELECTION" =~ ^([0-9]+),([0-9]+)[[:space:]]([0-9]+)x([0-9]+)$ ]]; then
|
||||
if (( ${BASH_REMATCH[3]} * ${BASH_REMATCH[4]} < 20 )); then
|
||||
click_x="${BASH_REMATCH[1]}"
|
||||
click_y="${BASH_REMATCH[2]}"
|
||||
|
||||
while IFS= read -r rect; do
|
||||
if [[ "$rect" =~ ^([0-9]+),([0-9]+)[[:space:]]([0-9]+)x([0-9]+) ]]; then
|
||||
rect_x="${BASH_REMATCH[1]}"
|
||||
rect_y="${BASH_REMATCH[2]}"
|
||||
rect_width="${BASH_REMATCH[3]}"
|
||||
rect_height="${BASH_REMATCH[4]}"
|
||||
|
||||
if (( click_x >= rect_x && click_x < rect_x+rect_width && click_y >= rect_y && click_y < rect_y+rect_height )); then
|
||||
SELECTION="${rect_x},${rect_y} ${rect_width}x${rect_height}"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done <<< "$RECTS"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
[ -z "$SELECTION" ] && exit 0
|
||||
|
||||
if [[ $PROCESSING == "slurp" ]]; then
|
||||
grim -g "$SELECTION" - |
|
||||
pkill slurp || hyprshot -m ${1:-region} --raw |
|
||||
satty --filename - \
|
||||
--output-filename "$OUTPUT_DIR/screenshot-$(date +'%Y-%m-%d_%H-%M-%S').png" \
|
||||
--early-exit \
|
||||
--actions-on-enter save-to-clipboard \
|
||||
--save-after-copy \
|
||||
--copy-command 'wl-copy'
|
||||
else
|
||||
grim -g "$SELECTION" - | wl-copy
|
||||
fi
|
||||
|
||||
@@ -2,16 +2,10 @@
|
||||
|
||||
# Go from current active terminal to its child shell process and run cwd there
|
||||
terminal_pid=$(hyprctl activewindow | awk '/pid:/ {print $2}')
|
||||
shell_pid=$(pgrep -P "$terminal_pid" | tail -n1)
|
||||
shell_pid=$(pgrep -P "$terminal_pid" | head -n1)
|
||||
|
||||
if [[ -n $shell_pid ]]; then
|
||||
cwd=$(readlink -f "/proc/$shell_pid/cwd" 2>/dev/null)
|
||||
|
||||
if [[ -d $cwd ]]; then
|
||||
echo "$cwd"
|
||||
else
|
||||
echo "$HOME"
|
||||
fi
|
||||
readlink -f "/proc/$shell_pid/cwd" 2>/dev/null || echo "$HOME"
|
||||
else
|
||||
echo "$HOME"
|
||||
fi
|
||||
|
||||
8
bin/omarchy-cmd-tzupdate
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
notify-send " Updating time and timezone..."
|
||||
sudo systemctl restart systemd-timesyncd
|
||||
sudo tzupdate
|
||||
new_timezone=$(timedatectl show -p Timezone --value)
|
||||
omarchy-restart-waybar
|
||||
notify-send " Time updated and timezone set to $new_timezone"
|
||||
@@ -1,61 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
LOG_FILE="/tmp/omarchy-debug.log"
|
||||
|
||||
cat > "$LOG_FILE" <<EOF
|
||||
Date: $(date)
|
||||
Hostname: $(hostname)
|
||||
Omarchy Branch: $(git -C "$OMARCHY_PATH" branch --show-current 2>/dev/null || echo "unknown")
|
||||
|
||||
=========================================
|
||||
SYSTEM INFORMATION
|
||||
=========================================
|
||||
$(inxi -Farz)
|
||||
|
||||
=========================================
|
||||
DMESG
|
||||
=========================================
|
||||
$(sudo dmesg)
|
||||
|
||||
=========================================
|
||||
JOURNALCTL (CURRENT BOOT, ERRORS ONLY)
|
||||
=========================================
|
||||
$(journalctl -b -p 4..1)
|
||||
|
||||
=========================================
|
||||
INSTALLED PACKAGES
|
||||
=========================================
|
||||
$({ expac -S '%n %v (%r)' $(pacman -Qqe) 2>/dev/null; comm -13 <(pacman -Sql | sort) <(pacman -Qqe | sort) | xargs -r expac -Q '%n %v (AUR)'; } | sort)
|
||||
EOF
|
||||
|
||||
OPTIONS=("View log" "Save in current directory")
|
||||
if ping -c 1 8.8.8.8 >/dev/null 2>&1; then
|
||||
OPTIONS=("Upload log" "${OPTIONS[@]}")
|
||||
fi
|
||||
|
||||
ACTION=$(gum choose "${OPTIONS[@]}")
|
||||
|
||||
case "$ACTION" in
|
||||
"Upload log")
|
||||
echo "Uploading debug log to 0x0.st..."
|
||||
URL=$(curl -sF "file=@$LOG_FILE" -Fexpires=24 https://0x0.st)
|
||||
if [ $? -eq 0 ] && [ -n "$URL" ]; then
|
||||
echo "✓ Log uploaded successfully!"
|
||||
echo "Share this URL:"
|
||||
echo ""
|
||||
echo " $URL"
|
||||
echo ""
|
||||
echo "This link will expire in 24 hours."
|
||||
else
|
||||
echo "Error: Failed to upload log file"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
"View log")
|
||||
less "$LOG_FILE"
|
||||
;;
|
||||
"Save in current directory")
|
||||
cp "$LOG_FILE" "./omarchy-debug.log"
|
||||
echo "✓ Log saved to $(pwd)/omarchy-debug.log"
|
||||
;;
|
||||
esac
|
||||
@@ -1,6 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
# FIXME: Update behavior
|
||||
cd ~/.local/share/omarchy
|
||||
migration_file="$HOME/.local/share/omarchy/migrations/$(git log -1 --format=%cd --date=unix).sh"
|
||||
touch $migration_file
|
||||
|
||||
@@ -1,344 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Omarchy Disk Configuration Tool
|
||||
|
||||
Interactive partition editor and validator for Omarchy installations.
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def _find_root_partition(disk_config):
|
||||
for dev_mod in disk_config.device_modifications:
|
||||
for part in dev_mod.partitions:
|
||||
if part.mountpoint == Path('/'):
|
||||
return part
|
||||
|
||||
if part.btrfs_subvols:
|
||||
for subvol in part.btrfs_subvols:
|
||||
if subvol.mountpoint == Path('/'):
|
||||
return part
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def validate_disk_config(config, interactive=True):
|
||||
from archinstall.lib.models.device import FilesystemType, Size, Unit, EncryptionType
|
||||
from archinstall.lib.output import info, warn
|
||||
|
||||
if not config.disk_config:
|
||||
return 'CONTINUE'
|
||||
|
||||
validation_warnings = []
|
||||
|
||||
boot_partition = None
|
||||
for dev_mod in config.disk_config.device_modifications:
|
||||
for part in dev_mod.partitions:
|
||||
if part.mountpoint == Path('/boot') or part.mountpoint == Path('/efi'):
|
||||
boot_partition = part
|
||||
break
|
||||
|
||||
if boot_partition:
|
||||
min_boot_size = Size(2, Unit.GiB, boot_partition.length.sector_size)
|
||||
if boot_partition.length >= min_boot_size:
|
||||
size_gb = boot_partition.length.convert(Unit.GiB).value
|
||||
info(f'✓ Boot partition size: {size_gb:.1f} GiB')
|
||||
else:
|
||||
size_mb = boot_partition.length.convert(Unit.MiB).value
|
||||
warn(f'⚠ Boot partition is only {size_mb:.0f} MiB')
|
||||
warn(' Omarchy recommends at least 2 GiB for boot partition')
|
||||
warn(' Multiple kernels may not fit')
|
||||
validation_warnings.append('boot_size')
|
||||
else:
|
||||
warn('⚠ Could not find boot partition (/boot or /efi)')
|
||||
warn(' System may not boot correctly')
|
||||
validation_warnings.append('no_boot')
|
||||
|
||||
root_partition = _find_root_partition(config.disk_config)
|
||||
|
||||
if root_partition:
|
||||
if root_partition.fs_type == FilesystemType.Btrfs:
|
||||
info('✓ Root filesystem is btrfs')
|
||||
|
||||
if root_partition.btrfs_subvols:
|
||||
subvol_names = [str(sv.name) for sv in root_partition.btrfs_subvols]
|
||||
subvol_mounts = {str(sv.mountpoint): str(sv.name) for sv in root_partition.btrfs_subvols}
|
||||
|
||||
required_subvols = {
|
||||
'/': '@',
|
||||
'/home': '@home',
|
||||
'/var/log': '@log',
|
||||
'/var/cache/pacman/pkg': '@pkg',
|
||||
}
|
||||
|
||||
missing_subvols = []
|
||||
for mount, expected_name in required_subvols.items():
|
||||
if mount not in subvol_mounts:
|
||||
missing_subvols.append(f'{expected_name} → {mount}')
|
||||
elif subvol_mounts[mount] != expected_name:
|
||||
warn(f'⚠ Subvolume at {mount} is named "{subvol_mounts[mount]}" not "{expected_name}"')
|
||||
|
||||
if missing_subvols:
|
||||
warn(f'⚠ Missing recommended subvolumes: {", ".join(missing_subvols)}')
|
||||
warn(' Omarchy recommends: @, @home, @log, @pkg')
|
||||
warn(' Some features (like Snapper) may not work optimally')
|
||||
info(f' Current subvolumes: {", ".join(subvol_names)}')
|
||||
validation_warnings.append('missing_subvols')
|
||||
else:
|
||||
info(f'✓ Btrfs subvolumes: {", ".join(subvol_names)}')
|
||||
else:
|
||||
warn('⚠ Btrfs partition has no subvolumes defined')
|
||||
warn(' Omarchy recommends subvolumes for snapshots')
|
||||
warn(' Required: @ (root), @home, @log, @pkg')
|
||||
validation_warnings.append('no_subvols')
|
||||
else:
|
||||
fs_name = root_partition.fs_type.value if root_partition.fs_type else 'unknown'
|
||||
warn(f'⚠ Root filesystem is {fs_name}, not btrfs')
|
||||
warn(' Omarchy is designed for btrfs with snapshots')
|
||||
warn(' Some features may not work correctly')
|
||||
validation_warnings.append('not_btrfs')
|
||||
|
||||
is_encrypted = False
|
||||
if config.disk_config.disk_encryption:
|
||||
enc = config.disk_config.disk_encryption
|
||||
if enc.encryption_type != EncryptionType.NoEncryption:
|
||||
is_encrypted = root_partition in enc.partitions
|
||||
|
||||
if is_encrypted:
|
||||
info('✓ Root partition is encrypted with LUKS')
|
||||
|
||||
if config.disk_config.disk_encryption.iter_time != 2000:
|
||||
old_time = config.disk_config.disk_encryption.iter_time
|
||||
config.disk_config.disk_encryption.iter_time = 2000
|
||||
info(f'✓ Adjusted iteration time: {old_time}ms → 2000ms')
|
||||
else:
|
||||
info('✓ Iteration time: 2000ms (optimal)')
|
||||
else:
|
||||
warn('⚠ Root partition is NOT encrypted')
|
||||
warn(' Omarchy recommends LUKS encryption for security')
|
||||
validation_warnings.append('no_encryption')
|
||||
else:
|
||||
warn('⚠ Could not identify root partition')
|
||||
validation_warnings.append('no_root')
|
||||
|
||||
if validation_warnings and interactive:
|
||||
import subprocess
|
||||
import shutil
|
||||
|
||||
gum_path = shutil.which('gum')
|
||||
if gum_path:
|
||||
warn('')
|
||||
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['gum', 'choose', '--header', 'Validation warnings detected. What would you like to do?',
|
||||
'Re-edit partitions', 'Continue anyway', 'Abort'],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
|
||||
choice = result.stdout.strip() if result.stdout else ''
|
||||
|
||||
if choice == 'Re-edit partitions':
|
||||
return 'RE_EDIT'
|
||||
elif choice == 'Abort':
|
||||
return 'ABORT'
|
||||
else:
|
||||
info('Continuing despite warnings')
|
||||
return 'CONTINUE'
|
||||
|
||||
except (subprocess.CalledProcessError, KeyboardInterrupt):
|
||||
return 'ABORT'
|
||||
|
||||
return 'CONTINUE'
|
||||
|
||||
|
||||
def apply_omarchy_partition_defaults():
|
||||
import archinstall.lib.interactions.disk_conf as disk_conf_module
|
||||
from archinstall.lib.models.device import (
|
||||
PartitionModification, ModificationStatus, PartitionType,
|
||||
Size, Unit, SectorSize, FilesystemType, PartitionFlag,
|
||||
DeviceModification, BDevice
|
||||
)
|
||||
from archinstall.lib.interactions.disk_conf import get_default_btrfs_subvols
|
||||
from archinstall.lib.disk.device_handler import device_handler
|
||||
|
||||
def _boot_partition_2gib(sector_size: SectorSize, using_gpt: bool) -> PartitionModification:
|
||||
flags = [PartitionFlag.BOOT]
|
||||
size = Size(2, Unit.GiB, sector_size)
|
||||
start = Size(1, Unit.MiB, sector_size)
|
||||
if using_gpt:
|
||||
flags.append(PartitionFlag.ESP)
|
||||
|
||||
return PartitionModification(
|
||||
status=ModificationStatus.Create,
|
||||
type=PartitionType.Primary,
|
||||
start=start,
|
||||
length=size,
|
||||
mountpoint=Path('/boot'),
|
||||
fs_type=FilesystemType.Fat32,
|
||||
flags=flags,
|
||||
)
|
||||
|
||||
def _select_main_filesystem_btrfs() -> FilesystemType:
|
||||
return FilesystemType.Btrfs
|
||||
|
||||
def _select_mount_options_compressed() -> list[str]:
|
||||
return ['compress=zstd']
|
||||
|
||||
def _suggest_single_disk_auto_subvolumes(
|
||||
device: BDevice,
|
||||
filesystem_type: FilesystemType | None = None,
|
||||
separate_home: bool | None = None,
|
||||
):
|
||||
if not filesystem_type:
|
||||
filesystem_type = FilesystemType.Btrfs
|
||||
|
||||
if filesystem_type == FilesystemType.Btrfs:
|
||||
using_subvolumes = True
|
||||
mount_options = ['compress=zstd']
|
||||
else:
|
||||
using_subvolumes = False
|
||||
mount_options = []
|
||||
|
||||
sector_size = device.device_info.sector_size
|
||||
device_modification = DeviceModification(device, wipe=True)
|
||||
using_gpt = device_handler.partition_table.is_gpt()
|
||||
|
||||
boot_partition = _boot_partition_2gib(sector_size, using_gpt)
|
||||
device_modification.add_partition(boot_partition)
|
||||
|
||||
total_size = device.device_info.total_size
|
||||
available_space = total_size - boot_partition.length - Size(1, Unit.MiB, sector_size)
|
||||
|
||||
root_partition = PartitionModification(
|
||||
status=ModificationStatus.Create,
|
||||
type=PartitionType.Primary,
|
||||
start=boot_partition.start + boot_partition.length,
|
||||
length=available_space,
|
||||
mountpoint=None if using_subvolumes else Path('/'),
|
||||
fs_type=filesystem_type,
|
||||
mount_options=mount_options,
|
||||
)
|
||||
|
||||
if using_subvolumes:
|
||||
root_partition.btrfs_subvols = get_default_btrfs_subvols()
|
||||
|
||||
device_modification.add_partition(root_partition)
|
||||
return device_modification
|
||||
|
||||
disk_conf_module._boot_partition = _boot_partition_2gib
|
||||
disk_conf_module.select_main_filesystem_format = _select_main_filesystem_btrfs
|
||||
disk_conf_module.select_mount_options = _select_mount_options_compressed
|
||||
disk_conf_module.suggest_single_disk_layout = _suggest_single_disk_auto_subvolumes
|
||||
|
||||
|
||||
def load_config(config_file: Path, creds_file: Path | None = None):
|
||||
from archinstall.lib.args import ArchConfig, Arguments
|
||||
|
||||
with open(config_file) as f:
|
||||
config_data = json.load(f)
|
||||
|
||||
if creds_file and creds_file.exists():
|
||||
with open(creds_file) as f:
|
||||
creds_data = json.load(f)
|
||||
config_data.update(creds_data)
|
||||
|
||||
args = Arguments(
|
||||
config=config_file,
|
||||
creds=creds_file,
|
||||
mountpoint=Path('/mnt'),
|
||||
silent=True,
|
||||
)
|
||||
|
||||
return ArchConfig.from_config(config_data, args)
|
||||
|
||||
|
||||
def save_config(config, output_file: Path):
|
||||
from archinstall.lib.output import info
|
||||
|
||||
try:
|
||||
config_dict = config.safe_json()
|
||||
with open(output_file, 'w') as f:
|
||||
json.dump(config_dict, f, indent=2, default=str)
|
||||
info(f'✓ Configuration saved to: {output_file}')
|
||||
except Exception as e:
|
||||
from archinstall.lib.output import error
|
||||
error(f'Failed to save config: {e}')
|
||||
raise
|
||||
|
||||
|
||||
def main():
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description='Omarchy Disk Configuration Tool')
|
||||
parser.add_argument('--config', type=Path, required=True, help='Path to config file')
|
||||
parser.add_argument('--creds', type=Path, help='Path to credentials file')
|
||||
parser.add_argument('--output', type=Path, help='Output path (default: overwrites input)')
|
||||
parser.add_argument('--non-interactive', action='store_true', help='Skip interactive prompts')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
output_file = args.output or args.config
|
||||
|
||||
if not args.config.exists():
|
||||
print(f'ERROR: Config file not found: {args.config}', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if args.creds and not args.creds.exists():
|
||||
print(f'ERROR: Credentials file not found: {args.creds}', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
from archinstall.lib.output import info, error
|
||||
from archinstall.lib.disk.disk_menu import DiskLayoutConfigurationMenu
|
||||
from archinstall.tui.curses_menu import Tui
|
||||
|
||||
apply_omarchy_partition_defaults()
|
||||
|
||||
info('Loading configuration...')
|
||||
config = load_config(args.config, args.creds)
|
||||
|
||||
if not config.disk_config:
|
||||
error('No disk configuration found in config file')
|
||||
sys.exit(1)
|
||||
|
||||
while True:
|
||||
info('Launching partition editor...')
|
||||
|
||||
with Tui():
|
||||
edited_disk_config = DiskLayoutConfigurationMenu(config.disk_config).run()
|
||||
if edited_disk_config:
|
||||
config.disk_config = edited_disk_config
|
||||
info('✓ Partition configuration updated')
|
||||
else:
|
||||
info('No changes made in partition editor')
|
||||
|
||||
interactive = not args.non_interactive
|
||||
validation_result = validate_disk_config(config, interactive=interactive)
|
||||
|
||||
if validation_result == 'RE_EDIT':
|
||||
continue
|
||||
elif validation_result == 'ABORT':
|
||||
info('Disk configuration cancelled by user')
|
||||
sys.exit(1)
|
||||
else:
|
||||
break
|
||||
|
||||
save_config(config, output_file)
|
||||
info('✓ Disk configuration complete!')
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print('\nCancelled by user', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f'ERROR: {e}', file=sys.stderr)
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -28,8 +28,6 @@ if [[ -n "$font_name" && "$font_name" != "CNCLD" ]]; then
|
||||
omarchy-restart-waybar
|
||||
omarchy-restart-swayosd
|
||||
omarchy-restart-walker
|
||||
|
||||
omarchy-hook font-set "$font_name"
|
||||
else
|
||||
echo "Font '$font_name' not found."
|
||||
exit 1
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "Usage: omarchy-hook [name] [args...]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
HOOK=$1
|
||||
HOOK_PATH="$HOME/.config/omarchy/hooks/$1"
|
||||
shift
|
||||
|
||||
if [[ -f $HOOK_PATH ]]; then
|
||||
bash "$HOOK_PATH" "$@"
|
||||
fi
|
||||
@@ -1,22 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Toggle to pop-out a tile to stay fixed on a display basis.
|
||||
|
||||
active=$(hyprctl activewindow -j)
|
||||
pinned=$(echo "$active" | jq .pinned)
|
||||
addr=$(echo "$active" | jq -r ".address")
|
||||
[ -z "$addr" ] && { echo "No active window"; exit 0; }
|
||||
|
||||
if [ "$pinned" = "true" ]; then
|
||||
hyprctl -q --batch \
|
||||
"dispatch pin address:$addr;" \
|
||||
"dispatch togglefloating address:$addr;" \
|
||||
"dispatch tagwindow -pop address:$addr;"
|
||||
else
|
||||
hyprctl -q --batch \
|
||||
"dispatch togglefloating address:$addr;" \
|
||||
"dispatch centerwindow address:$addr;" \
|
||||
"dispatch pin address:$addr;" \
|
||||
"dispatch alterzorder top address:$addr;" \
|
||||
"dispatch tagwindow +pop address:$addr;"
|
||||
fi
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
workspace_id=$(hyprctl activeworkspace -j | jq -r .id)
|
||||
gaps=$(hyprctl workspacerules -j | jq -r ".[] | select(.workspaceString==\"$workspace_id\") | .gapsOut[0] // 0")
|
||||
|
||||
if [[ $gaps == "0" ]]; then
|
||||
hyprctl keyword "workspace $workspace_id, gapsout:10, gapsin:5, bordersize:2"
|
||||
else \
|
||||
hyprctl keyword "workspace $workspace_id, gapsout:0, gapsin:0, bordersize:0"
|
||||
fi
|
||||
@@ -1,258 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Omarchy Install
|
||||
|
||||
Installs Arch Linux with Omarchy customizations using archinstall as a library.
|
||||
For disk configuration, use omarchy-disk-config.
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def load_config(config_file: Path, creds_file: Path | None = None):
|
||||
from archinstall.lib.args import ArchConfig, Arguments
|
||||
|
||||
with open(config_file) as f:
|
||||
config_data = json.load(f)
|
||||
|
||||
if creds_file and creds_file.exists():
|
||||
with open(creds_file) as f:
|
||||
creds_data = json.load(f)
|
||||
config_data.update(creds_data)
|
||||
|
||||
args = Arguments(
|
||||
config=config_file,
|
||||
creds=creds_file,
|
||||
mountpoint=Path('/mnt'),
|
||||
silent=True,
|
||||
skip_ntp=True,
|
||||
skip_wkd=True,
|
||||
)
|
||||
|
||||
return ArchConfig.from_config(config_data, args)
|
||||
|
||||
|
||||
def load_omarchy_packages() -> list[str]:
|
||||
omarchy_path = Path('/usr/share/omarchy/install')
|
||||
packages = []
|
||||
|
||||
base_packages_file = omarchy_path / 'omarchy-base.packages'
|
||||
if base_packages_file.exists():
|
||||
with open(base_packages_file) as f:
|
||||
packages.extend([line.strip() for line in f if line.strip() and not line.startswith('#')])
|
||||
|
||||
return packages
|
||||
|
||||
|
||||
def perform_installation(config_file: Path, creds_file: Path | None = None) -> None:
|
||||
from archinstall.lib.disk.filesystem import FilesystemHandler
|
||||
from archinstall.lib.installer import Installer
|
||||
from archinstall.lib.models.device import DiskLayoutType, EncryptionType
|
||||
from archinstall.lib.output import error, info
|
||||
from archinstall.lib.profile.profiles_handler import profile_handler
|
||||
from archinstall.lib.authentication.authentication_handler import auth_handler
|
||||
|
||||
start_time = time.time()
|
||||
|
||||
info('Loading configuration...')
|
||||
config = load_config(config_file, creds_file)
|
||||
|
||||
if not config.disk_config:
|
||||
error('No disk configuration found in config file')
|
||||
error('Use omarchy-disk-config to configure disk layout first')
|
||||
sys.exit(1)
|
||||
|
||||
disk_config = config.disk_config
|
||||
|
||||
if disk_config.config_type != DiskLayoutType.Pre_mount:
|
||||
info('Performing filesystem operations...')
|
||||
fs_handler = FilesystemHandler(disk_config)
|
||||
fs_handler.perform_filesystem_operations()
|
||||
|
||||
mountpoint = Path('/mnt')
|
||||
|
||||
info('Loading Omarchy base packages...')
|
||||
omarchy_packages = load_omarchy_packages()
|
||||
|
||||
info('Starting Omarchy installation...')
|
||||
|
||||
with Installer(
|
||||
mountpoint,
|
||||
disk_config,
|
||||
kernels=config.kernels or ['linux'],
|
||||
) as installation:
|
||||
|
||||
info('Mounting filesystems...')
|
||||
if disk_config.config_type != DiskLayoutType.Pre_mount:
|
||||
installation.mount_ordered_layout()
|
||||
|
||||
installation.sanity_check()
|
||||
|
||||
if disk_config.disk_encryption and disk_config.disk_encryption.encryption_type != EncryptionType.NoEncryption:
|
||||
info('Generating encryption keys...')
|
||||
installation.generate_key_files()
|
||||
|
||||
if config.mirror_config:
|
||||
info('Configuring mirrors...')
|
||||
installation.set_mirrors(config.mirror_config, on_target=False)
|
||||
|
||||
info('Installing base system...')
|
||||
installation.minimal_installation(
|
||||
optional_repositories=config.mirror_config.optional_repositories if config.mirror_config else [],
|
||||
mkinitcpio=not config.uki,
|
||||
hostname=config.hostname,
|
||||
locale_config=config.locale_config,
|
||||
)
|
||||
|
||||
if config.mirror_config:
|
||||
installation.set_mirrors(config.mirror_config, on_target=True)
|
||||
|
||||
if config.swap:
|
||||
info('Setting up swap...')
|
||||
installation.setup_swap('zram')
|
||||
|
||||
all_packages = omarchy_packages + (config.packages or [])
|
||||
if all_packages:
|
||||
info(f'Installing {len(all_packages)} packages...')
|
||||
installation.add_additional_packages(all_packages)
|
||||
|
||||
if config.bootloader:
|
||||
info(f'Installing bootloader: {config.bootloader.value}...')
|
||||
installation.add_bootloader(config.bootloader, config.uki)
|
||||
|
||||
if config.network_config:
|
||||
info('Configuring network...')
|
||||
config.network_config.install_network_config(installation, config.profile_config)
|
||||
|
||||
if config.auth_config and config.auth_config.users:
|
||||
info('Creating users...')
|
||||
installation.create_users(config.auth_config.users)
|
||||
auth_handler.setup_auth(installation, config.auth_config, config.hostname)
|
||||
|
||||
if config.app_config:
|
||||
info('Installing applications...')
|
||||
from archinstall.lib.applications.application_handler import application_handler
|
||||
application_handler.install_applications(installation, config.app_config)
|
||||
|
||||
if config.profile_config:
|
||||
info('Installing profile...')
|
||||
profile_handler.install_profile_config(installation, config.profile_config)
|
||||
|
||||
if config.timezone:
|
||||
installation.set_timezone(config.timezone)
|
||||
|
||||
if config.ntp:
|
||||
installation.activate_time_synchronization()
|
||||
|
||||
from archinstall.lib.installer import accessibility_tools_in_use
|
||||
if accessibility_tools_in_use():
|
||||
installation.enable_espeakup()
|
||||
|
||||
if config.auth_config and config.auth_config.root_enc_password:
|
||||
from archinstall.lib.models.users import User
|
||||
root_user = User('root', config.auth_config.root_enc_password, False)
|
||||
installation.set_user_password(root_user)
|
||||
|
||||
if config.profile_config and config.profile_config.profile:
|
||||
config.profile_config.profile.post_install(installation)
|
||||
|
||||
if config.services:
|
||||
info('Enabling services...')
|
||||
installation.enable_service(config.services)
|
||||
|
||||
if disk_config.has_default_btrfs_vols():
|
||||
btrfs_options = disk_config.btrfs_options
|
||||
snapshot_config = btrfs_options.snapshot_config if btrfs_options else None
|
||||
snapshot_type = snapshot_config.snapshot_type if snapshot_config else None
|
||||
if snapshot_type:
|
||||
installation.setup_btrfs_snapshot(snapshot_type, config.bootloader)
|
||||
|
||||
info('Mounting offline resources for chroot access...')
|
||||
from archinstall.lib.general import SysCommand
|
||||
import os
|
||||
import shutil
|
||||
|
||||
offline_mirror_src = Path('/var/cache/omarchy/mirror/offline')
|
||||
offline_mirror_dst = mountpoint / 'var/cache/omarchy/mirror/offline'
|
||||
packages_src = Path('/opt/packages')
|
||||
packages_dst = mountpoint / 'opt/packages'
|
||||
|
||||
os.makedirs(offline_mirror_dst, exist_ok=True)
|
||||
os.makedirs(packages_dst, exist_ok=True)
|
||||
|
||||
if offline_mirror_src.exists():
|
||||
SysCommand(f'mount --bind {offline_mirror_src} {offline_mirror_dst}')
|
||||
|
||||
if packages_src.exists():
|
||||
SysCommand(f'mount --bind {packages_src} {packages_dst}')
|
||||
|
||||
pacman_conf_src = Path('/etc/pacman.conf')
|
||||
pacman_conf_dst = mountpoint / 'etc/pacman.conf'
|
||||
if pacman_conf_src.exists():
|
||||
shutil.copy(pacman_conf_src, pacman_conf_dst)
|
||||
|
||||
info('Copying user info to chroot...')
|
||||
os.makedirs(mountpoint / 'tmp', exist_ok=True)
|
||||
|
||||
if os.path.exists('/tmp/omarchy-user-name.txt'):
|
||||
shutil.copy('/tmp/omarchy-user-name.txt', mountpoint / 'tmp/omarchy-user-name.txt')
|
||||
if os.path.exists('/tmp/omarchy-user-email.txt'):
|
||||
shutil.copy('/tmp/omarchy-user-email.txt', mountpoint / 'tmp/omarchy-user-email.txt')
|
||||
|
||||
if config.custom_commands:
|
||||
info('Running Omarchy custom commands...')
|
||||
from archinstall.lib.installer import run_custom_user_commands
|
||||
run_custom_user_commands(config.custom_commands, installation)
|
||||
|
||||
info('Generating fstab...')
|
||||
installation.genfstab()
|
||||
|
||||
end_time = time.time()
|
||||
duration_seconds = int(end_time - start_time)
|
||||
duration_mins = duration_seconds // 60
|
||||
duration_secs = duration_seconds % 60
|
||||
|
||||
timing_file = mountpoint / 'tmp/omarchy-install-time.txt'
|
||||
with open(timing_file, 'w') as f:
|
||||
f.write(f"{duration_mins}m {duration_secs}s\n")
|
||||
|
||||
info(f'Installation complete! Total time: {duration_mins}m {duration_secs}s')
|
||||
|
||||
|
||||
def main():
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description='Omarchy Install')
|
||||
parser.add_argument('--config', type=Path, required=True, help='Path to config file')
|
||||
parser.add_argument('--creds', type=Path, help='Path to credentials file')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.config.exists():
|
||||
print(f'ERROR: Config file not found: {args.config}', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if args.creds and not args.creds.exists():
|
||||
print(f'ERROR: Credentials file not found: {args.creds}', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
perform_installation(
|
||||
config_file=args.config,
|
||||
creds_file=args.creds,
|
||||
)
|
||||
except KeyboardInterrupt:
|
||||
print('\nInstallation cancelled by user', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f'ERROR: Installation failed: {e}', file=sys.stderr)
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
options=("MySQL" "PostgreSQL" "Redis" "MongoDB" "MariaDB" "MSSQL")
|
||||
options=("MySQL" "PostgreSQL" "Redis" "MongoDB" "MariaDB")
|
||||
|
||||
if [[ "$#" -eq 0 ]]; then
|
||||
choices=$(printf "%s\n" "${options[@]}" | gum choose --header "Select database (return to install, esc to cancel)") || main_menu
|
||||
@@ -16,7 +16,6 @@ if [[ -n "$choices" ]]; then
|
||||
MariaDB) sudo docker run -d --restart unless-stopped -p "127.0.0.1:3306:3306" --name=mariadb11 -e MARIADB_ROOT_PASSWORD= -e MARIADB_ALLOW_EMPTY_ROOT_PASSWORD=true mariadb:11.8 ;;
|
||||
Redis) sudo docker run -d --restart unless-stopped -p "127.0.0.1:6379:6379" --name=redis redis:7 ;;
|
||||
MongoDB) sudo docker run -d --restart unless-stopped -p "127.0.0.1:27017:27017" --name mongodb -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=admin123 mongo:noble ;;
|
||||
MSSQL) sudo docker run -d --restart unless-stopped -p "127.0.0.1:1433:1433" --name mssql -e MSSQL_PID=Developer -e ACCEPT_EULA=Y -e "MSSQL_SA_PASSWORD=@dmin123" mcr.microsoft.com/mssql/server:2022-CU12-ubuntu-22.04 ;;
|
||||
esac
|
||||
done
|
||||
else
|
||||
|
||||
@@ -4,5 +4,5 @@ echo "Installing all dependencies..."
|
||||
omarchy-pkg-add dropbox dropbox-cli libappindicator-gtk3 python-gpgme nautilus-dropbox
|
||||
|
||||
echo "Starting Dropbox..."
|
||||
uwsm-app -- dropbox-cli start &>/dev/null &
|
||||
uwsm app -- dropbox-cli start &>/dev/null &
|
||||
echo "See Dropbox icon behind hover tray in top right and right-click for setup."
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Omarchy Final Configurations Installer
|
||||
#
|
||||
# This script runs from archinstall's custom_commands after base packages
|
||||
# and user creation. It switches to the created user and runs install.sh
|
||||
# to complete package installation and system configuration.
|
||||
#
|
||||
# archinstall runs custom_commands as root via:
|
||||
# arch-chroot -S /mnt bash /var/tmp/user-command.0.sh
|
||||
#
|
||||
|
||||
set -eEo pipefail
|
||||
|
||||
# Setup comprehensive logging for chroot execution
|
||||
# This ensures all output is captured even though we're running inside chroot
|
||||
CHROOT_LOG_FILE="/var/log/omarchy-install-chroot.log"
|
||||
mkdir -p "$(dirname "$CHROOT_LOG_FILE")"
|
||||
touch "$CHROOT_LOG_FILE"
|
||||
|
||||
# Redirect all output to both the log file and stdout
|
||||
# This way:
|
||||
# 1. Output is saved to /var/log/omarchy-install-chroot.log (inside chroot = /mnt/var/log on ISO)
|
||||
# 2. Output still goes to stdout so arch-chroot can potentially capture it
|
||||
# 3. We use exec to redirect the entire script's output from this point forward
|
||||
exec > >(tee -a "$CHROOT_LOG_FILE") 2>&1
|
||||
|
||||
# Log script start with timestamp
|
||||
echo "========================================"
|
||||
echo "Omarchy Chroot Install Starting"
|
||||
echo "Started at: $(date '+%Y-%m-%d %H:%M:%S')"
|
||||
echo "Log file: $CHROOT_LOG_FILE"
|
||||
echo "========================================"
|
||||
echo
|
||||
|
||||
# Find the first non-root user (UID >= 1000, < 60000)
|
||||
OMARCHY_USER=$(getent passwd | awk -F: '$3 >= 1000 && $3 < 60000 {print $1; exit}')
|
||||
|
||||
if [[ -z "$OMARCHY_USER" ]]; then
|
||||
echo "ERROR: No non-root user found!"
|
||||
echo "Users created:"
|
||||
getent passwd | awk -F: '$3 >= 1000 {print $1, $3}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Setting up Omarchy for user: $OMARCHY_USER"
|
||||
|
||||
# Setup passwordless sudo (will be removed by post-install)
|
||||
echo "Setting up passwordless sudo..."
|
||||
mkdir -p /etc/sudoers.d
|
||||
cat >/etc/sudoers.d/99-omarchy-installer <<EOF
|
||||
root ALL=(ALL:ALL) NOPASSWD: ALL
|
||||
%wheel ALL=(ALL:ALL) NOPASSWD: ALL
|
||||
$OMARCHY_USER ALL=(ALL:ALL) NOPASSWD: ALL
|
||||
EOF
|
||||
chmod 440 /etc/sudoers.d/99-omarchy-installer
|
||||
|
||||
# Get user info from /tmp (written by configurator)
|
||||
if [[ -f /tmp/omarchy-user-name.txt ]]; then
|
||||
OMARCHY_USER_NAME=$(cat /tmp/omarchy-user-name.txt)
|
||||
else
|
||||
OMARCHY_USER_NAME=""
|
||||
fi
|
||||
|
||||
if [[ -f /tmp/omarchy-user-email.txt ]]; then
|
||||
OMARCHY_USER_EMAIL=$(cat /tmp/omarchy-user-email.txt)
|
||||
else
|
||||
OMARCHY_USER_EMAIL=""
|
||||
fi
|
||||
|
||||
# Run install.sh as the user
|
||||
echo "========================================"
|
||||
echo "Running Omarchy installation as user: $OMARCHY_USER"
|
||||
echo "========================================"
|
||||
echo
|
||||
|
||||
# Use runuser instead of su for better output handling
|
||||
# runuser doesn't go through PAM and preserves stdout/stderr better
|
||||
runuser -u "$OMARCHY_USER" -- bash -c "
|
||||
set -eEo pipefail
|
||||
export PYTHONUNBUFFERED=1
|
||||
export OMARCHY_CHROOT_INSTALL=1
|
||||
export OMARCHY_ARCHINSTALL_WRAPPER=1
|
||||
export OMARCHY_USER='$OMARCHY_USER'
|
||||
export OMARCHY_USER_NAME='$OMARCHY_USER_NAME'
|
||||
export OMARCHY_USER_EMAIL='$OMARCHY_USER_EMAIL'
|
||||
cd ~
|
||||
source /usr/share/omarchy/install.sh
|
||||
"
|
||||
|
||||
exit_code=$?
|
||||
|
||||
if [[ $exit_code -eq 0 ]]; then
|
||||
echo
|
||||
echo "========================================"
|
||||
echo "Omarchy install.sh completed successfully!"
|
||||
echo "========================================"
|
||||
echo
|
||||
echo "========================================"
|
||||
echo "Omarchy Chroot Install Completed"
|
||||
echo "Finished at: $(date '+%Y-%m-%d %H:%M:%S')"
|
||||
echo "Log file: $CHROOT_LOG_FILE"
|
||||
echo "========================================"
|
||||
else
|
||||
echo
|
||||
echo "========================================"
|
||||
echo "ERROR: Omarchy install.sh exited with code $exit_code"
|
||||
echo "========================================"
|
||||
exit $exit_code
|
||||
fi
|
||||
@@ -7,41 +7,13 @@ fi
|
||||
|
||||
package="$1"
|
||||
|
||||
# Map package name to desktop entry ID
|
||||
case "$package" in
|
||||
alacritty)
|
||||
desktop_id="Alacritty.desktop"
|
||||
;;
|
||||
ghostty)
|
||||
desktop_id="com.mitchellh.ghostty.desktop"
|
||||
;;
|
||||
kitty)
|
||||
desktop_id="kitty.desktop"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown terminal: $package"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Install package
|
||||
if omarchy-pkg-add $package; then
|
||||
# Set as default terminal
|
||||
echo "Setting $package as new default terminal..."
|
||||
sed -i "/export TERMINAL=/ c\export TERMINAL=$package" ~/.config/uwsm/default
|
||||
omarchy-pkg-add $package
|
||||
|
||||
# Copy custom desktop entry for alacritty with X-TerminalArg* keys
|
||||
if [ "$package" = "alacritty" ]; then
|
||||
mkdir -p ~/.local/share/applications
|
||||
cp "$OMARCHY_PATH/applications/Alacritty.desktop" ~/.local/share/applications/
|
||||
fi
|
||||
# Set as default terminal
|
||||
echo "Setting $package as new default terminal..."
|
||||
sed -i "/export TERMINAL=/ c\export TERMINAL=$package" ~/.config/uwsm/default
|
||||
|
||||
# Update xdg-terminals.list to prioritize the proper terminal
|
||||
cat > ~/.config/xdg-terminals.list << EOF
|
||||
# Terminal emulator preference order for xdg-terminal-exec
|
||||
# The first found and valid terminal will be used
|
||||
$desktop_id
|
||||
EOF
|
||||
else
|
||||
echo "Failed to install $package"
|
||||
fi
|
||||
# Relaunch is needed for new default to take effect
|
||||
echo
|
||||
gum confirm "Relaunch Hyprland to use new terminal?" && uwsm stop
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
echo "Installing VSCode..."
|
||||
omarchy-pkg-add visual-studio-code-bin
|
||||
|
||||
mkdir -p ~/.vscode ~/.config/Code/User
|
||||
mkdir -p ~/.vscode
|
||||
|
||||
cat > ~/.vscode/argv.json << 'EOF'
|
||||
// This configuration file allows you to pass permanent command line arguments to VS Code.
|
||||
@@ -18,10 +18,4 @@ cat > ~/.vscode/argv.json << 'EOF'
|
||||
}
|
||||
EOF
|
||||
|
||||
# Ensure VSC's own auto-update feature is turned off
|
||||
printf '{\n "update.mode": "none"\n}\n' > ~/.config/Code/User/settings.json
|
||||
|
||||
# Apply Omarchy theme to VSCode
|
||||
omarchy-theme-set-vscode
|
||||
|
||||
setsid gtk-launch code
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
exec setsid uwsm-app -- xdg-terminal-exec --app-id=com.omarchy.Omarchy -e bash -c 'fastfetch; read -n 1 -s'
|
||||
exec setsid uwsm app -- alacritty --class=Omarchy -o font.size=9 -e bash -c 'fastfetch; read -n 1 -s'
|
||||
|
||||
@@ -9,4 +9,4 @@ else
|
||||
private_flag="--incognito"
|
||||
fi
|
||||
|
||||
exec setsid uwsm-app -- "$browser_exec" "${@/--private/$private_flag}"
|
||||
exec setsid uwsm app -- "$browser_exec" "${@/--private/$private_flag}"
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
omarchy-cmd-present "$EDITOR" || EDITOR=nvim
|
||||
|
||||
case "$EDITOR" in
|
||||
nvim | vim | nano | micro | hx | helix)
|
||||
exec setsid uwsm-app -- xdg-terminal-exec "$EDITOR" "$@"
|
||||
case "${EDITOR:-nvim}" in
|
||||
nvim | vim | nano | micro | hx)
|
||||
exec setsid uwsm app -- "$TERMINAL" -e "$EDITOR" "$@"
|
||||
;;
|
||||
*)
|
||||
exec setsid uwsm-app -- "$EDITOR" "$@"
|
||||
exec setsid uwsm app -- "$EDITOR" "$@"
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
cmd="$*"
|
||||
exec setsid uwsm-app -- xdg-terminal-exec --app-id=com.omarchy.Omarchy --title=Omarchy -e bash -c "omarchy-show-logo; $cmd; omarchy-show-done"
|
||||
exec setsid uwsm app -- alacritty --class=Omarchy --title=Omarchy -e bash -c "omarchy-show-logo; $cmd; omarchy-show-done"
|
||||
|
||||
@@ -6,7 +6,7 @@ if (($# == 0)); then
|
||||
fi
|
||||
|
||||
WINDOW_PATTERN="$1"
|
||||
LAUNCH_COMMAND="${2:-"uwsm-app -- $WINDOW_PATTERN"}"
|
||||
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
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
if (($# == 0)); then
|
||||
echo "Usage: omarchy-launch-or-focus-webapp [window-pattern] [url-and-flags...]"
|
||||
echo "Usage: omarchy-launch-or-focus-webapp [window-pattern] [url]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
WINDOW_PATTERN="$1"
|
||||
shift
|
||||
LAUNCH_COMMAND="omarchy-launch-webapp $@"
|
||||
|
||||
exec omarchy-launch-or-focus "$WINDOW_PATTERN" "$LAUNCH_COMMAND"
|
||||
exec omarchy-launch-or-focus "$1" "omarchy-launch-webapp '$2'"
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 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 "$@"
|
||||
@@ -7,4 +7,4 @@ google-chrome* | brave-browser* | microsoft-edge* | opera* | vivaldi* | helium-b
|
||||
*) 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}"
|
||||
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}"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
exec setsid uwsm-app -- xdg-terminal-exec --app-id=com.omarchy.Impala -e impala "$@"
|
||||
exec setsid uwsm app -- "$TERMINAL" --class=Impala -e impala "$@"
|
||||
|
||||
@@ -9,4 +9,4 @@ if pgrep -x "1password" >/dev/null; then
|
||||
fi
|
||||
|
||||
# Avoid running screensaver when locked
|
||||
pkill -f "alacritty --class Screensaver"
|
||||
pkill -f "$TERMINAL --class Screensaver"
|
||||
|
||||
@@ -29,15 +29,15 @@ menu() {
|
||||
local index
|
||||
index=$(echo -e "$options" | grep -nxF "$preselect" | cut -d: -f1)
|
||||
if [[ -n "$index" ]]; then
|
||||
args+=("-c" "$index")
|
||||
args+=("-a" "$index")
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "$options" | omarchy-launch-walker --dmenu --width 295 --minheight 1 --maxheight 600 -p "$prompt…" "${args[@]}" 2>/dev/null
|
||||
echo -e "$options" | walker --dmenu --theme dmenu_250 -p "$prompt…" "${args[@]}"
|
||||
}
|
||||
|
||||
terminal() {
|
||||
xdg-terminal-exec --app-id=com.omarchy.Omarchy "$@"
|
||||
alacritty --class=Omarchy -e "$@"
|
||||
}
|
||||
|
||||
present_terminal() {
|
||||
@@ -104,21 +104,21 @@ show_capture_menu() {
|
||||
}
|
||||
|
||||
show_screenshot_menu() {
|
||||
case $(menu "Screenshot" " Snap with Editing\n Straight to Clipboard") in
|
||||
*Editing*) omarchy-cmd-screenshot smart ;;
|
||||
*Clipboard*) omarchy-cmd-screenshot smart clipboard ;;
|
||||
case $(menu "Screenshot" " Region\n Window\n Display") in
|
||||
*Region*) omarchy-cmd-screenshot ;;
|
||||
*Window*) omarchy-cmd-screenshot window ;;
|
||||
*Display*) omarchy-cmd-screenshot output ;;
|
||||
*) show_capture_menu ;;
|
||||
esac
|
||||
}
|
||||
|
||||
show_screenrecord_menu() {
|
||||
case $(menu "Screenrecord" " Region\n Region + Audio\n Display\n Display + Audio\n Display + Webcam") in
|
||||
*"Region + Audio"*) omarchy-cmd-screenrecord region --with-audio ;;
|
||||
case $(menu "Screenrecord" " Region\n Region + Audio\n Display\n Display + Audio") in
|
||||
*"Region + Audio"*) omarchy-cmd-screenrecord region audio ;;
|
||||
*Region*) omarchy-cmd-screenrecord ;;
|
||||
*"Display + Audio"*) omarchy-cmd-screenrecord output --with-audio ;;
|
||||
*"Display + Webcam"*) omarchy-cmd-screenrecord output --with-audio --with-webcam ;;
|
||||
*"Display + Audio"*) omarchy-cmd-screenrecord output audio ;;
|
||||
*Display*) omarchy-cmd-screenrecord output ;;
|
||||
*) back_to show_capture_menu ;;
|
||||
*) show_capture_menu ;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ show_theme_menu() {
|
||||
}
|
||||
|
||||
show_font_menu() {
|
||||
theme=$(menu "Font" "$(omarchy-font-list)" "--width 350" "$(omarchy-font-current)")
|
||||
theme=$(menu "Font" "$(omarchy-font-list)" "-w 350" "$(omarchy-font-current)")
|
||||
if [[ "$theme" == "CNCLD" || -z "$theme" ]]; then
|
||||
back_to show_style_menu
|
||||
else
|
||||
@@ -178,7 +178,7 @@ show_setup_menu() {
|
||||
options="$options\n Defaults\n DNS\n Security\n Config"
|
||||
|
||||
case $(menu "Setup" "$options") in
|
||||
*Audio*) xdg-terminal-exec --app-id=com.omarchy.Wiremix -e wiremix ;;
|
||||
*Audio*) $TERMINAL --class=Wiremix -e wiremix ;;
|
||||
*Wifi*)
|
||||
rfkill unblock wifi
|
||||
omarchy-launch-wifi
|
||||
@@ -232,7 +232,7 @@ show_setup_security_menu() {
|
||||
}
|
||||
|
||||
show_install_menu() {
|
||||
case $(menu "Install" " Package\n AUR\n Web App\n TUI\n Service\n Style\n Development\n Editor\n Terminal\n AI\n Windows\n Gaming") in
|
||||
case $(menu "Install" " Package\n AUR\n Web App\n TUI\n Service\n Style\n Development\n Editor\n Terminal\n AI\n Gaming") in
|
||||
*Package*) terminal omarchy-pkg-install ;;
|
||||
*AUR*) terminal omarchy-pkg-aur-install ;;
|
||||
*Web*) present_terminal omarchy-webapp-install ;;
|
||||
@@ -243,7 +243,6 @@ show_install_menu() {
|
||||
*Editor*) show_install_editor_menu ;;
|
||||
*Terminal*) show_install_terminal_menu ;;
|
||||
*AI*) show_install_ai_menu ;;
|
||||
*Windows*) present_terminal "omarchy-windows-vm install" ;;
|
||||
*Gaming*) show_install_gaming_menu ;;
|
||||
*) show_main_menu ;;
|
||||
esac
|
||||
@@ -264,7 +263,7 @@ show_install_editor_menu() {
|
||||
*VSCode*) present_terminal omarchy-install-vscode ;;
|
||||
*Cursor*) install_and_launch "Cursor" "cursor-bin" "cursor" ;;
|
||||
*Zed*) install_and_launch "Zed" "zed" "dev.zed.Zed" ;;
|
||||
*Sublime*) install_and_launch "Sublime Text" "sublime-text-4" "sublime_text" ;;
|
||||
*Sublime*) aur_install_and_launch "Sublime Text" "sublime-text-4" "sublime_text" ;;
|
||||
*Helix*) install "Helix" "helix" ;;
|
||||
*Emacs*) install "Emacs" "emacs-wayland" && systemctl --user enable --now emacs.service ;;
|
||||
*) show_install_menu ;;
|
||||
@@ -287,11 +286,10 @@ show_install_ai_menu() {
|
||||
echo ollama
|
||||
)
|
||||
|
||||
case $(menu "Install" " Claude Code\n Cursor CLI\n Gemini\n OpenAI Codex\n LM Studio\n Ollama\n Crush\n opencode") in
|
||||
case $(menu "Install" " Claude Code\n Gemini [AUR]\n OpenAI Codex [AUR]\n LM Studio\n Ollama\n Crush\n opencode") in
|
||||
*Claude*) install "Claude Code" "claude-code" ;;
|
||||
*Cursor*) install "Cursor CLI" "cursor-cli" ;;
|
||||
*OpenAI*) install "OpenAI Codex" "openai-codex-bin" ;;
|
||||
*Gemini*) install "Gemini" "gemini-cli" ;;
|
||||
*OpenAI*) aur_install "OpenAI Codex" "openai-codex-bin" ;;
|
||||
*Gemini*) aur_install "Gemini" "gemini-cli" ;;
|
||||
*Studio*) install "LM Studio" "lmstudio" ;;
|
||||
*Ollama*) install "Ollama" $ollama_pkg ;;
|
||||
*Crush*) install "Crush" "crush-bin" ;;
|
||||
@@ -304,7 +302,7 @@ show_install_gaming_menu() {
|
||||
case $(menu "Install" " Steam\n RetroArch [AUR]\n Minecraft") in
|
||||
*Steam*) present_terminal omarchy-install-steam ;;
|
||||
*RetroArch*) aur_install_and_launch "RetroArch" "retroarch retroarch-assets libretro libretro-fbneo" "com.libretro.RetroArch.desktop" ;;
|
||||
*Minecraft*) install_and_launch "Minecraft" "minecraft-launcher" "minecraft-launcher" ;;
|
||||
*Minecraft*) aur_install_and_launch "Minecraft [AUR]" "minecraft-launcher" "minecraft-launcher" ;;
|
||||
*) show_install_menu ;;
|
||||
esac
|
||||
}
|
||||
@@ -319,7 +317,7 @@ show_install_style_menu() {
|
||||
}
|
||||
|
||||
show_install_font_menu() {
|
||||
case $(menu "Install" " Meslo LG Mono\n Fira Code\n Victor Code\n Bistream Vera Mono" "--width 350") in
|
||||
case $(menu "Install" " Meslo LG Mono\n Fira Code\n Victor Code\n Bistream Vera Mono" "-w 350") in
|
||||
*Meslo*) install_font "Meslo LG Mono" "ttf-meslo-nerd" "MesloLGL Nerd Font" ;;
|
||||
*Fira*) install_font "Fira Code" "ttf-firacode-nerd" "FiraCode Nerd Font" ;;
|
||||
*Victor*) install_font "Victor Code" "ttf-victor-mono-nerd" "VictorMono Nerd Font" ;;
|
||||
@@ -374,12 +372,11 @@ show_install_elixir_menu() {
|
||||
}
|
||||
|
||||
show_remove_menu() {
|
||||
case $(menu "Remove" " Package\n Web App\n TUI\n Theme\n Windows\n Fingerprint\n Fido2") in
|
||||
case $(menu "Remove" " Package\n Web App\n TUI\n Theme\n Fingerprint\n Fido2") in
|
||||
*Package*) terminal omarchy-pkg-remove ;;
|
||||
*Web*) present_terminal omarchy-webapp-remove ;;
|
||||
*TUI*) present_terminal omarchy-tui-remove ;;
|
||||
*Theme*) present_terminal omarchy-theme-remove ;;
|
||||
*Windows*) present_terminal "omarchy-windows-vm remove" ;;
|
||||
*Fingerprint*) present_terminal "omarchy-setup-fingerprint --remove" ;;
|
||||
*Fido2*) present_terminal "omarchy-setup-fido2 --remove" ;;
|
||||
*) show_main_menu ;;
|
||||
@@ -387,20 +384,26 @@ show_remove_menu() {
|
||||
}
|
||||
|
||||
show_update_menu() {
|
||||
case $(menu "Update" " Omarchy\n Config\n Extra Themes\n Process\n Hardware\n Firmware\n Password\n Timezone\n Time") in
|
||||
case $(menu "Update" " Omarchy\n Branch\n Config\n Extra Themes\n Process\n Hardware\n Password\n Timezone") in
|
||||
*Omarchy*) present_terminal omarchy-update ;;
|
||||
*Branch*) show_update_branch_menu ;;
|
||||
*Config*) show_update_config_menu ;;
|
||||
*Themes*) present_terminal omarchy-theme-update ;;
|
||||
*Process*) show_update_process_menu ;;
|
||||
*Hardware*) show_update_hardware_menu ;;
|
||||
*Firmware*) present_terminal omarchy-update-firmware ;;
|
||||
*Timezone*) present_terminal omarchy-tz-select ;;
|
||||
*Time*) present_terminal omarchy-update-time ;;
|
||||
*Timezone*) omarchy-cmd-tzupdate ;;
|
||||
*Password*) show_update_password_menu ;;
|
||||
*) show_main_menu ;;
|
||||
esac
|
||||
}
|
||||
|
||||
show_update_branch_menu() {
|
||||
case $(menu "Branch" "master\ndev" "" "$(omarchy-version-branch)") in
|
||||
*master*) present_terminal "omarchy-update-branch master" ;;
|
||||
*dev*) present_terminal "omarchy-update-branch dev" ;;
|
||||
*) show_update_menu ;;
|
||||
esac
|
||||
}
|
||||
show_update_process_menu() {
|
||||
case $(menu "Restart" " Hypridle\n Hyprsunset\n Swayosd\n Walker\n Waybar") in
|
||||
*Hypridle*) omarchy-restart-hypridle ;;
|
||||
@@ -444,12 +447,13 @@ show_update_password_menu() {
|
||||
}
|
||||
|
||||
show_system_menu() {
|
||||
case $(menu "System" " Lock\n Screensaver\n Suspend\n Restart\n Shutdown") in
|
||||
case $(menu "System" " Lock\n Screensaver\n Suspend\n Relaunch\n Restart\n Shutdown") in
|
||||
*Lock*) omarchy-lock-screen ;;
|
||||
*Screensaver*) omarchy-launch-screensaver force ;;
|
||||
*Suspend*) systemctl suspend ;;
|
||||
*Restart*) omarchy-state clear re*-required && systemctl reboot --no-wall ;;
|
||||
*Shutdown*) omarchy-state clear re*-required && systemctl poweroff --no-wall ;;
|
||||
*Relaunch*) omarchy-state clear relaunch-required && sudo systemctl restart sddm ;;
|
||||
*Restart*) omarchy-state clear re*-required && systemctl reboot ;;
|
||||
*Shutdown*) omarchy-state clear re*-required && systemctl poweroff ;;
|
||||
*) back_to show_main_menu ;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -49,17 +49,6 @@ parse_keycodes() {
|
||||
code="${BASH_REMATCH[1]}"
|
||||
symbol=$(lookup_keycode_cached "$code" "$XKB_KEYMAP_CACHE")
|
||||
echo "${line/code:${code}/$symbol}"
|
||||
elif [[ "$line" =~ mouse:([0-9]+) ]]; then
|
||||
code="${BASH_REMATCH[1]}"
|
||||
|
||||
case "$code" in
|
||||
272) symbol="LEFT MOUSE BUTTON" ;;
|
||||
273) symbol="RIGHT MOUSE BUTTON" ;;
|
||||
274) symbol="MIDDLE MOUSE BUTTON" ;;
|
||||
*) symbol="mouse:${code}" ;;
|
||||
esac
|
||||
|
||||
echo "${line/mouse:${code}/$symbol}"
|
||||
else
|
||||
echo "$line"
|
||||
fi
|
||||
@@ -89,8 +78,8 @@ dynamic_bindings() {
|
||||
jq -r '.[] | {modmask, key, keycode, description, dispatcher, arg} | "\(.modmask),\(.key)@\(.keycode),\(.description),\(.dispatcher),\(.arg)"' |
|
||||
sed -r \
|
||||
-e 's/null//' \
|
||||
-e 's,~/.local/share/omarchy/bin/,,' \
|
||||
-e 's,uwsm app -- ,,' \
|
||||
-e 's,uwsm-app -- ,,' \
|
||||
-e 's/@0//' \
|
||||
-e 's/,@/,code:/' \
|
||||
-e 's/^0,/,/' \
|
||||
@@ -111,11 +100,6 @@ dynamic_bindings() {
|
||||
-e 's/^77,/SUPER SHIFT CTRL ALT,/'
|
||||
}
|
||||
|
||||
# Hardcoded bindings, like the copy-url extension and such
|
||||
static_bindings() {
|
||||
echo "SHIFT ALT,L,Copy URL from Web App,extension,copy-url"
|
||||
}
|
||||
|
||||
# Parse and format keybindings
|
||||
#
|
||||
# `awk` does the heavy lifting:
|
||||
@@ -162,67 +146,13 @@ parse_bindings() {
|
||||
}'
|
||||
}
|
||||
|
||||
prioritize_entries() {
|
||||
awk '
|
||||
{
|
||||
line = $0
|
||||
prio = 50
|
||||
if (match(line, /Terminal/)) prio = 0
|
||||
if (match(line, /Browser/) && !match(line, /Browser[[:space:]]*\(/)) prio = 1
|
||||
if (match(line, /File manager/)) prio = 2
|
||||
if (match(line, /Launch apps/)) prio = 3
|
||||
if (match(line, /Omarchy menu/)) prio = 4
|
||||
if (match(line, /System menu/)) prio = 5
|
||||
if (match(line, /Theme menu/)) prio = 6
|
||||
if (match(line, /Full screen/)) prio = 7
|
||||
if (match(line, /Close window/)) prio = 8
|
||||
if (match(line, /Toggle window floating/)) prio = 9
|
||||
if (match(line, /Toggle window split/)) prio = 10
|
||||
if (match(line, /Universal/)) prio = 11
|
||||
if (match(line, /Clipboard/)) prio = 12
|
||||
if (match(line, /Emoji picker/)) prio = 13
|
||||
if (match(line, /Color picker/)) prio = 14
|
||||
if (match(line, /Screenshot/)) prio = 15
|
||||
if (match(line, /Screenrecording/)) prio = 16
|
||||
if (match(line, /(Switch|Next|Former|Previous).*workspace/)) prio = 17
|
||||
if (match(line, /Move window to workspace/)) prio = 18
|
||||
if (match(line, /Swap window/)) prio = 19
|
||||
if (match(line, /Move window focus/)) prio = 20
|
||||
if (match(line, /Move window$/)) prio = 21
|
||||
if (match(line, /Resize window/)) prio = 22
|
||||
if (match(line, /Expand window/)) prio = 23
|
||||
if (match(line, /Shrink window/)) prio = 24
|
||||
if (match(line, /scratchpad/)) prio = 25
|
||||
if (match(line, /notification/)) prio = 26
|
||||
if (match(line, /Toggle window transparency/)) prio = 27
|
||||
if (match(line, /Toggle workspace gaps/)) prio = 28
|
||||
if (match(line, /Toggle nightlight/)) prio = 29
|
||||
if (match(line, /group/)) prio = 94
|
||||
if (match(line, /Scroll active workspace/)) prio = 95
|
||||
if (match(line, /Cycle to/)) prio = 96
|
||||
if (match(line, /Reveal active/)) prio = 97
|
||||
if (match(line, /Apple Display/)) prio = 98
|
||||
if (match(line, /XF86/)) prio = 99
|
||||
|
||||
# print "priority<TAB>line"
|
||||
printf "%d\t%s\n", prio, line
|
||||
}' |
|
||||
sort -k1,1n -k2,2 |
|
||||
cut -f2-
|
||||
}
|
||||
|
||||
monitor_height=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .height')
|
||||
menu_height=$((monitor_height * 40 / 100))
|
||||
|
||||
build_keymap_cache
|
||||
|
||||
{
|
||||
dynamic_bindings
|
||||
static_bindings
|
||||
} |
|
||||
dynamic_bindings |
|
||||
sort -u |
|
||||
parse_keycodes |
|
||||
parse_bindings |
|
||||
prioritize_entries |
|
||||
walker --dmenu -p 'Keybindings' --width 800 --height "$menu_height"
|
||||
|
||||
walker --dmenu --theme keybindings -p 'Keybindings' -w 800 -h "$menu_height"
|
||||
|
||||
@@ -8,7 +8,7 @@ mkdir -p "$STATE_DIR"
|
||||
mkdir -p "$STATE_DIR/skipped"
|
||||
|
||||
# Run any pending migrations
|
||||
for file in /usr/share/omarchy/migrations/*.sh; do
|
||||
for file in ~/.local/share/omarchy/migrations/*.sh; do
|
||||
filename=$(basename "$file")
|
||||
|
||||
if [[ ! -f "$STATE_DIR/$filename" && ! -f "$STATE_DIR/skipped/$filename" ]]; then
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
if omarchy-pkg-missing "$@"; then
|
||||
sudo pacman -S --noconfirm --needed "$@" || exit 1
|
||||
fi
|
||||
sudo pacman -S --noconfirm --needed "$@" || exit 1
|
||||
|
||||
for pkg in "$@"; do
|
||||
# Secondary check to handle states where pacman doesn't actually register an error
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
fzf_args=(
|
||||
--multi
|
||||
--preview 'yay -Siia {1}'
|
||||
--preview-label='alt-p: toggle description, alt-b/B: toggle PKGBUILD, alt-j/k: scroll, tab: multi-select'
|
||||
--preview-label='alt-p: toggle description, alt-b/B: toggle PKGBUILD, alt-j/k: scroll, tab: multi-select, F11: maximize'
|
||||
--preview-label-pos='bottom'
|
||||
--preview-window 'down:65%:wrap'
|
||||
--bind 'alt-p:toggle-preview'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
fzf_args=(
|
||||
--multi
|
||||
--preview 'pacman -Sii {1}'
|
||||
--preview-label='alt-p: toggle description, alt-j/k: scroll, tab: multi-select'
|
||||
--preview-label='alt-p: toggle description, alt-j/k: scroll, tab: multi-select, F11: maximize'
|
||||
--preview-label-pos='bottom'
|
||||
--preview-window 'down:65%:wrap'
|
||||
--bind 'alt-p:toggle-preview'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
fzf_args=(
|
||||
--multi
|
||||
--preview 'yay -Qi {1}'
|
||||
--preview-label='alt-p: toggle description, alt-j/k: scroll, tab: multi-select'
|
||||
--preview-label='alt-p: toggle description, alt-j/k: scroll, tab: multi-select, F11: maximize'
|
||||
--preview-label-pos='bottom'
|
||||
--preview-window 'down:65%:wrap'
|
||||
--bind 'alt-p:toggle-preview'
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
# Copy and sync icon files
|
||||
mkdir -p ~/.local/share/icons/hicolor/48x48/apps/
|
||||
cp /usr/share/omarchy/applications/icons/*.png ~/.local/share/icons/hicolor/48x48/apps/
|
||||
cp ~/.local/share/omarchy/applications/icons/*.png ~/.local/share/icons/hicolor/48x48/apps/
|
||||
gtk-update-icon-cache ~/.local/share/icons/hicolor &>/dev/null
|
||||
|
||||
# Copy .desktop declarations
|
||||
mkdir -p ~/.local/share/applications
|
||||
cp /usr/share/omarchy/applications/*.desktop ~/.local/share/applications/
|
||||
cp /usr/share/omarchy/applications/hidden/*.desktop ~/.local/share/applications/
|
||||
cp ~/.local/share/omarchy/applications/*.desktop ~/.local/share/applications/
|
||||
cp ~/.local/share/omarchy/applications/hidden/*.desktop ~/.local/share/applications/
|
||||
|
||||
update-desktop-database ~/.local/share/applications
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script deploys /etc/skel/.config/X/Y/Z -> ~/.config/X/Y/Z
|
||||
# This script deploys ~/.local/share/omarchy/config/X/Y/Z -> ~/.config/X/Y/Z
|
||||
config_file=$1
|
||||
|
||||
if [[ -z "$config_file" ]]; then
|
||||
@@ -8,16 +8,16 @@ if [[ -z "$config_file" ]]; then
|
||||
Usage: $0 [config_file]
|
||||
|
||||
Must provide a file path from the .config directory to be refreshed.
|
||||
To copy /etc/skel/.config/hypr/hyprlock.conf to ~/.config/hypr/hyprlock.conf
|
||||
|
||||
$0 hypr/hyprlock.conf
|
||||
To copy ~/.local/share/omarchy/config/hypr/hyprlock.conf to ~/.config/hypr/hyprlock.conf
|
||||
|
||||
$0 hypr/hyprlock.conf
|
||||
USAGE
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Backup the destination file (with timestamp) to avoid clobbering (Ex: hyprlock.conf.bak.1753817951)
|
||||
user_config_file="${HOME}/.config/$config_file"
|
||||
default_config_file="/etc/skel/.config/$config_file"
|
||||
default_config_file="${HOME}/.local/share/omarchy/config/$config_file"
|
||||
backup_config_file="$user_config_file.bak.$(date +%s)"
|
||||
|
||||
if [[ -f "$user_config_file" ]]; then
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ -f /boot/EFI/linux/omarchy_linux.efi ]] && [[ -f /boot/EFI/linux/$(cat /etc/machine-id)_linux.efi ]]; then
|
||||
echo "Cleanup extra UKI"
|
||||
sudo rm -f /boot/EFI/Linux/$(cat /etc/machine-id)_linux.efi
|
||||
fi
|
||||
echo "Resetting limine config"
|
||||
|
||||
sudo mv /boot/limine.conf /boot/limine.conf.bak
|
||||
|
||||
sudo tee /boot/limine.conf <<EOF >/dev/null
|
||||
### Read more at config document: https://github.com/limine-bootloader/limine/blob/trunk/CONFIG.md
|
||||
#timeout: 3
|
||||
default_entry: 2
|
||||
interface_branding: Omarchy Bootloader
|
||||
interface_branding_color: 2
|
||||
hash_mismatch_panic: no
|
||||
|
||||
term_background: 1a1b26
|
||||
backdrop: 1a1b26
|
||||
|
||||
# Terminal colors (Tokyo Night palette)
|
||||
term_palette: 15161e;f7768e;9ece6a;e0af68;7aa2f7;bb9af7;7dcfff;a9b1d6
|
||||
term_palette_bright: 414868;f7768e;9ece6a;e0af68;7aa2f7;bb9af7;7dcfff;c0caf5
|
||||
|
||||
# Text colors
|
||||
term_foreground: c0caf5
|
||||
term_foreground_bright: c0caf5
|
||||
term_background_bright: 24283b
|
||||
|
||||
EOF
|
||||
|
||||
sudo limine-update
|
||||
sudo limine-snapper-sync
|
||||
@@ -1,3 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
sudo cp -f /usr/share/omarchy/default/pacman/mirrorlist /etc/pacman.d/mirrorlist
|
||||
sudo cp -f ~/.local/share/omarchy/default/pacman/mirrorlist /etc/pacman.d/mirrorlist
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
sudo cp /usr/share/omarchy/default/plymouth/* /usr/share/plymouth/themes/omarchy/
|
||||
sudo cp ~/.local/share/omarchy/default/plymouth/* /usr/share/plymouth/themes/omarchy/
|
||||
sudo plymouth-set-default-theme omarchy
|
||||
|
||||
if command -v limine-mkinitcpio &>/dev/null; then
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
omarchy-refresh-config walker/config.toml
|
||||
omarchy-refresh-config elephant/calc.toml
|
||||
omarchy-refresh-config elephant/desktopapplications.toml
|
||||
omarchy-restart-walker
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$EUID" -eq 0 ]; then
|
||||
echo "Error: This script should not be run as root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "This will reinstall all the default Omarchy packages and reset all default configs.\nWarning: All changes to configs will be lost.\n"
|
||||
|
||||
if gum confirm "Are you sure you want to reinstall and lose all config changes?"; then
|
||||
echo "Reinstalling Omarchy Package"
|
||||
sudo pacman -Syu --noconfirm --needed omarchy
|
||||
|
||||
echo "Reinstalling missing Omarchy packages"
|
||||
mapfile -t packages < <(grep -v '^#' "$OMARCHY_PATH/install/omarchy-base.packages" | grep -v '^$')
|
||||
sudo pacman -Syu --noconfirm --needed "${packages[@]}"
|
||||
|
||||
echo "Resetting all Omarchy configs"
|
||||
cp -R /etc/skel/.config/* ~/.config/
|
||||
|
||||
$(bash $OMARCHY_PATH/install/config/theme.sh)
|
||||
$(bash $OMARCHY_PATH/install/config/git.sh)
|
||||
|
||||
omarchy-refresh-limine
|
||||
omarchy-refresh-plymouth
|
||||
omarchy-nvim-setup
|
||||
fi
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
pkill -x $1
|
||||
setsid uwsm-app -- $1 >/dev/null 2>&1 &
|
||||
setsid uwsm app -- $1 >/dev/null 2>&1 &
|
||||
|
||||
@@ -1,33 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Detect if we're running as root (from pacman hook)
|
||||
if [[ $EUID -eq 0 ]]; then
|
||||
# Find all logged-in users running Hyprland
|
||||
for user_runtime in /run/user/*/; do
|
||||
USER_UID=$(basename "$user_runtime")
|
||||
USER_NAME=$(id -un "$USER_UID" 2>/dev/null)
|
||||
|
||||
# Skip if we can't resolve the username or if no Hyprland session
|
||||
[[ -z "$USER_NAME" ]] && continue
|
||||
[[ ! -S "${user_runtime}hypr/"*"/.socket.sock" ]] && continue
|
||||
|
||||
# Kill existing processes for this user
|
||||
pkill -u "$USER_NAME" elephant
|
||||
pkill -u "$USER_NAME" walker
|
||||
|
||||
# Restart services as this user
|
||||
systemd-run --uid="$USER_NAME" --setenv=XDG_RUNTIME_DIR="/run/user/$USER_UID" \
|
||||
bash -c "
|
||||
setsid uwsm-app -- elephant &
|
||||
setsid uwsm-app -- walker --gapplication-service &
|
||||
"
|
||||
done
|
||||
else
|
||||
# Running as user directly
|
||||
pkill elephant
|
||||
pkill walker
|
||||
|
||||
setsid uwsm-app -- elephant &
|
||||
wait 2
|
||||
setsid uwsm-app -- walker --gapplication-service &
|
||||
fi
|
||||
pkill walker
|
||||
# FIXME: Just deal with the memory leak for now.
|
||||
# See https://github.com/basecamp/omarchy/issues/698
|
||||
setsid uwsm app -- walker --gapplication-service &
|
||||
echo # Always end in success so we don't terminate further running
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Track active Omarchy user for package migrations
|
||||
echo "$USER:$HOME:$XDG_RUNTIME_DIR" > /tmp/omarchy-active-user
|
||||
@@ -2,6 +2,6 @@
|
||||
|
||||
clear
|
||||
echo -e "\033[32m"
|
||||
cat < /usr/share/omarchy/logo.txt
|
||||
cat <~/.local/share/omarchy/logo.txt
|
||||
echo -e "\033[0m"
|
||||
echo
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
COMMAND="$1"
|
||||
OMARCHY_PATH=${OMARCHY_PATH:-$HOME/.local/share/omarchy}
|
||||
|
||||
@@ -19,7 +17,7 @@ create)
|
||||
DESC="$(omarchy-version)"
|
||||
|
||||
echo -e "\e[32mCreate system snapshot\e[0m"
|
||||
|
||||
|
||||
# Get existing snapper config names from CSV output
|
||||
mapfile -t CONFIGS < <(sudo snapper --csvout list-configs | awk -F, 'NR>1 {print $1}')
|
||||
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
BACKGROUNDS_DIR="$HOME/.config/omarchy/current/theme/backgrounds/"
|
||||
CURRENT_BACKGROUND_LINK="$HOME/.config/omarchy/current/background"
|
||||
|
||||
mapfile -d '' -t BACKGROUNDS < <(find -L "$BACKGROUNDS_DIR" -type f -print0 | sort -z)
|
||||
mapfile -d '' -t BACKGROUNDS < <(find "$BACKGROUNDS_DIR" -type f -print0 | sort -z)
|
||||
TOTAL=${#BACKGROUNDS[@]}
|
||||
|
||||
if [[ $TOTAL -eq 0 ]]; then
|
||||
notify-send "No background was found for theme" -t 2000
|
||||
pkill -x swaybg
|
||||
setsid uwsm-app -- swaybg --color '#000000' >/dev/null 2>&1 &
|
||||
setsid uwsm app -- swaybg --color '#000000' >/dev/null 2>&1 &
|
||||
else
|
||||
# Get current background from symlink
|
||||
if [[ -L "$CURRENT_BACKGROUND_LINK" ]]; then
|
||||
@@ -44,5 +44,5 @@ else
|
||||
|
||||
# Relaunch swaybg
|
||||
pkill -x swaybg
|
||||
setsid uwsm-app -- swaybg -i "$CURRENT_BACKGROUND_LINK" -m fill >/dev/null 2>&1 &
|
||||
setsid uwsm app -- swaybg -i "$CURRENT_BACKGROUND_LINK" -m fill >/dev/null 2>&1 &
|
||||
fi
|
||||
|
||||
@@ -24,21 +24,15 @@ ln -nsf "$THEME_PATH" "$CURRENT_THEME_DIR"
|
||||
omarchy-theme-bg-next
|
||||
|
||||
# Restart components to apply new theme
|
||||
if pgrep -x waybar >/dev/null; then
|
||||
omarchy-restart-waybar
|
||||
fi
|
||||
omarchy-restart-waybar
|
||||
omarchy-restart-swayosd
|
||||
hyprctl reload
|
||||
pkill -SIGUSR2 btop
|
||||
makoctl reload
|
||||
|
||||
# Change gnome, browser, vscode, cursor themes
|
||||
# Change gnome, browser, vscode themes
|
||||
omarchy-theme-set-terminal
|
||||
omarchy-theme-set-gnome
|
||||
omarchy-theme-set-eza
|
||||
omarchy-theme-set-browser
|
||||
omarchy-theme-set-vscode
|
||||
omarchy-theme-set-cursor
|
||||
omarchy-theme-set-obsidian
|
||||
|
||||
# Call hook on theme set
|
||||
omarchy-hook theme-set "$THEME_NAME"
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
CHROMIUM_THEME=~/.config/omarchy/current/theme/chromium.theme
|
||||
|
||||
if omarchy-cmd-present chromium || omarchy-cmd-present helium-browser || omarchy-cmd-present brave; then
|
||||
if omarchy-cmd-present chromium || omarchy-cmd-present brave; then
|
||||
if [[ -f $CHROMIUM_THEME ]]; then
|
||||
THEME_RGB_COLOR=$(<$CHROMIUM_THEME)
|
||||
THEME_HEX_COLOR=$(printf '#%02x%02x%02x' ${THEME_RGB_COLOR//,/ })
|
||||
THEME_HEX_COLOR=$(printf '#%02x%02x%02x' ${rgb//,/ })
|
||||
else
|
||||
# Use a default, neutral grey if theme doesn't have a color
|
||||
THEME_RGB_COLOR="28,32,39"
|
||||
@@ -15,17 +15,6 @@ if omarchy-cmd-present chromium || omarchy-cmd-present helium-browser || omarchy
|
||||
if omarchy-cmd-present chromium; then
|
||||
rm -f /etc/chromium/policies/managed/color.json
|
||||
chromium --no-startup-window --set-theme-color="$THEME_RGB_COLOR"
|
||||
|
||||
if [[ -f ~/.config/omarchy/current/theme/light.mode ]]; then
|
||||
chromium --no-startup-window --set-color-scheme="light"
|
||||
else
|
||||
chromium --no-startup-window --set-color-scheme="dark"
|
||||
fi
|
||||
fi
|
||||
|
||||
if omarchy-cmd-present helium-browser; then
|
||||
echo "{\"BrowserThemeColor\": \"$THEME_HEX_COLOR\"}" | tee "/etc/chromium/policies/managed/color.json" >/dev/null
|
||||
helium-browser --no-startup-window --refresh-platform-policy
|
||||
fi
|
||||
|
||||
if omarchy-cmd-present brave; then
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Call the VSCode theme setter with Cursor-specific parameters
|
||||
omarchy-theme-set-vscode cursor "$HOME/.config/Cursor/User/settings.json" "$HOME/.local/state/omarchy/toggles/skip-cursor-theme-changes" Cursor
|
||||
7
bin/omarchy-theme-set-eza
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ -f ~/.config/omarchy/current/theme/eza.yml ]; then
|
||||
ln -snf ~/.config/omarchy/current/theme/eza.yml ~/.config/eza/theme.yml
|
||||
else
|
||||
rm -f ~/.config/eza/theme.yml
|
||||
fi
|
||||
@@ -1,684 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy-theme-set-obsidian: Bootstrap and update Omarchy theme for Obsidian
|
||||
#
|
||||
# - Ensures registry at ~/.local/state/omarchy/obsidian-vaults
|
||||
# - Populates by extracting vault paths from ~/.config/obsidian/obsidian.json
|
||||
# - For each valid vault:
|
||||
# - Ensures .obsidian/themes/Omarchy/{manifest.json, theme.css}
|
||||
# - Updates theme.css (uses current theme’s obsidian.css if present; otherwise generates -- see below)
|
||||
|
||||
# Theme automagic generation logic:
|
||||
#
|
||||
# - Background/foreground: read from ~/.config/omarchy/current/theme/alacritty.toml [colors.primary]
|
||||
# (background/foreground). Fallbacks: bg=#1a1b26, fg=#a9b1d6. Compute bg brightness for light/dark handling.
|
||||
# - Palette extraction: collect colors from Alacritty (primary/normal/bright/dim/selection), Waybar (@define-color),
|
||||
# and Hyprland (col.*_border; rgba->hex). Normalize, dedupe, and count frequencies.
|
||||
# - Slot ordering: remove bg/fg, sort remaining colors by frequency, then fill 13 slots by cycling. Map slots to:
|
||||
# h1–h6, links, inline code, marks, interactive accent, blockquote border; muted/faint use border color.
|
||||
# - Code colors: code background = closest color to bg (Euclidean RGB); if none, make a subtle bg variant (+/− RGB).
|
||||
# code foreground = closest color to fg; fallback #e0e0e0.
|
||||
# - Border color: from btop.theme theme[div_line]; else blended mix biased toward bg (≈ (bg+fg)/3).
|
||||
# - Selection: from Alacritty [colors.selection] (background/text), honoring CellForeground/Background.
|
||||
# If missing, background = 75% bg + 25% fg; text chosen for contrast vs selection background.
|
||||
# - Fonts: monospace from Alacritty [font] or fontconfig monospace; UI font from fontconfig sans-serif.
|
||||
|
||||
VAULTS_FILE="$HOME/.local/state/omarchy/obsidian-vaults"
|
||||
CURRENT_THEME_DIR="$HOME/.config/omarchy/current/theme"
|
||||
|
||||
ensure_vaults_file() {
|
||||
mkdir -p "$(dirname "$VAULTS_FILE")"
|
||||
local tmpfile
|
||||
tmpfile="$(mktemp)"
|
||||
# Extract the Obsidian vault location from config file <base>/<vault>/.obsidian
|
||||
jq -r '.vaults | values[].path' ~/.config/obsidian/obsidian.json 2>/dev/null >>"$tmpfile"
|
||||
if [ -s "$tmpfile" ]; then
|
||||
sort -u "$tmpfile" >"$VAULTS_FILE"
|
||||
else
|
||||
: >"$VAULTS_FILE"
|
||||
fi
|
||||
rm "$tmpfile"
|
||||
}
|
||||
|
||||
# Ensure theme directory and minimal manifest exist in a vault
|
||||
ensure_theme_scaffold() {
|
||||
local vault_path="$1"
|
||||
local theme_dir="$vault_path/.obsidian/themes/Omarchy"
|
||||
mkdir -p "$theme_dir"
|
||||
if [ ! -f "$theme_dir/manifest.json" ]; then
|
||||
cat >"$theme_dir/manifest.json" <<'EOF'
|
||||
{
|
||||
"name": "Omarchy",
|
||||
"version": "1.0.0",
|
||||
"minAppVersion": "0.16.0",
|
||||
"description": "Automatically syncs with your current Omarchy system theme colors and fonts",
|
||||
"author": "Omarchy",
|
||||
"authorUrl": "https://omarchy.org"
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
[ -f "$theme_dir/theme.css" ] || : >"$theme_dir/theme.css"
|
||||
}
|
||||
|
||||
# Function to extract hex color from string
|
||||
extract_hex_color() {
|
||||
echo "$1" | grep -oE '#[0-9a-fA-F]{6}' | head -1
|
||||
}
|
||||
|
||||
# Function to convert RGB/RGBA to hex
|
||||
rgb_to_hex() {
|
||||
local rgb_string="$1"
|
||||
if [[ $rgb_string =~ rgba?\(([0-9]+),\s*([0-9]+),\s*([0-9]+) ]]; then
|
||||
printf "#%02x%02x%02x\n" "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Convert hex to RGB components
|
||||
hex_to_rgb() {
|
||||
local hex="${1#\#}"
|
||||
printf "%d %d %d\n" "0x${hex:0:2}" "0x${hex:2:2}" "0x${hex:4:2}"
|
||||
}
|
||||
|
||||
# Calculate perceived brightness (0-255)
|
||||
calculate_brightness() {
|
||||
local hex="$1"
|
||||
read -r r g b <<<"$(hex_to_rgb "$hex")"
|
||||
# Use perceived brightness formula
|
||||
echo $(((r * 299 + g * 587 + b * 114) / 1000))
|
||||
}
|
||||
|
||||
# Calculate approximate contrast ratio between two colors
|
||||
# Returns ratio scaled by 100 (e.g., 450 = 4.5:1 ratio)
|
||||
# (this is due to bash not supporting decimal math)
|
||||
calculate_contrast_ratio() {
|
||||
local hex1="$1" hex2="$2"
|
||||
local br1=$(calculate_brightness "$hex1") # 0-255 range
|
||||
local br2=$(calculate_brightness "$hex2") # 0-255 range
|
||||
|
||||
# Ensure br1 is the lighter color (higher brightness)
|
||||
if [ $br1 -lt $br2 ]; then
|
||||
local temp=$br1
|
||||
br1=$br2
|
||||
br2=$temp
|
||||
fi
|
||||
|
||||
# Approximate contrast ratio scaled by 100
|
||||
# Add offset to avoid division by zero and approximate WCAG +0.05 behavior
|
||||
echo $(((br1 + 13) * 100 / (br2 + 13)))
|
||||
}
|
||||
|
||||
# Check if two colors meet minimum contrast threshold
|
||||
# Usage: meets_contrast_threshold <ratio> <threshold>
|
||||
# Both ratio and threshold should be scaled by 100 (e.g., 300 = 3:1)
|
||||
meets_contrast_threshold() {
|
||||
local ratio="$1" # Ratio scaled by 100 (from calculate_contrast_ratio)
|
||||
local threshold="$2" # Threshold scaled by 100 (300=3:1, 450=4.5:1, 700=7:1)
|
||||
[ $ratio -ge $threshold ]
|
||||
}
|
||||
|
||||
# Calculate color distance (euclidean in RGB space)
|
||||
color_distance() {
|
||||
local hex1="$1"
|
||||
local hex2="$2"
|
||||
read -r r1 g1 b1 <<<"$(hex_to_rgb "$hex1")"
|
||||
read -r r2 g2 b2 <<<"$(hex_to_rgb "$hex2")"
|
||||
echo $(((r1 - r2) * (r1 - r2) + (g1 - g2) * (g1 - g2) + (b1 - b2) * (b1 - b2)))
|
||||
}
|
||||
|
||||
# Extract all colors with frequency count
|
||||
extract_all_colors_with_count() {
|
||||
local -A color_counts
|
||||
local color
|
||||
|
||||
# Extract from Alacritty config
|
||||
if [ -f "$CURRENT_THEME_DIR/alacritty.toml" ]; then
|
||||
# Primary colors
|
||||
while IFS= read -r color; do
|
||||
color=$(echo "$color" | tr '[:upper:]' '[:lower:]') # Lowercase for consistency
|
||||
[ -n "$color" ] && ((color_counts["$color"]++))
|
||||
done < <(grep -E "(background|foreground|cursor|text)" "$CURRENT_THEME_DIR/alacritty.toml" | sed "s/.*[\"']0x/#/;s/.*[\"']#/#/;s/[\"'].*//;s/.*#\([0-9a-fA-F]\{6\}\).*/\#\1/" | grep "^#")
|
||||
|
||||
# Normal colors
|
||||
while IFS= read -r color; do
|
||||
color=$(echo "$color" | tr '[:upper:]' '[:lower:]') # Lowercase for consistency
|
||||
[ -n "$color" ] && ((color_counts["$color"]++))
|
||||
done < <(grep -A 20 "\[colors.normal\]" "$CURRENT_THEME_DIR/alacritty.toml" | grep -E "(black|red|green|yellow|blue|magenta|cyan|white)" | sed "s/.*[\"']0x/#/;s/.*[\"']#/#/;s/[\"'].*//;s/.*#\([0-9a-fA-F]\{6\}\).*/\#\1/" | grep "^#")
|
||||
|
||||
# Bright colors
|
||||
while IFS= read -r color; do
|
||||
# Add # if missing
|
||||
[[ "$color" =~ ^[0-9a-fA-F]{6}$ ]] && color="#$color"
|
||||
color=$(echo "$color" | tr '[:upper:]' '[:lower:]') # Lowercase for consistency
|
||||
[[ "$color" =~ ^#[0-9a-f]{6}$ ]] && ((color_counts["$color"]++))
|
||||
done < <(grep -A 20 "\[colors.bright\]" "$CURRENT_THEME_DIR/alacritty.toml" | grep -E "(black|red|green|yellow|blue|magenta|cyan|white)" | sed "s/.*[\"']//;s/[\"'].*//")
|
||||
|
||||
# Dim colors if present
|
||||
while IFS= read -r color; do
|
||||
# Add # if missing
|
||||
[[ "$color" =~ ^[0-9a-fA-F]{6}$ ]] && color="#$color"
|
||||
color=$(echo "$color" | tr '[:upper:]' '[:lower:]') # Lowercase for consistency
|
||||
[[ "$color" =~ ^#[0-9a-f]{6}$ ]] && ((color_counts["$color"]++))
|
||||
done < <(grep -A 20 "\[colors.dim\]" "$CURRENT_THEME_DIR/alacritty.toml" 2>/dev/null | grep -E "(black|red|green|yellow|blue|magenta|cyan|white)" | sed "s/.*[\"']//;s/[\"'].*//")
|
||||
|
||||
# Selection colors
|
||||
while IFS= read -r color; do
|
||||
color=$(echo "$color" | tr '[:upper:]' '[:lower:]') # Lowercase for consistency
|
||||
[ -n "$color" ] && ((color_counts["$color"]++))
|
||||
done < <(grep -A 5 "\[colors.selection\]" "$CURRENT_THEME_DIR/alacritty.toml" 2>/dev/null | grep -E "(background|text)" | sed "s/.*[\"']0x/#/;s/.*[\"']#/#/;s/[\"'].*//;s/.*#\([0-9a-fA-F]\{6\}\).*/\#\1/" | grep "^#")
|
||||
fi
|
||||
|
||||
# Extract from Waybar CSS
|
||||
if [ -f "$CURRENT_THEME_DIR/waybar.css" ]; then
|
||||
while IFS= read -r color; do
|
||||
color=$(echo "$color" | tr '[:upper:]' '[:lower:]') # Lowercase for consistency
|
||||
[ -n "$color" ] && ((color_counts["$color"]++))
|
||||
done < <(grep -oE '@define-color [a-z_-]+ #[0-9a-fA-F]{6}' "$CURRENT_THEME_DIR/waybar.css" | grep -oE '#[0-9a-fA-F]{6}')
|
||||
fi
|
||||
|
||||
# Extract from Hyprland config
|
||||
if [ -f "$CURRENT_THEME_DIR/hyprland.conf" ]; then
|
||||
while IFS= read -r color; do
|
||||
if [[ $color == rgba* ]] || [[ $color == rgb* ]]; then
|
||||
color=$(rgb_to_hex "$color")
|
||||
fi
|
||||
color=$(echo "$color" | tr '[:upper:]' '[:lower:]') # Lowercase for consistency
|
||||
[ -n "$color" ] && ((color_counts["$color"]++))
|
||||
done < <(grep -E "col\.(active|inactive)_border" "$CURRENT_THEME_DIR/hyprland.conf" | grep -oE 'rgba?\([^)]+\)|#[0-9a-fA-F]{6,8}' | sed 's/ff$//')
|
||||
fi
|
||||
|
||||
# Output colors with their counts
|
||||
for color in "${!color_counts[@]}"; do
|
||||
echo "${color_counts[$color]} $color"
|
||||
done
|
||||
}
|
||||
|
||||
# Sort colors by frequency
|
||||
sort_colors_by_frequency() {
|
||||
# Input is already "count color" format
|
||||
sort -rn | cut -d' ' -f2
|
||||
}
|
||||
|
||||
# Fill color slots with cycling if needed
|
||||
fill_color_slots() {
|
||||
local -a colors=("$@")
|
||||
local -a slots
|
||||
local num_colors=${#colors[@]}
|
||||
|
||||
# Need 13 slots total (code colors are handled separately)
|
||||
local slots_needed=13
|
||||
|
||||
if [ $num_colors -eq 0 ]; then
|
||||
# No colors available, use defaults
|
||||
colors=("#3d3d3d" "#5d5d5d" "#7d7d7d" "#9d9d9d" "#bd93f9" "#50fa7b")
|
||||
num_colors=6
|
||||
fi
|
||||
|
||||
# Fill slots, cycling if necessary
|
||||
for ((i = 0; i < slots_needed; i++)); do
|
||||
slots[$i]="${colors[$((i % num_colors))]}"
|
||||
done
|
||||
|
||||
echo "${slots[@]}"
|
||||
}
|
||||
|
||||
# Main color extraction and theme generation
|
||||
extract_theme_data() {
|
||||
# Get primary colors from Alacritty
|
||||
local bg_color="#1a1b26"
|
||||
local fg_color="#a9b1d6"
|
||||
|
||||
if [ -f "$CURRENT_THEME_DIR/alacritty.toml" ]; then
|
||||
local extracted_bg=$(grep -A 5 "\[colors.primary\]" "$CURRENT_THEME_DIR/alacritty.toml" | grep "^background = " | sed "s/.*[\"']0x/#/;s/.*[\"']#/#/;s/[\"'].*//;s/.*#\([0-9a-fA-F]\{6\}\).*/\#\1/" | head -1 | tr '[:upper:]' '[:lower:]')
|
||||
local extracted_fg=$(grep -A 5 "\[colors.primary\]" "$CURRENT_THEME_DIR/alacritty.toml" | grep "^foreground = " | sed "s/.*[\"']0x/#/;s/.*[\"']#/#/;s/[\"'].*//;s/.*#\([0-9a-fA-F]\{6\}\).*/\#\1/" | head -1 | tr '[:upper:]' '[:lower:]')
|
||||
[ -n "$extracted_bg" ] && bg_color="$extracted_bg"
|
||||
[ -n "$extracted_fg" ] && fg_color="$extracted_fg"
|
||||
fi
|
||||
|
||||
# Determine if light or dark theme
|
||||
local bg_brightness=$(calculate_brightness "$bg_color")
|
||||
local is_light_theme=false
|
||||
[ $bg_brightness -gt 127 ] && is_light_theme=true
|
||||
|
||||
# Extract all colors with counts
|
||||
local color_data=$(extract_all_colors_with_count)
|
||||
|
||||
# Filter out background and foreground colors for the main array
|
||||
local filtered_data=$(echo "$color_data" | grep -v "$bg_color" | grep -v "$fg_color")
|
||||
|
||||
# Get all unique colors (including bg/fg) for distance calculations
|
||||
local -a all_unique_colors
|
||||
readarray -t all_unique_colors < <(echo "$color_data" | cut -d' ' -f2 | sort -u)
|
||||
|
||||
# Find the 3 closest colors to background for background variations
|
||||
local -a bg_distances
|
||||
for color in "${all_unique_colors[@]}"; do
|
||||
if [ "$color" != "$bg_color" ]; then
|
||||
distance=$(color_distance "$color" "$bg_color")
|
||||
bg_distances+=("$distance:$color")
|
||||
fi
|
||||
done
|
||||
|
||||
# All background variations use the same as primary background
|
||||
local bg_primary_alt="$bg_color"
|
||||
local bg_secondary="$bg_color"
|
||||
local bg_secondary_alt="$bg_color"
|
||||
|
||||
# Generate code background color that will contrast with foreground text
|
||||
read -r r g b <<<"$(hex_to_rgb "$bg_color")"
|
||||
if [ $bg_brightness -gt 127 ]; then
|
||||
r=$((r - 10))
|
||||
g=$((g - 10))
|
||||
b=$((b - 10))
|
||||
else
|
||||
r=$((r + 15))
|
||||
g=$((g + 15))
|
||||
b=$((b + 15))
|
||||
fi
|
||||
[ $r -lt 0 ] && r=0
|
||||
[ $r -gt 255 ] && r=255
|
||||
[ $g -lt 0 ] && g=0
|
||||
[ $g -gt 255 ] && g=255
|
||||
[ $b -lt 0 ] && b=0
|
||||
[ $b -gt 255 ] && b=255
|
||||
code_bg=$(printf "#%02x%02x%02x" "$r" "$g" "$b")
|
||||
|
||||
|
||||
# Find closest color to foreground for code block text
|
||||
local code_fg=""
|
||||
min_distance=999999999
|
||||
for color in "${all_unique_colors[@]}"; do
|
||||
if [ "$color" != "$fg_color" ]; then
|
||||
distance=$(color_distance "$color" "$fg_color")
|
||||
if [ $distance -lt $min_distance ]; then
|
||||
min_distance=$distance
|
||||
code_fg="$color"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
[ -z "$code_fg" ] && code_fg="#e0e0e0" # Fallback
|
||||
|
||||
# Extract text selection colors from Alacritty
|
||||
local selection_bg=""
|
||||
local selection_fg=""
|
||||
if [ -f "$CURRENT_THEME_DIR/alacritty.toml" ]; then
|
||||
selection_bg=$(grep -A 5 "\[colors.selection\]" "$CURRENT_THEME_DIR/alacritty.toml" | grep "^background = " | sed "s/.*[\"']0x/#/;s/.*[\"']#/#/;s/[\"'].*//;s/.*#\([0-9a-fA-F]\{6\}\).*/\#\1/" | head -1 | tr '[:upper:]' '[:lower:]')
|
||||
local selection_text=$(grep -A 5 "\[colors.selection\]" "$CURRENT_THEME_DIR/alacritty.toml" | grep "^text = " | sed "s/.*[\"']0x/#/;s/.*[\"']#/#/;s/[\"'].*//;s/.*#\([0-9a-fA-F]\{6\}\).*/\#\1/" | head -1 | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
# If text is set to CellForeground/CellBackground, use the appropriate color
|
||||
if [ -z "$selection_text" ] || [[ "$(grep -A 5 "\[colors.selection\]" "$CURRENT_THEME_DIR/alacritty.toml" | grep "^text = ")" == *"CellForeground"* ]]; then
|
||||
selection_fg="$fg_color"
|
||||
elif [[ "$(grep -A 5 "\[colors.selection\]" "$CURRENT_THEME_DIR/alacritty.toml" | grep "^text = ")" == *"CellBackground"* ]]; then
|
||||
selection_fg="$bg_color"
|
||||
else
|
||||
selection_fg="$selection_text"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Fallback if no selection colors found
|
||||
if [ -z "$selection_bg" ]; then
|
||||
read -r r1 g1 b1 <<<"$(hex_to_rgb "$bg_color")"
|
||||
read -r r2 g2 b2 <<<"$(hex_to_rgb "$fg_color")"
|
||||
local r=$(((r1 * 3 + r2) / 4)) # 75% background, 25% foreground
|
||||
local g=$(((g1 * 3 + g2) / 4))
|
||||
local b=$(((b1 * 3 + b2) / 4))
|
||||
selection_bg=$(printf "#%02x%02x%02x" "$r" "$g" "$b")
|
||||
fi
|
||||
|
||||
# Use contrasting color for selection text if not defined
|
||||
if [ -z "$selection_fg" ]; then
|
||||
# Calculate brightness of selection background
|
||||
local sel_brightness=$(calculate_brightness "$selection_bg")
|
||||
if [ $sel_brightness -gt 127 ]; then
|
||||
selection_fg="$bg_color" # Dark text on light selection
|
||||
else
|
||||
selection_fg="$fg_color" # Light text on dark selection
|
||||
fi
|
||||
fi
|
||||
|
||||
# Extract border color from btop theme
|
||||
local border_color=""
|
||||
if [ -f "$CURRENT_THEME_DIR/btop.theme" ]; then
|
||||
# Look for theme[div_line] in btop theme
|
||||
local btop_divline=$(grep 'theme\[div_line\]' "$CURRENT_THEME_DIR/btop.theme" | head -1)
|
||||
|
||||
if [ -n "$btop_divline" ]; then
|
||||
# Extract the color value after the = sign
|
||||
local extracted=$(echo "$btop_divline" | sed 's/.*=//' | xargs)
|
||||
|
||||
# Check if it's a hex color and lowercase it
|
||||
if [[ $extracted =~ ^#[0-9a-fA-F]{6}$ ]]; then
|
||||
border_color=$(echo "$extracted" | tr '[:upper:]' '[:lower:]')
|
||||
elif [[ $extracted =~ ^[0-9a-fA-F]{6}$ ]]; then
|
||||
# Add # if missing and lowercase
|
||||
border_color=$(echo "#$extracted" | tr '[:upper:]' '[:lower:]')
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Fallback if no border color found
|
||||
if [ -z "$border_color" ]; then
|
||||
# Use a color between bg and fg
|
||||
read -r r1 g1 b1 <<<"$(hex_to_rgb "$bg_color")"
|
||||
read -r r2 g2 b2 <<<"$(hex_to_rgb "$fg_color")"
|
||||
local r=$(((r1 + r2) / 3)) # Closer to background
|
||||
local g=$(((g1 + g2) / 3))
|
||||
local b=$(((b1 + b2) / 3))
|
||||
border_color=$(printf "#%02x%02x%02x" "$r" "$g" "$b")
|
||||
fi
|
||||
|
||||
# Set text colors for muted/faint based on contrast
|
||||
local text_muted_color="$border_color"
|
||||
local text_faint_color="$border_color"
|
||||
|
||||
# Validate border color contrast against background
|
||||
|
||||
# Represents a 3:1 WCAG contrast ratio
|
||||
local ideal_contrast_ratio=300
|
||||
|
||||
local border_contrast=$(calculate_contrast_ratio "$border_color" "$bg_color")
|
||||
if ! meets_contrast_threshold "$border_contrast" "$ideal_contrast_ratio"; then
|
||||
# Override text colors for readability, keep border color for visibility
|
||||
text_muted_color="$fg_color"
|
||||
text_faint_color="$fg_color"
|
||||
fi
|
||||
|
||||
# Get unique colors array (without bg/fg) sorted by frequency
|
||||
local -a unique_colors
|
||||
readarray -t unique_colors < <(echo "$filtered_data" | sort_colors_by_frequency)
|
||||
|
||||
# Fill the 13 color slots (code colors handled separately)
|
||||
local -a color_slots
|
||||
readarray -t color_slots < <(fill_color_slots "${unique_colors[@]}" | tr ' ' '\n')
|
||||
|
||||
# Extract fonts
|
||||
local monospace_font="CaskaydiaMono Nerd Font"
|
||||
local ui_font="Liberation Sans"
|
||||
|
||||
if [ -f "$CURRENT_THEME_DIR/alacritty.toml" ]; then
|
||||
local alacritty_font=$(grep -A 5 "\[font\]" "$CURRENT_THEME_DIR/alacritty.toml" | grep 'family = ' | head -1 | cut -d'"' -f2)
|
||||
[ -n "$alacritty_font" ] && monospace_font="$alacritty_font"
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.config/fontconfig/fonts.conf" ]; then
|
||||
local fontconfig_mono=$(xmlstarlet sel -t -v '//match[@target="pattern"][test/string="monospace"]/edit[@name="family"]/string' "$HOME/.config/fontconfig/fonts.conf" 2>/dev/null || true)
|
||||
[ -n "$fontconfig_mono" ] && monospace_font="$fontconfig_mono"
|
||||
|
||||
local fontconfig_sans=$(xmlstarlet sel -t -v '//match[@target="pattern"][test/string="sans-serif"]/edit[@name="family"]/string' "$HOME/.config/fontconfig/fonts.conf" 2>/dev/null || true)
|
||||
[ -n "$fontconfig_sans" ] && ui_font="$fontconfig_sans"
|
||||
fi
|
||||
|
||||
# Generate CSS with 14-slot system
|
||||
cat <<EOF
|
||||
/* Omarchy Theme for Obsidian */
|
||||
/* Generated on $(date) from theme: $(basename "$(readlink "$CURRENT_THEME_DIR" 2>/dev/null || echo "unknown")") */
|
||||
/* Colors sorted by frequency, backgrounds by distance */
|
||||
|
||||
.theme-dark, .theme-light {
|
||||
/* Core colors */
|
||||
--background-primary: $bg_color;
|
||||
--text-normal: $fg_color;
|
||||
|
||||
/* Background variations (always distance-based) */
|
||||
--background-primary-alt: $bg_primary_alt;
|
||||
--background-secondary: $bg_secondary;
|
||||
--background-secondary-alt: $bg_secondary_alt;
|
||||
|
||||
/* Code block colors (always distance-based) */
|
||||
--code-background: $code_bg;
|
||||
--code-foreground: $code_fg;
|
||||
|
||||
/* Border color from btop theme */
|
||||
--border-color: $border_color;
|
||||
|
||||
/* Selection colors from Alacritty */
|
||||
--text-selection: $selection_bg;
|
||||
--text-selection-fg: $selection_fg;
|
||||
|
||||
/* 13-slot color system for remaining elements */
|
||||
--text-title-h1: ${color_slots[0]};
|
||||
--text-title-h2: ${color_slots[1]};
|
||||
--text-title-h3: ${color_slots[2]};
|
||||
--text-title-h4: ${color_slots[3]};
|
||||
--text-title-h5: ${color_slots[4]};
|
||||
--text-title-h6: ${color_slots[4]}; /* Same as h5 */
|
||||
--text-link: ${color_slots[5]};
|
||||
--markup-code: ${color_slots[6]};
|
||||
--text-mark: ${color_slots[7]};
|
||||
--interactive-accent: ${color_slots[8]};
|
||||
--blockquote-border: ${color_slots[9]};
|
||||
--text-muted: $text_muted_color; /* Use text-specific color for muted text */
|
||||
--text-faint: $text_faint_color; /* Use text-specific color for faint text */
|
||||
|
||||
/* Additional mappings */
|
||||
--text-accent: var(--interactive-accent);
|
||||
--text-accent-hover: var(--interactive-accent);
|
||||
--text-error: var(--text-title-h1);
|
||||
--text-error-hover: var(--text-title-h1);
|
||||
--text-highlight-bg: $fg_color; /* Use text color as highlight background */
|
||||
--text-on-accent: $bg_color;
|
||||
|
||||
--interactive-normal: var(--code-background);
|
||||
--interactive-hover: var(--interactive-accent);
|
||||
--interactive-accent-hover: var(--interactive-accent);
|
||||
--interactive-success: var(--text-title-h2);
|
||||
|
||||
--scrollbar-bg: var(--background-primary);
|
||||
--scrollbar-thumb-bg: var(--code-background);
|
||||
--scrollbar-active-thumb-bg: var(--interactive-accent);
|
||||
|
||||
--background-modifier-border: var(--border-color);
|
||||
--background-modifier-form-field: var(--code-background);
|
||||
--background-modifier-form-field-highlighted: var(--code-background);
|
||||
--background-modifier-box-shadow: rgba(0, 0, 0, 0.3);
|
||||
--background-modifier-success: var(--interactive-success);
|
||||
--background-modifier-error: var(--text-error);
|
||||
--background-modifier-error-hover: var(--text-error);
|
||||
--background-modifier-cover: rgba(0, 0, 0, 0.8);
|
||||
|
||||
--link-color: var(--text-link);
|
||||
--link-color-hover: var(--text-link);
|
||||
--link-unresolved-color: var(--text-muted);
|
||||
--link-unresolved-opacity: 0.7;
|
||||
|
||||
--tag-color: var(--text-title-h3);
|
||||
--tag-background: var(--code-background);
|
||||
|
||||
--graph-line: var(--text-muted);
|
||||
--graph-node: var(--interactive-accent);
|
||||
--graph-node-unresolved: var(--text-muted);
|
||||
--graph-node-focused: var(--text-link);
|
||||
--graph-node-tag: var(--text-title-h3);
|
||||
--graph-node-attachment: var(--text-title-h2);
|
||||
|
||||
/* Fonts */
|
||||
--font-interface-theme: "$ui_font";
|
||||
--font-text-theme: "$ui_font";
|
||||
--font-monospace-theme: "$monospace_font";
|
||||
}
|
||||
|
||||
/* Headers */
|
||||
.cm-header-1, .markdown-rendered h1 { color: var(--text-title-h1); }
|
||||
.cm-header-2, .markdown-rendered h2 { color: var(--text-title-h2); }
|
||||
.cm-header-3, .markdown-rendered h3 { color: var(--text-title-h3); }
|
||||
.cm-header-4, .markdown-rendered h4 { color: var(--text-title-h4); }
|
||||
.cm-header-5, .markdown-rendered h5 { color: var(--text-title-h5); }
|
||||
.cm-header-6, .markdown-rendered h6 { color: var(--text-title-h6); }
|
||||
|
||||
/* Code blocks */
|
||||
.markdown-rendered code {
|
||||
font-family: var(--font-monospace-theme);
|
||||
background-color: var(--code-background);
|
||||
color: var(--markup-code);
|
||||
padding: 2px 4px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.markdown-rendered pre {
|
||||
background-color: var(--code-background);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.markdown-rendered pre code {
|
||||
background-color: transparent;
|
||||
color: var(--code-foreground);
|
||||
}
|
||||
|
||||
/* Syntax highlighting */
|
||||
.cm-s-obsidian span.cm-keyword { color: var(--text-title-h1); }
|
||||
.cm-s-obsidian span.cm-string { color: var(--text-title-h2); }
|
||||
.cm-s-obsidian span.cm-number { color: var(--text-title-h3); }
|
||||
.cm-s-obsidian span.cm-comment { color: var(--text-muted); }
|
||||
.cm-s-obsidian span.cm-operator { color: var(--text-link); }
|
||||
.cm-s-obsidian span.cm-variable { color: var(--text-normal); }
|
||||
.cm-s-obsidian span.cm-def { color: var(--text-link); }
|
||||
|
||||
/* Highlighted text */
|
||||
.markdown-rendered mark,
|
||||
.cm-s-obsidian span.cm-highlight,
|
||||
mark {
|
||||
background-color: var(--text-highlight-bg) !important;
|
||||
color: var(--code-background) !important;
|
||||
}
|
||||
|
||||
/* Links */
|
||||
.markdown-rendered a {
|
||||
color: var(--text-link);
|
||||
}
|
||||
|
||||
/* Blockquotes */
|
||||
.markdown-rendered blockquote {
|
||||
border-left: 4px solid var(--blockquote-border);
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
/* Status bar */
|
||||
.status-bar {
|
||||
background-color: var(--code-background);
|
||||
border-top: 1px solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
/* Active file */
|
||||
.workspace-leaf.mod-active .workspace-leaf-header-title {
|
||||
color: var(--interactive-accent);
|
||||
}
|
||||
|
||||
.nav-file-title.is-active {
|
||||
background-color: var(--code-background);
|
||||
color: var(--interactive-accent);
|
||||
}
|
||||
|
||||
/* Text selection */
|
||||
::selection {
|
||||
background-color: var(--text-selection);
|
||||
color: var(--text-selection-fg);
|
||||
}
|
||||
|
||||
/* Search results */
|
||||
.search-result-file-title {
|
||||
color: var(--interactive-accent);
|
||||
}
|
||||
|
||||
.search-result-file-match {
|
||||
background-color: var(--code-background);
|
||||
color: var(--text-normal);
|
||||
border-left: 3px solid var(--interactive-accent);
|
||||
}
|
||||
|
||||
.search-result-file-matched-text {
|
||||
color: var(--code-background);
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
.markdown-rendered table {
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
.markdown-rendered th {
|
||||
background-color: var(--code-background);
|
||||
color: var(--text-accent);
|
||||
}
|
||||
|
||||
.markdown-rendered td {
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
/* Callouts */
|
||||
.callout {
|
||||
border-left: 4px solid var(--interactive-accent);
|
||||
background-color: var(--code-background);
|
||||
}
|
||||
.callout * {
|
||||
color: var(--text-normal);
|
||||
}
|
||||
|
||||
/* Modal dialogs */
|
||||
.modal {
|
||||
background-color: var(--background-primary);
|
||||
border: 2px solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
/* Settings */
|
||||
.vertical-tab-header-group-title {
|
||||
color: var(--interactive-accent);
|
||||
}
|
||||
|
||||
.vertical-tab-nav-item.is-active {
|
||||
background-color: var(--code-background);
|
||||
color: var(--interactive-accent);
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# Option handling
|
||||
if [ "${1:-}" = "--reset" ]; then
|
||||
echo "♻️ Resetting Omarchy themes and registry..."
|
||||
if [ -f "$VAULTS_FILE" ] && [ -s "$VAULTS_FILE" ]; then
|
||||
while IFS= read -r vault_path || [ -n "$vault_path" ]; do
|
||||
case "$vault_path" in ""|\#*) continue ;; esac
|
||||
vault_path="${vault_path%/}"
|
||||
vault_name=$(basename "$vault_path")
|
||||
theme_dir="$vault_path/.obsidian/themes/Omarchy"
|
||||
if [ -d "$theme_dir" ]; then
|
||||
rm -rf "$theme_dir"
|
||||
echo " ✅ $vault_name (theme removed)"
|
||||
else
|
||||
echo " ℹ️ $vault_name (no theme present)"
|
||||
fi
|
||||
done <"$VAULTS_FILE"
|
||||
fi
|
||||
rm -f "$VAULTS_FILE"
|
||||
echo "✅ Registry removed"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Main update logic
|
||||
echo "🔄 Updating Obsidian vaults..."
|
||||
|
||||
# Step 1: ensure registry exists (bootstrap if needed)
|
||||
ensure_vaults_file
|
||||
|
||||
while IFS= read -r vault_path || [ -n "$vault_path" ]; do
|
||||
case "$vault_path" in "" | \#*) continue ;; esac
|
||||
vault_path="${vault_path%/}"
|
||||
vault_name=$(basename "$vault_path")
|
||||
|
||||
# Step 2: verify path exists; log/skip gracefully if invalid
|
||||
if [ ! -d "$vault_path" ] || [ ! -d "$vault_path/.obsidian" ]; then
|
||||
echo " ❌ $vault_name (invalid entry: missing directory or .obsidian)"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Ensure theme files exist for this vault
|
||||
ensure_theme_scaffold "$vault_path"
|
||||
THEME_DIR="$vault_path/.obsidian/themes/Omarchy"
|
||||
|
||||
# Step 3: update theme.css
|
||||
if [ -f "$CURRENT_THEME_DIR/obsidian.css" ]; then
|
||||
cp "$CURRENT_THEME_DIR/obsidian.css" "$THEME_DIR/theme.css"
|
||||
echo " ✅ $vault_name (custom theme)"
|
||||
else
|
||||
extract_theme_data >"$THEME_DIR/theme.css"
|
||||
echo " ✅ $vault_name (generated theme)"
|
||||
fi
|
||||
done <"$VAULTS_FILE"
|
||||
@@ -1,8 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ -f ~/.config/alacritty/alacritty.toml ]]; then
|
||||
touch ~/.config/alacritty/alacritty.toml
|
||||
fi
|
||||
|
||||
killall -SIGUSR1 kitty
|
||||
killall -SIGUSR2 ghostty
|
||||
case "$TERMINAL" in
|
||||
"alacritty") touch ~/.config/alacritty/alacritty.toml ;;
|
||||
"kitty") killall -SIGUSR1 kitty ;;
|
||||
"ghostty") killall -SIGUSR2 ghostty ;;
|
||||
esac
|
||||
|
||||
@@ -3,45 +3,44 @@
|
||||
# Note: We cannot use `jq` to update settings.json because it’s JSONC (allows comments),
|
||||
# which jq doesn’t support.
|
||||
|
||||
# Parameters: EDITOR_CMD SETTINGS_PATH SKIP_FLAG EDITOR_NAME
|
||||
EDITOR_CMD="${1:-code}"
|
||||
SETTINGS_PATH="${2:-$HOME/.config/Code/User/settings.json}"
|
||||
SKIP_FLAG="${3:-$HOME/.local/state/omarchy/toggles/skip-vscode-theme-changes}"
|
||||
EDITOR_NAME="${4:-VS Code}"
|
||||
|
||||
VS_CODE_THEME="$HOME/.config/omarchy/current/theme/vscode.json"
|
||||
VS_CODE_SETTINGS="$HOME/.config/Code/User/settings.json"
|
||||
VS_CODE_SKIP_FLAG="$HOME/.local/state/omarchy/toggles/skip-vscode-theme-changes"
|
||||
|
||||
if omarchy-cmd-present "$EDITOR_CMD" && [[ ! -f "$SKIP_FLAG" ]]; then
|
||||
if omarchy-cmd-present code && [[ ! -f "$VS_CODE_SKIP_FLAG" ]]; then
|
||||
if [[ -f "$VS_CODE_THEME" ]]; then
|
||||
theme_name=$(jq -r '.name' "$VS_CODE_THEME")
|
||||
extension=$(jq -r '.extension' "$VS_CODE_THEME")
|
||||
|
||||
# Install $EDITOR_NAME theme extension
|
||||
if [[ -n "$extension" ]] && ! "$EDITOR_CMD" --list-extensions | grep -Fxq "$extension"; then
|
||||
"$EDITOR_CMD" --install-extension "$extension" >/dev/null
|
||||
# Install VS Code theme extension
|
||||
if [[ -n "$extension" ]] && ! code --list-extensions | grep -Fxq "$extension"; then
|
||||
notify-send " Installing VS Code theme for $theme_name"
|
||||
code --install-extension "$extension" >/dev/null
|
||||
fi
|
||||
|
||||
# Create config file if there isn't already one
|
||||
mkdir -p "$(dirname "$SETTINGS_PATH")"
|
||||
if [[ ! -f "$SETTINGS_PATH" ]]; then
|
||||
printf '{\n}\n' >"$SETTINGS_PATH"
|
||||
mkdir -p "$(dirname "$VS_CODE_SETTINGS")"
|
||||
if [[ ! -f "$VS_CODE_SETTINGS" ]]; then
|
||||
printf '{\n}\n' > "$VS_CODE_SETTINGS"
|
||||
fi
|
||||
|
||||
# Create a `workbench.colorTheme` entry in settings.
|
||||
if ! grep -q '"workbench.colorTheme"' "$SETTINGS_PATH"; then
|
||||
# Create a `workbench.colorTheme` entry in settings.
|
||||
if ! grep -q '"workbench.colorTheme"' "$VS_CODE_SETTINGS"; then
|
||||
# Insert `"workbench.colorTheme": "",` immediately after the first `{`
|
||||
# Use sed's first-match range (0,/{/) to only replace the first `{`
|
||||
sed -i --follow-symlinks -E '0,/\{/{s/\{/{\ "workbench.colorTheme": "",/}' "$SETTINGS_PATH"
|
||||
sed -i --follow-symlinks -E '0,/\{/{s/\{/{\
|
||||
"workbench.colorTheme": "",/}' "$VS_CODE_SETTINGS"
|
||||
fi
|
||||
|
||||
# Update theme
|
||||
sed -i --follow-symlinks -E \
|
||||
"s/(\"workbench.colorTheme\"[[:space:]]*:[[:space:]]*\")[^\"]*(\")/\1$theme_name\2/" \
|
||||
"$SETTINGS_PATH"
|
||||
"$VS_CODE_SETTINGS"
|
||||
else
|
||||
# Remove theme from settings.json when the theme doesn't have $EDITOR_NAME support
|
||||
if [[ -f "$SETTINGS_PATH" ]]; then
|
||||
sed -i --follow-symlinks -E 's/\"workbench\.colorTheme\"[[:space:]]*:[^,}]*,?//' "$SETTINGS_PATH"
|
||||
# Remove theme from settings.json when the theme doesn't have vscode support
|
||||
if [[ -f "$VS_CODE_SETTINGS" ]]; then
|
||||
sed -i --follow-symlinks -E '/"workbench\.colorTheme"[[:space:]]*:[^,}]*,?/d' "$VS_CODE_SETTINGS"
|
||||
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
for dir in ~/.config/omarchy/themes/*/; do
|
||||
if [[ -d $dir ]] && [[ ! -L "${dir%/}" ]] && [[ -d "$dir/.git" ]]; then
|
||||
echo "Updating: $(basename "$dir")"
|
||||
git -C "$dir" pull
|
||||
fi
|
||||
[ -d "$dir" ] && [ ! -L "${dir%/}" ] && echo "Updating: $(basename "$dir")" && git -C "$dir" pull
|
||||
done
|
||||
|
||||
@@ -4,6 +4,6 @@ if pgrep -x hypridle >/dev/null; then
|
||||
pkill -x hypridle
|
||||
notify-send "Stop locking computer when idle"
|
||||
else
|
||||
uwsm-app -- hypridle >/dev/null 2>&1 &
|
||||
uwsm app -- hypridle >/dev/null 2>&1 &
|
||||
notify-send "Now locking computer when idle"
|
||||
fi
|
||||
|
||||
@@ -6,7 +6,7 @@ OFF_TEMP=6000
|
||||
|
||||
# Ensure hyprsunset is running
|
||||
if ! pgrep -x hyprsunset; then
|
||||
setsid uwsm-app -- hyprsunset &
|
||||
setsid uwsm app -- hyprsunset &
|
||||
sleep 1 # Give it time to register
|
||||
fi
|
||||
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
if pgrep -x waybar >/dev/null; then
|
||||
pkill -x waybar
|
||||
else
|
||||
uwsm-app -- waybar >/dev/null 2>&1 &
|
||||
uwsm app -- waybar >/dev/null 2>&1 &
|
||||
fi
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
timezone=$(timedatectl list-timezones | gum filter --height 20 --header "Set timezone") || exit 1
|
||||
sudo timedatectl set-timezone "$timezone"
|
||||
echo "Timezone is now set to $timezone"
|
||||
omarchy-restart-waybar
|
||||
@@ -2,9 +2,6 @@
|
||||
|
||||
set -e
|
||||
|
||||
trap 'echo ""; echo -e "\033[0;31mSomething went wrong during the update!\n\nPlease review the output above carefully, correct the error, and retry the update.\n\nIf you need assistance, get help from the community at https://omarchy.org/discord\033[0m"' ERR
|
||||
|
||||
omarchy-update-confirm
|
||||
omarchy-snapshot create || [ $? -eq 127 ]
|
||||
omarchy-update-git
|
||||
omarchy-update-perform
|
||||
|
||||
@@ -2,4 +2,3 @@
|
||||
|
||||
# Ensure Waybar icon offering the available update is removed
|
||||
pkill -RTMIN+7 waybar
|
||||
exit 0
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
set -e
|
||||
|
||||
if (($# == 0)); then
|
||||
echo "Usage: omarchy-update-branch [master|dev]"
|
||||
echo "Usage: omarchy-verion-branch-set [master|dev]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
gum style --border normal --border-foreground 6 --padding "1 2" \
|
||||
"Ready to update Omarchy?" \
|
||||
"" \
|
||||
"• You cannot stop the update once you start!" \
|
||||
"• Make sure you're connected to power or have a full battery"
|
||||
|
||||
if ! gum confirm "Continue with update?"; then
|
||||
echo "Update cancelled"
|
||||
exit 0
|
||||
fi
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
echo -e "\e[32mUpdate Firmware\e[0m"
|
||||
|
||||
if omarchy-cmd-missing fwupdmgr; then
|
||||
omarchy-pkg-add fwupd
|
||||
fi
|
||||
|
||||
fwupdmgr refresh
|
||||
sudo fwupdmgr update
|
||||
@@ -1,7 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
echo -e "\e[32mUpdate Omarchy\e[0m"
|
||||
|
||||
git -C $OMARCHY_PATH pull --autostash
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Ensure we have the omarchy-keyring and it's populated
|
||||
if omarchy-pkg-missing omarchy-keyring || ! sudo pacman-key --list-keys 40DFB630FF42BCFFB047046CF0134EE680CAC571 &>/dev/null; then
|
||||
sudo pacman-key --recv-keys 40DFB630FF42BCFFB047046CF0134EE680CAC571 --keyserver keys.openpgp.org
|
||||
sudo pacman-key --lsign-key 40DFB630FF42BCFFB047046CF0134EE680CAC571
|
||||
|
||||
sudo pacman -Sy
|
||||
omarchy-pkg-add omarchy-keyring
|
||||
|
||||
sudo pacman-key --list-keys 40DFB630FF42BCFFB047046CF0134EE680CAC571
|
||||
fi
|
||||
@@ -2,10 +2,7 @@
|
||||
|
||||
set -e
|
||||
|
||||
omarchy-update-time
|
||||
omarchy-update-keyring
|
||||
omarchy-update-available-reset
|
||||
omarchy-update-system-pkgs
|
||||
omarchy-migrate
|
||||
omarchy-hook post-update
|
||||
omarchy-update-restart
|
||||
|
||||
@@ -5,6 +5,9 @@ if [ "$(uname -r | sed 's/-arch/\.arch/')" != "$(pacman -Q linux | awk '{print $
|
||||
|
||||
elif [ -f "$HOME/.local/state/omarchy/reboot-required" ]; then
|
||||
gum confirm "Updates require reboot. Ready?" && omarchy-state clear re*-required && sudo reboot now
|
||||
|
||||
elif [ -f "$HOME/.local/state/omarchy/relaunch-required" ]; then
|
||||
gum confirm "Updates require Hyprland relaunch. Ready?" && omarchy-state clear re*-required && uwsm stop
|
||||
fi
|
||||
|
||||
for file in "$HOME"/.local/state/omarchy/restart-*-required; do
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Used in package emergencies if a bad package has been pushed and we can't revoke.
|
||||
# Requires manually installing the good package using sudo pacman -U <url>
|
||||
ignored_packages=$(omarchy-pkg-ignored)
|
||||
@@ -23,7 +21,7 @@ if pacman -Qem >/dev/null; then
|
||||
fi
|
||||
fi
|
||||
|
||||
orphans=$(pacman -Qtdq || true)
|
||||
orphans=$(pacman -Qtdq)
|
||||
if [[ -n $orphans ]]; then
|
||||
echo -e "\e[32m\nRemove orphan system packages\e[0m"
|
||||
for pkg in $orphans; do
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "Updating time..."
|
||||
sudo systemctl restart systemd-timesyncd
|
||||
@@ -30,7 +30,7 @@ else
|
||||
fi
|
||||
|
||||
if [[ ${#APP_NAMES[@]} -eq 0 ]]; then
|
||||
echo "You must select at least one web app to remove."
|
||||
echo "You must provide web app names."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,445 +0,0 @@
|
||||
#!/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" -lt "$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
|
||||
|
||||
omarchy-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 "$OMARCHY_PATH/applications/icons/windows.png" ]; then
|
||||
cp "$OMARCHY_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 -- omarchy-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 -le $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" -lt 1 ] || [ "$SELECTED_CORES" -gt "$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 -lt 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 -le $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: omarchy-windows
|
||||
environment:
|
||||
VERSION: "11"
|
||||
RAM_SIZE: "$SELECTED_RAM"
|
||||
CPU_CORES: "$SELECTED_CORES"
|
||||
DISK_SIZE: "$SELECTED_DISK"
|
||||
USERNAME: "$USERNAME"
|
||||
PASSWORD: "$PASSWORD"
|
||||
devices:
|
||||
- /dev/kvm
|
||||
- /dev/net/tun
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
ports:
|
||||
- 8006:8006
|
||||
- 3389:3389/tcp
|
||||
- 3389:3389/udp
|
||||
volumes:
|
||||
- $HOME/.windows:/storage
|
||||
- $HOME/Windows:/shared
|
||||
restart: always
|
||||
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: omarchy-windows-vm stop"
|
||||
echo "To change resources: ~/.config/windows/docker-compose.yml"
|
||||
echo ""
|
||||
}
|
||||
|
||||
remove_windows() {
|
||||
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: omarchy-windows-vm install"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if container is already running
|
||||
CONTAINER_STATUS=$(docker inspect --format='{{.State.Status}}' omarchy-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: omarchy-windows-vm status"
|
||||
echo " View logs: docker logs omarchy-windows"
|
||||
notify-send -u critical "Windows VM" "Failed to start Windows VM"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Wait for RDP to be ready
|
||||
echo "Waiting for Windows VM to be ready..."
|
||||
WAIT_COUNT=0
|
||||
while ! nc -z 127.0.0.1 3389 2>/dev/null; do
|
||||
sleep 2
|
||||
WAIT_COUNT=$((WAIT_COUNT + 1))
|
||||
if [ $WAIT_COUNT -gt 60 ]; then # 2 minutes timeout
|
||||
echo "❌ Timeout waiting for RDP!"
|
||||
echo " The VM might still be installing Windows."
|
||||
echo " Check progress at: http://127.0.0.1:8006"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Give it a moment more to fully initialize
|
||||
sleep 5
|
||||
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"
|
||||
|
||||
# Build the connection info
|
||||
if [ "$KEEP_ALIVE" = true ]; then
|
||||
LIFECYCLE="VM will keep running after RDP closes
|
||||
To stop: omarchy-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 '.[0].scale')
|
||||
SCALE_PERCENT=$(echo "$HYPR_SCALE" | awk '{print int($1 * 100)}')
|
||||
|
||||
RDP_SCALE=""
|
||||
if [ "$SCALE_PERCENT" -ge 170 ]; then
|
||||
RDP_SCALE="/scale:180"
|
||||
elif [ "$SCALE_PERCENT" -ge 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 /cert:ignore /title:"Windows VM - Omarchy" /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: omarchy-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: omarchy-windows-vm install"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CONTAINER_STATUS=$(docker inspect --format='{{.State.Status}}' omarchy-windows 2>/dev/null)
|
||||
|
||||
if [ -z "$CONTAINER_STATUS" ]; then
|
||||
echo "Windows VM container not found."
|
||||
echo "To start: omarchy-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: omarchy-windows-vm launch" \
|
||||
"To stop: omarchy-windows-vm stop"
|
||||
else
|
||||
echo "Windows VM is stopped (status: $CONTAINER_STATUS)"
|
||||
echo "To start: omarchy-windows-vm launch"
|
||||
fi
|
||||
}
|
||||
|
||||
show_usage() {
|
||||
echo "Usage: omarchy-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 " omarchy-windows-vm install # Set up Windows VM for first time"
|
||||
echo " omarchy-windows-vm launch # Connect to VM (auto-stop on exit)"
|
||||
echo " omarchy-windows-vm launch -k # Connect to VM (keep running)"
|
||||
echo " omarchy-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
|
||||
25
boot.sh
@@ -3,15 +3,15 @@
|
||||
# Set install mode to online since boot.sh is used for curl installations
|
||||
export OMARCHY_ONLINE_INSTALL=true
|
||||
|
||||
ansi_art=' ▄▄▄
|
||||
▄█████▄ ▄███████████▄ ▄███████ ▄███████ ▄███████ ▄█ █▄ ▄█ █▄
|
||||
ansi_art=' ▄▄▄
|
||||
▄█████▄ ▄███████████▄ ▄███████ ▄███████ ▄███████ ▄█ █▄ ▄█ █▄
|
||||
███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███
|
||||
███ ███ ███ ███ ███ ███ ███ ███ ███ ███ █▀ ███ ███ ███ ███
|
||||
███ ███ ███ ███ ███ ▄███▄▄▄███ ▄███▄▄▄██▀ ███ ▄███▄▄▄███▄ ███▄▄▄███
|
||||
███ ███ ███ ███ ███ ▀███▀▀▀███ ▀███▀▀▀▀ ███ ▀▀███▀▀▀███ ▀▀▀▀▀▀███
|
||||
███ ███ ███ ███ ███ ███ ███ ██████████ ███ █▄ ███ ███ ▄██ ███
|
||||
███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███
|
||||
▀█████▀ ▀█ ███ █▀ ███ █▀ ███ ███ ███████▀ ███ █▀ ▀█████▀
|
||||
▀█████▀ ▀█ ███ █▀ ███ █▀ ███ ███ ███████▀ ███ █▀ ▀█████▀
|
||||
███ █▀ '
|
||||
|
||||
clear
|
||||
@@ -19,4 +19,21 @@ echo -e "\n$ansi_art\n"
|
||||
|
||||
sudo pacman -Syu --noconfirm --needed git
|
||||
|
||||
# FIXME: Update behavior or remove
|
||||
# Use custom repo if specified, otherwise default to basecamp/omarchy
|
||||
OMARCHY_REPO="${OMARCHY_REPO:-basecamp/omarchy}"
|
||||
|
||||
echo -e "\nCloning Omarchy from: https://github.com/${OMARCHY_REPO}.git"
|
||||
rm -rf ~/.local/share/omarchy/
|
||||
git clone "https://github.com/${OMARCHY_REPO}.git" ~/.local/share/omarchy >/dev/null
|
||||
|
||||
# Use custom branch if instructed, otherwise default to master
|
||||
OMARCHY_REF="${OMARCHY_REF:-master}"
|
||||
if [[ $OMARCHY_REF != "master" ]]; then
|
||||
echo -e "\e[32mUsing branch: $OMARCHY_REF\e[0m"
|
||||
cd ~/.local/share/omarchy
|
||||
git fetch origin "${OMARCHY_REF}" && git checkout "${OMARCHY_REF}"
|
||||
cd -
|
||||
fi
|
||||
|
||||
echo -e "\nInstallation starting..."
|
||||
source ~/.local/share/omarchy/install.sh
|
||||
|
||||
@@ -16,6 +16,5 @@ decorations = "None"
|
||||
|
||||
[keyboard]
|
||||
bindings = [
|
||||
{ key = "Insert", mods = "Shift", action = "Paste" },
|
||||
{ key = "Insert", mods = "Control", action = "Copy" }
|
||||
{ key = "F11", action = "ToggleFullscreen" }
|
||||
]
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
--ozone-platform=wayland
|
||||
--ozone-platform-hint=wayland
|
||||
--enable-features=TouchpadOverscrollHistoryNavigation
|
||||
# Chromium crash workaround for Wayland color management on Hyprland - see https://github.com/hyprwm/Hyprland/issues/11957
|
||||
--disable-features=WaylandWpColorManagerV1
|
||||
|
||||
@@ -22,7 +22,7 @@ presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:defaul
|
||||
|
||||
#* 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
|
||||
vim_keys = False
|
||||
|
||||
#* Rounded corners on boxes, is ignored if TTY mode is ON.
|
||||
rounded_corners = True
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
--ozone-platform=wayland
|
||||
--ozone-platform-hint=wayland
|
||||
--enable-features=TouchpadOverscrollHistoryNavigation
|
||||
--load-extension=/usr/share/omarchy/default/chromium/extensions/copy-url
|
||||
# Chromium crash workaround for Wayland color management on Hyprland - see https://github.com/hyprwm/Hyprland/issues/11957
|
||||
--disable-features=WaylandWpColorManagerV1
|
||||
--load-extension=~/.local/share/omarchy/default/chromium/extensions/copy-url
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
async = false
|
||||
@@ -1,3 +0,0 @@
|
||||
show_actions = false
|
||||
only_search_title = true
|
||||
history = false
|
||||