Compare commits

..
32 Commits
Author SHA1 Message Date
AquaMorph 897746b703 feat(orcaslicer): share profile directory 2026-10-18 10:36:24 -04:00
AquaMorph b94863cef8 feat(packages): install OrcaSlicer 2026-10-18 10:20:52 -04:00
AquaMorph 87312f9099 docs(readme): clarify setup instructions 2026-10-17 21:47:02 -04:00
AquaMorph aacee17255 feat(homebrew): install steam 2026-10-17 21:43:31 -04:00
AquaMorph e71962c89f feat(macos): configure system preferences 2026-10-17 21:19:38 -04:00
AquaMorph bbc7509810 feat(homebrew): install logitech options 2026-10-17 20:40:08 -04:00
AquaMorph a601ceb4de feat(brew): include nextcloud sync client 2026-10-15 21:36:28 -04:00
AquaMorph 6ec72b77c7 feat(chezmoi): configure encrypted ssh secrets 2026-10-15 20:39:17 -04:00
AquaMorph 50dcca10c9 feat(git): configure lfs filters 2026-10-15 18:58:53 -04:00
AquaMorph b942953365 fix(autorause): focus windows without intentional delay 2026-10-14 07:19:27 -04:00
AquaMorph 38fb8d8448 feat(macos): configure hover window focus 2026-10-14 07:16:15 -04:00
AquaMorph 05da23ca10 feat(keyboard): configure model m macos keybindings 2026-10-13 21:20:41 -04:00
AquaMorph 67c81eea85 feat(shell): improve history and path handling 2026-10-11 14:55:29 -04:00
AquaMorph ed99088c87 fix(updater): continue after individual failures 2026-10-11 14:53:41 -04:00
AquaMorph 891ba27000 feat(dotfiles): document macos setup and secure secrets 2026-10-11 12:55:19 -04:00
AquaMorph 8d80823b37 feat(chezmoi): ignore linux configuration on macos 2026-10-11 12:44:24 -04:00
AquaMorph 021dcf7010 chore(zsh): use configured model for commit agent 2026-10-11 12:31:28 -04:00
AquaMorph 8fb6eb5f82 fix(zsh): correct commit command argument order 2026-10-11 12:28:53 -04:00
AquaMorph 585818041a fix(models): use stable luna model 2026-10-11 12:26:44 -04:00
AquaMorph 525f55487f feat(zsh): support cross-platform shell setup 2026-10-11 12:24:19 -04:00
AquaMorph f47e69f438 fix(quickshell): detect wayland when session type is unset 2026-09-27 16:08:50 -04:00
AquaMorph cbbcf06c30 fix(quickshell): detect wayland display sessions 2026-09-27 13:33:22 -04:00
AquaMorph 5c13c8c3e7 feat(quickshell): support x11 bar sessions 2026-09-27 09:33:47 -04:00
AquaMorph 3f6473ce17 feat(quickshell): manage bar with systemd 2026-09-25 17:46:39 -04:00
AquaMorph 04cf13ae99 refactor(quickshell): split bar components 2026-09-25 17:41:59 -04:00
AquaMorph 4fdb6d90d8 refactor(quickshell): use event-driven hardware updates 2026-09-25 17:36:46 -04:00
AquaMorph 73f74fe05f refactor(quickshell): centralize bar theme values 2026-09-25 17:30:44 -04:00
AquaMorph 1a9d6a6a78 feat(quickshell): toggle clock seconds display 2026-09-25 17:23:53 -04:00
AquaMorph c31b2486e3 feat(quickshell): show detailed status popups 2026-09-25 17:20:08 -04:00
AquaMorph 56581c54a7 refactor(quickshell): centralize hardware status polling 2026-09-25 14:04:14 -04:00
AquaMorph 67764b4618 feat(quickshell): show microphone status separately 2026-09-25 13:53:13 -04:00
AquaMorph c3778e57ad feat(wayland): migrate bar to quickshell 2026-09-25 13:42:12 -04:00
43 changed files with 3152 additions and 53 deletions
+91 -2
View File
@@ -1,10 +1,99 @@
# Dotfiles # Dotfiles
A collection of config files and scripts for Fedora GNU/Linux. A collection of config files and scripts for Fedora GNU/Linux and macOS.
## Installation ## Linux installation
```bash ```bash
chezmoi init --apply git@github.com:AquaMorph/dotfiles.git chezmoi init --apply git@github.com:AquaMorph/dotfiles.git
``` ```
## macOS installation
1. Install the Xcode Command Line Tools with `xcode-select --install`, then
install [Homebrew](https://brew.sh/) and follow its `brew shellenv`
instructions.
2. Download the dotfiles without applying them, then install dependencies:
```bash
brew install chezmoi
chezmoi init git@github.com:AquaMorph/dotfiles.git
brew bundle --file="$(chezmoi source-path ~/.brewfile)"
```
3. Restore your password store to `~/.password-store` and import its GPG private
key from a secure backup before applying the dotfiles:
```bash
gpg --import /path/to/private-key-backup.asc
```
If the store is kept in Git, clone it to `~/.password-store` using your
password-store repository URL. Verify that all required secrets can be
decrypted without printing their values:
```bash
pass show self-host/token/audible-activation-bytes >/dev/null
pass show self-host/token/aquaai >/dev/null
pass show self-host/token/todoist >/dev/null
```
`settings.conf` is rendered using `pass`, so applying it requires these
entries and the matching private key. Never commit keys or plaintext tokens.
4. Review and apply the dotfiles, then open a new terminal:
```bash
chezmoi diff
chezmoi apply
```
Linux-only configuration and scripts are automatically ignored on macOS.
To install newly added macOS dependencies later:
```bash
brew bundle --file="$(chezmoi source-path ~/.brewfile)"
```
### System preferences
Close System Settings, then review and run the optional setup script as your
normal user (not with `sudo`):
```bash
~/bin/setup-macos.sh --dry-run
~/bin/setup-macos.sh
```
It enables dark mode and Dock auto-hide, disables natural scrolling and
swipe-to-navigate, and removes window-tiling margins (macOS Sequoia and later).
Animation settings and machine-specific state, such as Dock contents and
monitor/Spaces layouts, are left unchanged.
The script is safe to rerun but does not back up previous values or run
automatically during `chezmoi apply`. Log out and back in if changes are not
visible.
### Hover window focus
AutoRaise focuses and raises windows on hover. Its settings are managed in
`~/.config/AutoRaise/config`.
After installing dependencies and applying the dotfiles, enable it at login:
```bash
brew services start dimentium/autoraise/autoraise
```
Grant AutoRaise access in **System Settings → Privacy & Security → Accessibility**.
If it is not listed, use **+**, press **Cmd+Shift+G**, and enter the path printed by
`echo "$(brew --prefix autoraise)/bin/AutoRaise"`. Then restart it with
`brew services restart dimentium/autoraise/autoraise`.
Hold **Control** to temporarily suspend hover focus. To turn it off entirely:
```bash
brew services stop dimentium/autoraise/autoraise
```
+4
View File
@@ -0,0 +1,4 @@
encryption = "gpg"
[gpg]
recipient = "02C20A131365D6EF3CC4A023B9BDD0975CF5592D"
+61
View File
@@ -0,0 +1,61 @@
{{ if eq .chezmoi.os "darwin" -}}
# Linux desktop configuration
.config/g13
.config/gtk-3.0
.config/gtk-4.0
.config/hypr
.config/i3
.config/mako
.config/polybar
.config/quickshell
.config/rofi
.config/waybar
# Linux services and PipeWire configuration
.config/systemd
.config/wireplumber
.local/share/wireplumber
user/*.service
# Linux package installers and desktop startup scripts
bin/installers
bin/desktop
bin/system
bin/i3-mouse.py
bin/i3wm-config-gen.sh
bin/i3wm-for-window-gen.sh
bin/launch-stocks-tracker.py
bin/start-firefox.py
bin/start-brave.sh
# Linux hardware, screen locking, and NAS mounting
bin/get-mouse-battery.sh
bin/lock.sh
bin/toggle-graphics.sh
bin/trackpad-toggle.sh
bin/connect-nas.sh
# ALSA/PipeWire routing and Rofi prompts; keep portable audio utilities
bin/audio/audio-lib.sh
bin/audio/aquamix.sh
bin/audio/es8start.sh
bin/audio/es9start.sh
bin/audio/es9stop.sh
bin/audio/system-start-audio.sh
bin/audio/synth-power-prompt.sh
# Wine-based Adobe DNG conversion with GNU date
bin/video/cr3todng.sh
{{ else -}}
# Homebrew dependencies are only managed on macOS.
.brewfile
# macOS OrcaSlicer uses a symlink to the shared Linux-style profile directory.
Library/Application Support/OrcaSlicer
{{ end -}}
{{ if ne .chezmoi.os "darwin" -}}
.config/karabiner
.config/AutoRaise
bin/setup-macos.sh
{{ end -}}
+1 -1
View File
@@ -1 +1 @@
openai/gpt-5.6-luna-fast openai/gpt-5.6-luna
@@ -0,0 +1 @@
{{ .chezmoi.homeDir }}/.config/OrcaSlicer/user/default
@@ -0,0 +1,23 @@
#!/bin/bash
# Start the systemd-managed Quickshell bar in the current graphical session.
if ! command -v qs &> /dev/null; then
if [ "${XDG_SESSION_TYPE}" = "x11" ]; then
~/bin/desktop/polybar-start.sh
fi
exit 0
fi
if [ "${XDG_SESSION_TYPE}" = "x11" ]; then
systemctl --user unset-environment WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE
systemctl --user set-environment QT_QPA_PLATFORM=xcb
else
systemctl --user set-environment QT_QPA_PLATFORM=wayland
fi
systemctl --user import-environment DISPLAY XAUTHORITY WAYLAND_DISPLAY XDG_SESSION_TYPE XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE I3SOCK
if [ "$(hostname)" = "desktop" ]; then
systemctl --user set-environment QUICKSHELL_BAR_SCREEN=DP-2
else
systemctl --user unset-environment QUICKSHELL_BAR_SCREEN
fi
systemctl --user restart quickshell-bar.service
+58
View File
@@ -0,0 +1,58 @@
#!/bin/bash
# Apply curated macOS preferences without copying machine-specific state.
set -euo pipefail
function usage {
echo "Usage: ${0##*/} [--dry-run]"
echo "Apply macOS preferences for the current user. Do not run with sudo."
}
dry_run=false
case "${1:-}" in
--dry-run) dry_run=true ;;
--help|-h) usage; exit 0 ;;
"") ;;
*) usage >&2; exit 1 ;;
esac
if [[ $# -gt 1 ]]; then
usage >&2
exit 1
fi
if [[ "$(uname -s)" != "Darwin" ]]; then
echo "This script only supports macOS." >&2
exit 1
fi
if [[ "$EUID" -eq 0 ]]; then
echo "Run this script as your normal user, not with sudo." >&2
exit 1
fi
function write_preference {
if [[ "$dry_run" == true ]]; then
printf '%q ' defaults write "$@"
printf '\n'
elif ! defaults write "$@"; then
echo "Could not write preference: $1 $2" >&2
exit 1
fi
}
# Existing preferences observed on this Mac. This is not a full defaults export:
# macOS also stores stock values, histories, and hardware-specific state there.
# Use dark appearance and automatically hide the Dock.
write_preference NSGlobalDomain AppleInterfaceStyle -string Dark
write_preference com.apple.dock autohide -bool true
# Use traditional scrolling and disable swipe-based back/forward navigation.
write_preference NSGlobalDomain com.apple.swipescrolldirection -bool false
write_preference NSGlobalDomain AppleEnableSwipeNavigateWithScrolls -bool false
# Remove the gaps around tiled windows (macOS Sequoia and later).
write_preference com.apple.WindowManager EnableTiledWindowMargins -bool false
if [[ "$dry_run" == false ]]; then
echo "Preferences saved. Log out and back in if changes are not visible."
fi
+38 -18
View File
@@ -22,8 +22,7 @@ function dnfUpdate {
function aptUpdate { function aptUpdate {
if command -v apt &> /dev/null; then if command -v apt &> /dev/null; then
echo Updating APT... echo Updating APT...
sudo apt update sudo apt update && sudo apt upgrade
sudo apt upgrade
fi fi
} }
@@ -31,22 +30,31 @@ function aptUpdate {
function flatpakUpdate { function flatpakUpdate {
if command -v flatpak &> /dev/null; then if command -v flatpak &> /dev/null; then
echo Updating Flatpak... echo Updating Flatpak...
flatpak uninstall --unused flatpak uninstall --unused && flatpak update
flatpak update
fi fi
} }
# Appimage Updater # Appimage Updater
function appimageUpdate { function appimageUpdate {
if command -v am &> /dev/null; then
echo Updating AppImages...
am update am update
fi
}
# Homebrew Updater
function brewUpdate {
if command -v brew &> /dev/null; then
echo Updating Homebrew...
brew update && brew upgrade
fi
} }
# Pass Repository Updater # Pass Repository Updater
function passUpdate { function passUpdate {
if [ -d "$HOME/.password-store/.git" ] && [ -d "$HOME/.password-store" ]; then if [ -d "$HOME/.password-store/.git" ] && [ -d "$HOME/.password-store" ]; then
echo Updating pass repository... echo Updating pass repository...
cd "$HOME/.password-store" git -C "$HOME/.password-store" pull
git pull
fi fi
} }
@@ -72,16 +80,28 @@ function manualUpdate {
fi fi
} }
chezmoiUpdate update_failed=0
echo ''
dnfUpdate
aptUpdate
echo ''
flatpakUpdate
echo ''
appimageUpdate
echo ''
manualUpdate
echo ''
passUpdate
# Report failures while allowing the remaining updaters to run.
function run_updater {
if ! "$1"; then
echo "Updater failed: $1" >&2
update_failed=1
fi
}
run_updater chezmoiUpdate
echo ''
run_updater brewUpdate
run_updater dnfUpdate
run_updater aptUpdate
echo ''
run_updater flatpakUpdate
echo ''
run_updater appimageUpdate
echo ''
run_updater manualUpdate
echo ''
run_updater passUpdate
exit "$update_failed"
+2 -1
View File
@@ -7,6 +7,7 @@ import datetime as dt
import re import re
import operator import operator
import os import os
import shlex
import sys import sys
import tbapy import tbapy
from todoist_api_python.api import TodoistAPI from todoist_api_python.api import TodoistAPI
@@ -105,7 +106,7 @@ configParser.read_string(configString)
# Load needed credentials # Load needed credentials
tbaKey = configParser.get('Settings', 'TBAKey') tbaKey = configParser.get('Settings', 'TBAKey')
todoistToken = configParser.get('Settings', 'TodoistToken') todoistToken = shlex.split(configParser.get('Settings', 'TodoistToken'))[0]
# Setup Todoist # Setup Todoist
api = TodoistAPI(todoistToken) api = TodoistAPI(todoistToken)
@@ -3,4 +3,4 @@
# Import library # Import library
source $(dirname ${BASH_SOURCE[0]})/install-lib.sh source $(dirname ${BASH_SOURCE[0]})/install-lib.sh
sudo $(packageManager) install sway waybar rofi mako alacritty sudo $(packageManager) install sway waybar quickshell rofi mako alacritty brightnessctl
+1 -2
View File
@@ -5,9 +5,8 @@ pass git pull
# Desktop # Desktop
~/bin/connect-nas.sh ~/bin/connect-nas.sh
systemctl --user start polybar ~/bin/desktop/quickshell-start.sh
systemctl --user restart streamdeck systemctl --user restart streamdeck
waybar &
/usr/libexec/polkit-gnome-authentication-agent-1 & /usr/libexec/polkit-gnome-authentication-agent-1 &
# Keyring # Keyring
+37
View File
@@ -0,0 +1,37 @@
# Shared command-line tools
brew "chezmoi"
brew "git"
brew "emacs"
brew "python"
brew "jq"
# Password-store secrets used by chezmoi templates
brew "pass"
brew "gnupg"
# Web browser
cask "brave-browser"
# Nextcloud file sync
cask "nextcloud"
# Gaming
cask "steam"
# 3D printing
cask "orcaslicer"
# Logitech mouse configuration
cask "logi-options+"
# Terminal and font used by the shared Alacritty configuration
cask "alacritty"
cask "font-inconsolata"
# Focus and raise windows when hovering
tap "dimentium/autoraise"
brew "dimentium/autoraise/autoraise"
# Optional tools for audio conversion and local AI
# brew "ffmpeg"
# brew "ollama"
+10
View File
@@ -0,0 +1,10 @@
# Focus and raise on hover without an intentional delay; never warp the cursor.
pollMillis=50
delay=1
requireMouseStop=true
warpX=0
warpY=0
# Hold Control to temporarily suspend hover focus.
disableKey=control
# Do not steal focus during authentication or screenshot selection.
stayFocusedBundleIds="com.apple.SecurityAgent,com.apple.screencaptureui"
@@ -0,0 +1,5 @@
# Single-quote values and escape embedded single quotes without changing backslashes.
computer='{{ .chezmoi.hostname | replace "'" "'\\''" }}'
activation_bytes='{{ pass "self-host/token/audible-activation-bytes" | replace "'" "'\\''" }}'
AQUAAI_KEY='{{ pass "self-host/token/aquaai" | replace "'" "'\\''" }}'
TodoistToken='{{ pass "self-host/token/todoist" | replace "'" "'\\''" }}'
@@ -0,0 +1,48 @@
import QtQuick
import Quickshell
Block {
id: root
required property var sink
required property var source
signal detailsRequested(var anchorItem)
blockColor: sink && sink.audio && sink.audio.muted
? Theme.foreground : Theme.primary
textColor: sink && sink.audio && sink.audio.muted
? Theme.foregroundDark : Theme.foreground
interactive: true
text: {
if (!sink || !sink.audio)
return "\uf026";
return sink.audio.muted
? "\uf026" : "\uf028 " + Math.round(sink.audio.volume * 100) + "%";
}
secondaryIcon: source && source.audio
? (source.audio.muted
? "file://" + Quickshell.shellPath("icons/microphone-muted.svg")
: "file://" + Quickshell.shellPath("icons/microphone.svg"))
: ""
secondaryText: source && source.audio
? (source.audio.muted ? "OFF"
: Math.round(source.audio.volume * 100) + "%")
: ""
onClicked: mouse => {
if (mouse.button === Qt.LeftButton)
detailsRequested(root);
else if (mouse.button === Qt.MiddleButton && sink && sink.audio)
sink.audio.muted = !sink.audio.muted;
else
Quickshell.execDetached(["qjackctl"]);
}
onWheel: wheel => {
if (!sink || !sink.audio)
return;
const change = wheel.angleDelta.y > 0 ? 0.05 : -0.05;
sink.audio.volume = Math.max(0, Math.min(1.5,
sink.audio.volume + change));
}
}
@@ -0,0 +1,16 @@
import QtQuick
Block {
id: root
required property var service
visible: service.brightness >= 0
blockColor: Theme.secondary
interactive: true
text: "\uf185 " + service.brightness + "%"
onWheel: wheel => {
const change = wheel.angleDelta.y > 0 ? "+5%" : "5%-";
service.setBrightness(change);
}
}
+97
View File
@@ -0,0 +1,97 @@
import QtQuick
import Quickshell
import Quickshell.Services.Pipewire
import Quickshell.Services.UPower
PanelWindow {
id: bar
property var sink: Pipewire.defaultAudioSink
property var source: Pipewire.defaultAudioSource
property var battery: UPower.displayDevice
property var hardware
property bool isWayland: Quickshell.env("XDG_SESSION_TYPE") === "wayland"
|| (!Quickshell.env("XDG_SESSION_TYPE") && !!Quickshell.env("WAYLAND_DISPLAY"))
anchors {
top: true
left: true
right: true
}
implicitHeight: Theme.barHeight
color: Theme.background
PwObjectTracker {
objects: [bar.sink, bar.source]
}
SystemClock {
id: clock
precision: SystemClock.Seconds
}
DetailPopup {
id: detailsPopup
hardware: bar.hardware
sink: bar.sink
source: bar.source
battery: bar.battery
clock: clock
}
Row {
id: leftModules
anchors {
left: parent.left
verticalCenter: parent.verticalCenter
}
height: Theme.blockHeight
spacing: Theme.moduleSpacing
Loader {
height: parent.height
source: bar.isWayland ? "Workspaces.qml" : "I3Workspaces.qml"
}
}
Loader {
anchors.centerIn: parent
width: Math.max(0, Math.min(implicitWidth,
parent.width - leftModules.width - rightModules.width - Theme.blockHeight))
source: bar.isWayland ? "HyprlandTitle.qml" : "I3Title.qml"
}
Row {
id: rightModules
anchors {
right: parent.right
verticalCenter: parent.verticalCenter
rightMargin: Theme.moduleSpacing / 2
}
spacing: Theme.moduleSpacing
AudioBlock {
sink: bar.sink
source: bar.source
onDetailsRequested: anchorItem => detailsPopup.toggle("audio", anchorItem)
}
Network {
service: bar.hardware
onDetailsRequested: anchorItem => detailsPopup.toggle("network", anchorItem)
}
Backlight { service: bar.hardware }
BatteryBlock {
battery: bar.battery
onDetailsRequested: anchorItem => detailsPopup.toggle("battery", anchorItem)
}
Tray { barWindow: bar }
ClockBlock {
clock: clock
onDetailsRequested: anchorItem => detailsPopup.toggle("clock", anchorItem)
}
}
}
@@ -0,0 +1,26 @@
import Quickshell.Services.UPower
Block {
id: root
required property var battery
property int percentage: battery ? Math.round(battery.percentage * 100) : 0
signal detailsRequested(var anchorItem)
visible: battery && battery.ready && battery.isLaptopBattery
interactive: true
blockColor: percentage <= 15 && UPower.onBattery
? Theme.urgent : UPower.onBattery ? Theme.foreground : Theme.secondary
textColor: UPower.onBattery && percentage > 15
? Theme.foregroundDark : Theme.foreground
text: {
if (!UPower.onBattery)
return "\uf1e6 " + percentage + "%";
if (percentage <= 10) return "\uf244 " + percentage + "%";
if (percentage <= 35) return "\uf243 " + percentage + "%";
if (percentage <= 60) return "\uf242 " + percentage + "%";
if (percentage <= 85) return "\uf241 " + percentage + "%";
return "\uf240 " + percentage + "%";
}
onClicked: detailsRequested(root)
}
+61
View File
@@ -0,0 +1,61 @@
import QtQuick
import Quickshell.Widgets
Rectangle {
id: root
property color blockColor: Theme.primary
property color textColor: Theme.foreground
property bool interactive: false
property string text: ""
property string fontFamily: Theme.iconFontFamily
property string secondaryIcon: ""
property string secondaryText: ""
signal clicked(var mouse)
signal doubleClicked(var mouse)
signal wheel(var wheel)
implicitWidth: content.implicitWidth + Theme.contentPadding * 2
implicitHeight: Theme.blockHeight
color: blockColor
Row {
id: content
anchors.centerIn: parent
spacing: 7
Text {
text: root.text
color: root.textColor
font.family: root.fontFamily
font.pixelSize: Theme.fontSize
}
IconImage {
width: 18
height: 18
anchors.verticalCenter: parent.verticalCenter
visible: root.secondaryIcon !== ""
source: root.secondaryIcon
}
Text {
anchors.verticalCenter: parent.verticalCenter
visible: root.secondaryText !== ""
text: root.secondaryText
color: root.textColor
font.family: root.fontFamily
font.pixelSize: Theme.fontSize
}
}
MouseArea {
anchors.fill: parent
enabled: root.interactive
acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton
cursorShape: Qt.PointingHandCursor
onClicked: mouse => root.clicked(mouse)
onDoubleClicked: mouse => root.doubleClicked(mouse)
onWheel: wheel => root.wheel(wheel)
}
}
@@ -0,0 +1,20 @@
Block {
id: root
required property var clock
property bool showSeconds: false
signal detailsRequested(var anchorItem)
function formattedTime() {
const date = clock.date;
const hour = date.getHours() % 12 || 12;
const minute = date.getMinutes().toString().padStart(2, "0");
const second = date.getSeconds().toString().padStart(2, "0");
return hour + ":" + minute + (showSeconds ? ":" + second : "");
}
interactive: true
text: formattedTime()
onClicked: detailsRequested(root)
onDoubleClicked: showSeconds = !showSeconds
}
@@ -0,0 +1,386 @@
import QtQuick
import Quickshell
import Quickshell.Services.UPower
PopupWindow {
id: root
property var hardware
property var sink
property var source
property var battery
property var clock
property var anchorItem: null
property string page: ""
function toggle(nextPage, item) {
if (visible && page === nextPage) {
visible = false;
return;
}
page = nextPage;
anchorItem = item;
if (page === "network")
hardware.refreshWifi();
anchor.updateAnchor();
visible = true;
}
function duration(seconds) {
if (seconds <= 0)
return "Calculating";
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
return hours + "h " + minutes + "m";
}
function batteryState() {
switch (battery.state) {
case UPowerDeviceState.Charging: return "Charging";
case UPowerDeviceState.Discharging: return "Discharging";
case UPowerDeviceState.FullyCharged: return "Fully charged";
case UPowerDeviceState.Empty: return "Empty";
case UPowerDeviceState.PendingCharge: return "Waiting to charge";
case UPowerDeviceState.PendingDischarge: return "Waiting to discharge";
default: return "Unknown";
}
}
visible: false
implicitWidth: Theme.popupWidth
implicitHeight: contentLoader.item
? contentLoader.item.implicitHeight + Theme.popupPadding * 2 : 100
color: "transparent"
anchor {
item: root.anchorItem
edges: Edges.Bottom | Edges.Right
gravity: Edges.Bottom | Edges.Left
margins.top: 4
}
Rectangle {
anchors.fill: parent
color: Theme.popupBackground
Loader {
id: contentLoader
anchors {
left: parent.left
right: parent.right
top: parent.top
margins: Theme.popupPadding
}
sourceComponent: root.page === "clock" ? clockPage
: root.page === "audio" ? audioPage
: root.page === "network" ? networkPage
: batteryPage
}
Rectangle {
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
height: Theme.activeLineWidth
color: Theme.accent
}
}
Component {
id: clockPage
Item {
id: clockContent
property date now: root.clock.date
property int year: now.getFullYear()
property int month: now.getMonth()
property int firstDay: new Date(year, month, 1).getDay()
property int days: new Date(year, month + 1, 0).getDate()
implicitWidth: Theme.popupContentWidth
implicitHeight: 310
PopupHeader {
width: parent.width
text: Qt.formatDateTime(parent.now, "dddd, MMMM d")
}
Text {
anchors {
horizontalCenter: parent.horizontalCenter
top: parent.top
topMargin: 40
}
text: Qt.formatDateTime(parent.now, "h:mm:ss AP")
color: Theme.foreground
font.family: Theme.fontFamily
font.pixelSize: Theme.fontClock
}
Row {
anchors {
left: parent.left
top: parent.top
topMargin: 86
}
spacing: 4
Repeater {
model: ["S", "M", "T", "W", "T", "F", "S"]
Text {
required property string modelData
width: 37
text: modelData
color: Theme.muted
font.family: Theme.fontFamily
horizontalAlignment: Text.AlignHCenter
font.bold: true
}
}
}
Grid {
anchors {
left: parent.left
top: parent.top
topMargin: 112
}
columns: 7
spacing: 4
Repeater {
model: 42
Rectangle {
required property int index
property int day: index - clockContent.firstDay + 1
property bool today: day === clockContent.now.getDate()
width: 37
height: 29
radius: 0
color: today ? Theme.primary : "transparent"
Rectangle {
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
height: Theme.activeLineWidth
visible: parent.today
color: Theme.accent
}
Text {
anchors.centerIn: parent
text: parent.day > 0 && parent.day <= clockContent.days
? parent.day : ""
color: Theme.foreground
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSmall
}
}
}
}
}
}
Component {
id: audioPage
Column {
width: Theme.popupContentWidth
spacing: 12
PopupHeader {
width: parent.width
text: "Audio"
}
PopupSlider {
width: parent.width
label: "Output"
value: root.sink && root.sink.audio ? root.sink.audio.volume : 0
muted: root.sink && root.sink.audio ? root.sink.audio.muted : false
onValueRequested: value => {
if (root.sink && root.sink.audio)
root.sink.audio.volume = value;
}
onMuteRequested: {
if (root.sink && root.sink.audio)
root.sink.audio.muted = !root.sink.audio.muted;
}
}
PopupSlider {
width: parent.width
label: "Microphone"
value: root.source && root.source.audio ? root.source.audio.volume : 0
muted: root.source && root.source.audio ? root.source.audio.muted : false
onValueRequested: value => {
if (root.source && root.source.audio)
root.source.audio.volume = value;
}
onMuteRequested: {
if (root.source && root.source.audio)
root.source.audio.muted = !root.source.audio.muted;
}
}
}
}
Component {
id: networkPage
Column {
width: Theme.popupContentWidth
spacing: 10
PopupHeader {
width: parent.width
text: "Network"
}
Text {
text: "Connected to " + root.hardware.connection
color: Theme.foreground
font.family: Theme.fontFamily
font.pixelSize: Theme.fontBody
}
Column {
id: networks
width: parent.width
spacing: 5
Repeater {
model: root.hardware.wifiNetworks
Rectangle {
required property var modelData
width: networks.width
height: 29
radius: 0
color: modelData.active ? Theme.primary : Theme.background
Rectangle {
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
height: Theme.activeLineWidth
visible: parent.modelData.active
color: Theme.accent
}
Text {
anchors {
left: parent.left
leftMargin: 9
verticalCenter: parent.verticalCenter
}
width: parent.width - 70
elide: Text.ElideRight
text: modelData.ssid
color: Theme.foreground
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSmall
}
Text {
anchors {
right: parent.right
rightMargin: 9
verticalCenter: parent.verticalCenter
}
text: modelData.signal + "%"
color: Theme.foreground
font.family: Theme.fontFamily
font.pixelSize: Theme.fontCaption
}
}
}
}
Rectangle {
width: parent.width
height: 30
radius: 0
color: Theme.primary
Text {
anchors.centerIn: parent
text: "Open network settings"
color: Theme.foreground
font.family: Theme.fontFamily
font.pixelSize: Theme.fontCaption
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: Quickshell.execDetached(["nm-connection-editor"])
}
}
}
}
Component {
id: batteryPage
Column {
width: Theme.popupContentWidth
spacing: 12
PopupHeader {
width: parent.width
text: "Battery"
}
Text {
text: Math.round(root.battery.percentage * 100) + "% "
+ root.batteryState()
color: Theme.foreground
font.family: Theme.fontFamily
font.pixelSize: Theme.fontDisplay
}
Rectangle {
width: parent.width
height: 8
radius: 0
color: Theme.track
Rectangle {
width: parent.width * root.battery.percentage
height: parent.height
radius: 0
color: root.battery.percentage <= 0.15 ? Theme.urgent : Theme.primary
}
}
Text {
text: UPower.onBattery
? "Remaining: " + root.duration(root.battery.timeToEmpty)
: "Until full: " + root.duration(root.battery.timeToFull)
color: Theme.accent
font.family: Theme.fontFamily
font.pixelSize: Theme.fontBody
}
Text {
text: "Rate: " + Math.abs(root.battery.changeRate).toFixed(1) + " W"
+ (root.battery.healthSupported
? " Health: " + Math.round(root.battery.healthPercentage * 100) + "%"
: "")
color: Theme.foreground
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSmall
}
}
}
}
@@ -0,0 +1,130 @@
import QtQuick
import Quickshell
import Quickshell.Io
Scope {
id: root
property string connection: "Disconnected"
property int brightness: -1
property var wifiNetworks: []
function setBrightness(change) {
Quickshell.execDetached(["brightnessctl", "set", change]);
}
function refreshNetwork() {
if (!networkQuery.running)
networkQuery.running = true;
}
function refreshWifi() {
if (!wifiQuery.running)
wifiQuery.running = true;
}
Process {
id: networkQuery
command: ["nmcli", "-t", "-f", "TYPE,NAME", "connection", "show", "--active"]
running: true
stdout: StdioCollector {
onStreamFinished: {
const lines = text.trim().split("\n");
for (let line of lines) {
const separator = line.indexOf(":");
const type = line.slice(0, separator);
if (type === "802-11-wireless" || type === "wifi") {
root.connection = line.slice(separator + 1);
return;
}
}
for (let line of lines) {
const separator = line.indexOf(":");
const type = line.slice(0, separator);
if (type === "802-3-ethernet" || type === "ethernet") {
root.connection = line.slice(separator + 1);
return;
}
}
root.connection = "Disconnected";
}
}
}
Process {
id: networkMonitor
command: ["nmcli", "monitor"]
running: true
stdout: SplitParser {
onRead: {
root.refreshNetwork();
if (root.wifiNetworks.length > 0)
root.refreshWifi();
}
}
onExited: networkRestart.start()
}
Timer {
id: networkRestart
interval: 1000
onTriggered: networkMonitor.running = true
}
function updateBrightness() {
if (!brightnessFile.loaded || !maximumBrightnessFile.loaded)
return;
const current = parseInt(brightnessFile.text().trim());
const maximum = parseInt(maximumBrightnessFile.text().trim());
root.brightness = maximum > 0 && !isNaN(current)
? Math.round(current / maximum * 100) : -1;
}
FileView {
id: brightnessFile
path: "file:///sys/class/backlight/intel_backlight/brightness"
watchChanges: true
onFileChanged: reload()
onLoaded: root.updateBrightness()
}
FileView {
id: maximumBrightnessFile
path: "file:///sys/class/backlight/intel_backlight/max_brightness"
onLoaded: root.updateBrightness()
}
Process {
id: wifiQuery
command: ["nmcli", "-t", "-f", "IN-USE,SSID,SIGNAL", "device", "wifi", "list", "--rescan", "auto"]
stdout: StdioCollector {
onStreamFinished: {
const networks = [];
const seen = {};
for (let line of text.trim().split("\n")) {
const fields = line.split(":");
if (fields.length < 3)
continue;
const active = fields.shift() === "*";
const signal = parseInt(fields.pop());
const ssid = fields.join(":").replace(/\\:/g, ":");
if (!ssid || seen[ssid])
continue;
seen[ssid] = true;
networks.push({
"ssid": ssid,
"signal": signal,
"active": active
});
if (networks.length >= 8)
break;
}
root.wifiNetworks = networks;
}
}
}
}
@@ -0,0 +1,11 @@
import QtQuick
import Quickshell.Hyprland
Text {
elide: Text.ElideRight
horizontalAlignment: Text.AlignHCenter
text: Hyprland.activeToplevel ? Hyprland.activeToplevel.title : ""
color: Theme.foreground
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSize
}
@@ -0,0 +1,40 @@
import QtQuick
import Quickshell.I3
import Quickshell.Io
Text {
id: root
function focusedTitle(node) {
for (const child of (node.nodes || []).concat(node.floating_nodes || [])) {
const title = focusedTitle(child);
if (title)
return title;
}
return node.focused && node.type === "con" ? node.name || "" : "";
}
elide: Text.ElideRight
horizontalAlignment: Text.AlignHCenter
color: Theme.foreground
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSize
Connections {
target: I3
function onRawEvent(event) {
if ((event.type === "window" || event.type === "workspace") && !treeQuery.running)
treeQuery.running = true;
}
}
Process {
id: treeQuery
command: ["i3-msg", "-t", "get_tree"]
running: true
stdout: StdioCollector {
onStreamFinished: root.text = root.focusedTitle(JSON.parse(text))
}
}
}
@@ -0,0 +1,48 @@
import QtQuick
import Quickshell.I3
Row {
spacing: 0
Repeater {
model: I3.workspaces
Rectangle {
id: workspaceButton
required property var modelData
property bool active: modelData.active
visible: modelData.number > 0
width: visible ? Theme.blockHeight + 2 : 0
height: parent.height
color: modelData.urgent ? Theme.urgent
: active ? Theme.primary : "transparent"
Rectangle {
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
height: Theme.activeLineWidth
color: workspaceButton.active ? Theme.accent : "transparent"
}
Text {
anchors.centerIn: parent
text: modelData.number === 2 ? "\uf120"
: modelData.number === 13 ? "\uf001" : modelData.name
color: Theme.foreground
font.family: Theme.iconFontFamily
font.pixelSize: Theme.fontSize
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: workspaceButton.modelData.activate()
}
}
}
}
@@ -0,0 +1,20 @@
import QtQuick
import Quickshell
Block {
id: root
required property var service
property bool connected: service.connection !== "Disconnected"
signal detailsRequested(var anchorItem)
blockColor: connected ? Theme.secondary : Theme.urgent
interactive: true
text: connected ? "\uf1eb " + service.connection : "Disconnected !"
onClicked: mouse => {
if (mouse.button === Qt.LeftButton)
detailsRequested(root);
else
Quickshell.execDetached(["nm-connection-editor"]);
}
}
@@ -0,0 +1,23 @@
import QtQuick
Rectangle {
id: root
property string text: ""
implicitHeight: Theme.blockHeight
color: Theme.primary
Text {
anchors {
left: parent.left
leftMargin: Theme.contentPadding
verticalCenter: parent.verticalCenter
}
text: root.text
color: Theme.foreground
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSize
font.bold: true
}
}
@@ -0,0 +1,82 @@
import QtQuick
Item {
id: root
property string label: ""
property real value: 0
property bool muted: false
signal valueRequested(real value)
signal muteRequested()
implicitWidth: 280
implicitHeight: 58
Text {
anchors.left: parent.left
text: root.label
color: Theme.foreground
font.family: Theme.fontFamily
font.pixelSize: Theme.fontBody
}
Rectangle {
anchors {
right: parent.right
top: parent.top
}
width: 58
height: 24
radius: 0
color: root.muted ? Theme.urgent : Theme.primary
Text {
anchors.centerIn: parent
text: root.muted ? "MUTED" : Math.round(root.value * 100) + "%"
color: Theme.foreground
font.pixelSize: Theme.fontTiny
font.bold: true
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: root.muteRequested()
}
}
Rectangle {
id: track
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
height: 8
radius: 0
color: Theme.track
Rectangle {
width: Math.min(parent.width, parent.width * root.value / 1.5)
height: parent.height
radius: 0
color: root.muted ? Theme.urgent : Theme.primary
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
function updateValue(mouse) {
root.valueRequested(Math.max(0,
Math.min(1.5, mouse.x / width * 1.5)));
}
onPressed: mouse => updateValue(mouse)
onPositionChanged: mouse => {
if (pressed)
updateValue(mouse);
}
}
}
}
+36
View File
@@ -0,0 +1,36 @@
pragma Singleton
import QtQuick
import Quickshell
Singleton {
readonly property color background: "#80000000"
readonly property color popupBackground: "#e0000000"
readonly property color primary: "#0288d1"
readonly property color secondary: "#2980b9"
readonly property color accent: "#b3e5fc"
readonly property color urgent: "#e91e63"
readonly property color foreground: "#ffffff"
readonly property color foregroundDark: "#000000"
readonly property color muted: "#7aa6da"
readonly property color track: "#40000000"
readonly property string fontFamily: "SF Pro Display, Helvetica, Arial, sans-serif"
readonly property string iconFontFamily: "SF Pro Display, Font Awesome 6 Free"
readonly property int barHeight: 32
readonly property int blockHeight: 32
readonly property int fontSize: 18
readonly property int fontTiny: 11
readonly property int fontCaption: 13
readonly property int fontSmall: 14
readonly property int fontBody: 15
readonly property int fontDisplay: 25
readonly property int fontClock: 30
readonly property int moduleSpacing: 8
readonly property int contentPadding: 10
readonly property int activeLineWidth: 3
readonly property int popupWidth: 320
readonly property int popupPadding: 12
readonly property int popupContentWidth: popupWidth - popupPadding * 2
}
+66
View File
@@ -0,0 +1,66 @@
import QtQuick
import Quickshell.Services.SystemTray
import Quickshell.Widgets
Rectangle {
id: root
required property var barWindow
visible: trayRepeater.count > 0
implicitWidth: trayItems.implicitWidth + Theme.contentPadding * 2
implicitHeight: Theme.blockHeight
color: Theme.primary
Row {
id: trayItems
anchors.centerIn: parent
spacing: Theme.contentPadding
Repeater {
id: trayRepeater
model: SystemTray.items
Item {
id: trayItem
required property var modelData
width: 26
height: 30
IconImage {
anchors {
fill: parent
margins: 3
}
source: trayItem.modelData.icon
opacity: trayMouse.containsMouse ? 1 : 0.82
Behavior on opacity {
NumberAnimation { duration: 120 }
}
}
MouseArea {
id: trayMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton
onClicked: mouse => {
if (mouse.button === Qt.MiddleButton) {
trayItem.modelData.secondaryActivate();
} else if (mouse.button === Qt.RightButton || trayItem.modelData.onlyMenu) {
const point = mapToItem(root.barWindow.contentItem, 0, height);
trayItem.modelData.display(root.barWindow, point.x, point.y);
} else {
trayItem.modelData.activate();
}
}
onWheel: wheel => trayItem.modelData.scroll(
wheel.angleDelta.y, false)
}
}
}
}
}
@@ -0,0 +1,53 @@
import QtQuick
import Quickshell
import Quickshell.Hyprland
Row {
spacing: 0
Repeater {
model: Hyprland.workspaces
Rectangle {
id: workspaceButton
required property var modelData
property bool active: modelData.active
visible: modelData.id > 0
width: Theme.blockHeight + 2
height: parent.height
color: modelData.urgent ? Theme.urgent
: active ? Theme.primary : "transparent"
Rectangle {
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
height: Theme.activeLineWidth
color: workspaceButton.active ? Theme.accent : "transparent"
}
Text {
anchors.centerIn: parent
text: modelData.id === 2 ? "\uf120"
: modelData.id === 13 ? "\uf001" : modelData.name
color: Theme.foreground
font.family: Theme.iconFontFamily
font.pixelSize: Theme.fontSize
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: Quickshell.execDetached([
"hyprctl",
"dispatch",
"hl.dsp.focus({ workspace = " + workspaceButton.modelData.id + " })"
])
}
}
}
}
@@ -0,0 +1,6 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg">
<g fill="#ffffff">
<path d="M8 1C6.34 1 5 2.34 5 4v4c0 1.66 1.34 3 3 3 .36 0 .7-.07 1.02-.18.04-.45.23-.89.57-1.23.33-.33.77-.54 1.23-.58.11-.32.18-.66.18-1.01V4c0-1.66-1.34-3-3-3zm0 2c.55 0 1 .45 1 1v4c0 .55-.45 1-1 1s-1-.45-1-1V4c0-.55.45-1 1-1zM2 7v1.01c0 2.96 2.16 5.42 5 5.9V16h2v-2.09c.13-.02.25-.05.38-.08a2 2 0 0 1 .21-.24l.41-.42v-.34l-.41-.42a2 2 0 0 1-.15-.16A4.5 4.5 0 0 1 3.5 8.01V7z" opacity=".7"/>
<path d="M11 10a1 1 0 0 0-.71 1.71L11.59 13l-1.3 1.29a1 1 0 1 0 1.42 1.42L13 14.41l1.29 1.3a1 1 0 1 0 1.42-1.42L14.41 13l1.3-1.29a1 1 0 1 0-1.42-1.42L13 11.59l-1.29-1.3A1 1 0 0 0 11 10z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 710 B

@@ -0,0 +1,3 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg">
<path d="M8 0C6.34 0 5 1.34 5 3v5c0 1.66 1.34 3 3 3s3-1.34 3-3V3c0-1.66-1.34-3-3-3zM2 6v2.01c0 2.96 2.16 5.43 5 5.91V16h2v-2.08c2.84-.48 5-2.94 5-5.91V6h-1.5v2.01c0 2.5-1.99 4.49-4.5 4.49s-4.5-1.99-4.5-4.49V6z" fill="#ffffff"/>
</svg>

After

Width:  |  Height:  |  Size: 321 B

+19
View File
@@ -0,0 +1,19 @@
import Quickshell
ShellRoot {
HardwareService {
id: hardwareService
}
Variants {
model: Quickshell.screens
Bar {
required property var modelData
screen: modelData
visible: !Quickshell.env("QUICKSHELL_BAR_SCREEN")
|| modelData.name === Quickshell.env("QUICKSHELL_BAR_SCREEN")
hardware: hardwareService
}
}
}
-4
View File
@@ -1,4 +0,0 @@
computer={{ .chezmoi.hostname }}
activation_bytes={{ pass "self-host/token/audible-activation-bytes" }}
AQUAAI_KEY={{ pass "self-host/token/aquaai" }}
TodoistToken={{ pass "self-host/token/todoist" }}
@@ -0,0 +1,15 @@
[Unit]
Description=Quickshell desktop bar
Documentation=https://quickshell.org/
After=graphical-session.target
PartOf=graphical-session.target
[Service]
Type=simple
ExecStart=/usr/bin/qs -c bar --no-duplicate
Restart=on-failure
RestartSec=2
TimeoutStopSec=5
[Install]
WantedBy=graphical-session.target
+5
View File
@@ -12,3 +12,8 @@
sort = -committerdate sort = -committerdate
[push] [push]
autoSetupRemote = true autoSetupRemote = true
[filter "lfs"]
required = true
clean = git-lfs clean -- %f
smudge = git-lfs smudge -- %f
process = git-lfs filter-process
-10
View File
@@ -1,10 +0,0 @@
sh ~/.config/scripts/setup.sh -nr
# Load user settings from config file.
. ~/.config/settings.conf
if [[ $computer == 'w530' ]]; then
if [[ ! $DISPLAY && $XDG_VTNR -eq 1 ]]; then
exec startx
fi
fi
+25
View File
@@ -0,0 +1,25 @@
{{ if eq .chezmoi.os "darwin" -}}
# Initialize Homebrew on Apple Silicon or Intel Macs.
if [[ -x /opt/homebrew/bin/brew ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
elif [[ -x /usr/local/bin/brew ]]; then
eval "$(/usr/local/bin/brew shellenv)"
fi
{{ else if eq .chezmoi.os "linux" -}}
if [[ -f "$HOME/.config/scripts/setup.sh" ]]; then
sh "$HOME/.config/scripts/setup.sh" -nr
fi
{{ end }}
# Load user settings from config file.
if [[ -f "$HOME/.config/settings.conf" ]]; then
source "$HOME/.config/settings.conf"
fi
{{ if eq .chezmoi.os "linux" -}}
if [[ $computer == 'w530' ]]; then
if [[ ! $DISPLAY && $XDG_VTNR -eq 1 ]]; then
exec startx
fi
fi
{{ end -}}
+42 -13
View File
@@ -5,24 +5,45 @@ setopt PROMPT_SUBST
PROMPT='%F{white}%n% @%m%f %F{blue}%~%f %F{red}${vcs_info_msg_0_}%f$ ' PROMPT='%F{white}%n% @%m%f %F{blue}%~%f %F{red}${vcs_info_msg_0_}%f$ '
setopt appendhistory autocd extendedglob nomatch notify setopt appendhistory autocd extendedglob nomatch notify
setopt hist_ignore_all_dups hist_save_no_dups hist_find_no_dups
unsetopt beep unsetopt beep
bindkey -e bindkey -e
zstyle :compinstall filename '~/.zshrc' zstyle :compinstall filename '~/.zshrc'
# Keep PATH entries unique when shell configuration is sourced again.
typeset -U path PATH
{{ if eq .chezmoi.os "darwin" -}}
# Load Homebrew completions before initializing completion support.
typeset -U fpath
if [[ -n "$HOMEBREW_PREFIX" && -d "$HOMEBREW_PREFIX/share/zsh/site-functions" ]]; then
fpath=("$HOMEBREW_PREFIX/share/zsh/site-functions" $fpath)
elif [[ -d /opt/homebrew/share/zsh/site-functions ]]; then
fpath=(/opt/homebrew/share/zsh/site-functions $fpath)
elif [[ -d /usr/local/share/zsh/site-functions ]]; then
fpath=(/usr/local/share/zsh/site-functions $fpath)
fi
{{ end -}}
autoload -Uz compinit autoload -Uz compinit
compinit compinit
HISTFILE=~/.zsh_history HISTFILE=~/.zsh_history
HISTSIZE=99999999 HISTSIZE=100000
SAVEHIST=99999999 SAVEHIST=50000
source "$HOME/.config/settings.conf" if [[ -f "$HOME/.config/settings.conf" ]]; then
source "$HOME/.config/settings.conf"
fi
# User scripts
path=("$HOME/bin" $path)
export PATH
# Text Editor # Text Editor
export EDITOR='emacs -nw' export EDITOR='emacs -nw'
alias emacs="${EDITOR}" alias emacs="${EDITOR}"
alias e="${EDITOR}" alias e="${EDITOR}"
export TERM=xterm
# Search # Search
alias g='grep -Irn' alias g='grep -Irn'
@@ -36,16 +57,21 @@ alias dote="${DOT_PROGRAM} edit --apply"
alias dotu="${DOT_PROGRAM} update" alias dotu="${DOT_PROGRAM} update"
# Other # Other
{{ if eq .chezmoi.os "darwin" -}}
alias i='brew install'
alias d='brew'
{{ else -}}
alias i='sudo dnf install' alias i='sudo dnf install'
alias d='sudo dnf' alias d='sudo dnf'
alias u='sh ~/bin/update.sh' {{ end -}}
alias u='bash ~/bin/update.sh'
alias h='cd ~/git/cacolglazier.com/ && hugo server' alias h='cd ~/git/cacolglazier.com/ && hugo server'
# OpenCode # OpenCode
export PATH="$HOME/.opencode/bin:$PATH" path=("$HOME/.opencode/bin" $path)
OPENCODE='opencode' OPENCODE='opencode'
alias o="${OPENCODE}" alias o="${OPENCODE}"
alias oc="${OPENCODE} --agent commit run 'Create a commit.'" alias oc="${OPENCODE} run --agent commit --model '{{ includeTemplate ".chezmoitemplates/models/small-brain" | trim }}' 'Create a commit.'"
alias ocr="${OPENCODE} --agent review --prompt 'Code review staged changes.'" alias ocr="${OPENCODE} --agent review --prompt 'Code review staged changes.'"
alias or="${OPENCODE} --continue" alias or="${OPENCODE} --continue"
@@ -76,11 +102,14 @@ export AQUAAI_RICH_FORMAT_MODE=false
export AQUAAI_KEY export AQUAAI_KEY
# Daisy build toolkit # Daisy build toolkit
GCC_PATH=~/dev/gcc-arm-none-eabi-10-2020-q4-major/bin GCC_PATH="$HOME/dev/gcc-arm-none-eabi-10-2020-q4-major/bin"
export PATH=$GCC_PATH:$PATH if [[ -d "$GCC_PATH" ]]; then
path=("$GCC_PATH" $path)
fi
# AM auto complete # AM auto complete
autoload bashcompinit if [[ -f "$HOME/.local/share/bash-completion/completions/am" ]]; then
bashcompinit autoload bashcompinit
source "/home/aqua/.local/share/bash-completion/completions/am" bashcompinit
source "$HOME/.local/share/bash-completion/completions/am"
fi
@@ -0,0 +1,19 @@
-----BEGIN PGP MESSAGE-----
hQGMA4qZwZB4gWrxAQv+IYT0PC4dEdl85V1geFnz+xd7nSSpOdyJ1/0QQQ23zOUw
c3sqMRNzzMcSQwHbBOk69QPbF2kW/2W3XsU7qCGnbownr/vaBSrnvx1UxDepd8E3
j1XO0n0o24xBXGZi3xnQBPIJCtjlgNvtREslFz3fgBT8M69gDGynuytn3ZlAM4ni
BmZjnZsz6JKZ76H+mNJ3n6jYZjCbqPVjKyWBiYDRkpVLHntz/OHQCcHfsHpr8CZ2
JgRlqMcwTJGtLVxxZx9eQ6KSkizQvPmy1weqC85NkKkuAENBCUCyh+IJSEpifSyF
ewvOljGDSZOjDL553x+POjVGbtK/U/n162La0kLBQQVJwDSRIIJyTu5/ZLWde12F
mZNObOq4JJzUBbKJtYqRFl51Po3hcWhcXxaDcay7i/MWEesEnsFaKnbCEhJ7FMUa
1+VUQySgU5j9ULxfeaqLYZ2LClA7AGatHt0q1J6UhFSHkBFcmZTjFrlQFjkL2XVu
qvptke90iaepRuMHqTUR0sBpAQT4/pqbDep1npJf11hOwf5ICOPRkJ2Y/iIjZKc7
+d8akX4RlCUfROqsXykZ+W5a+e8gWcsvLGAaeQxUHZ3goNAutrzux2ye9FcQRI3d
pTvu9m/PvoRpYRmx0YgB4VkWVX9Qd9ezderBZIfAcdBfWY8Z1BHPLFyOS/kYoqrv
U/yVkFsXGgOfxRAc+r8HhcCHfMLWXwCoLDmKCMYBPca4psl/oVec4KTkG3nNbaXf
sZ6zxnXv0WuazEIBZSRKSuaN8iQ50LUKh8oxoyzjqg0U/0LshYruanDVk28YXtnx
LTh3jlTAAx6s2VN/ZhJSbnyL2faLfnqwo50GeJQsAt1aI1PZmdbXSB5fthU+XTaW
RWjjMOZELZxkibUtlMchSnZP1gMYBP+rNuFy
=BfV6
-----END PGP MESSAGE-----
+2
View File
@@ -0,0 +1,2 @@
# Host entries are managed in a separately encrypted file.
Include ~/.ssh/config.private