Compare commits
3 Commits
f30bf8a3bd
...
f99cfeae79
| Author | SHA1 | Date | |
|---|---|---|---|
| f99cfeae79 | |||
| 34acd648c9 | |||
| 9647feebfa |
@@ -1 +0,0 @@
|
||||
../idle-inhibitor-monitor.service
|
||||
@@ -28,6 +28,7 @@ local cutKind: string? = nil
|
||||
local deleteRelative: string? = nil
|
||||
local operationError: string? = nil
|
||||
local searchMode = false
|
||||
local pendingNavigation: { vaultPath: string, currentDir: string, selectedRelative: string }? = nil
|
||||
local loading = false
|
||||
local loadError: string? = nil
|
||||
local render: () -> ()
|
||||
@@ -231,6 +232,54 @@ local function selectedEntry(): any?
|
||||
return visible[selected]
|
||||
end
|
||||
|
||||
local function navigationStatePath(): string?
|
||||
local dataDir = noctalia.pluginDataDir()
|
||||
if type(dataDir) ~= "string" then
|
||||
return nil
|
||||
end
|
||||
return dataDir .. "/navigation-state.json"
|
||||
end
|
||||
|
||||
local function saveNavigation()
|
||||
if vaultPath == "" then
|
||||
return
|
||||
end
|
||||
local path = navigationStatePath()
|
||||
if path == nil then
|
||||
return
|
||||
end
|
||||
local entry = selectedEntry()
|
||||
noctalia.writeFile(path, noctalia.json.encode({
|
||||
vaultPath = vaultPath,
|
||||
currentDir = currentDir,
|
||||
selectedRelative = entry ~= nil and tostring(entry.relative or "") or "",
|
||||
}))
|
||||
end
|
||||
|
||||
local function loadNavigation(): { vaultPath: string, currentDir: string, selectedRelative: string }?
|
||||
local path = navigationStatePath()
|
||||
if path == nil then
|
||||
return nil
|
||||
end
|
||||
local raw = noctalia.readFile(path)
|
||||
if type(raw) ~= "string" then
|
||||
return nil
|
||||
end
|
||||
local saved = noctalia.json.decode(raw)
|
||||
if type(saved) ~= "table"
|
||||
or type(saved.vaultPath) ~= "string"
|
||||
or type(saved.currentDir) ~= "string"
|
||||
or type(saved.selectedRelative) ~= "string"
|
||||
then
|
||||
return nil
|
||||
end
|
||||
return {
|
||||
vaultPath = saved.vaultPath,
|
||||
currentDir = saved.currentDir,
|
||||
selectedRelative = saved.selectedRelative,
|
||||
}
|
||||
end
|
||||
|
||||
local function fullMarkdown(note: any): string
|
||||
local lines = note.lines or {}
|
||||
if #lines == 0 then
|
||||
@@ -245,6 +294,7 @@ local function setSelected(index: number)
|
||||
end
|
||||
selected = math.max(1, math.min(index, #visible))
|
||||
previewTop = 1
|
||||
saveNavigation()
|
||||
render()
|
||||
end
|
||||
|
||||
@@ -452,6 +502,7 @@ local function enterSelected()
|
||||
selected = 1
|
||||
previewTop = 1
|
||||
applyFilter()
|
||||
saveNavigation()
|
||||
render()
|
||||
else
|
||||
enterReader(entry)
|
||||
@@ -473,6 +524,7 @@ local function goParent()
|
||||
end
|
||||
end
|
||||
previewTop = 1
|
||||
saveNavigation()
|
||||
render()
|
||||
end
|
||||
|
||||
@@ -827,7 +879,11 @@ local function completeIndexLoad(selectAfterRefresh: string?, actionAfterRefresh
|
||||
selected = 1
|
||||
applyFilter()
|
||||
end
|
||||
elseif pendingNavigation ~= nil then
|
||||
selectRelative(pendingNavigation.selectedRelative)
|
||||
end
|
||||
pendingNavigation = nil
|
||||
saveNavigation()
|
||||
render()
|
||||
end
|
||||
|
||||
@@ -945,14 +1001,19 @@ validateVault = function(candidate: string?, actionAfterValidation: string?)
|
||||
vaultName = tostring(info.name or "")
|
||||
obsidianVaultId = type(info.vaultId) == "string" and info.vaultId or nil
|
||||
obsidianError = type(info.obsidianError) == "string" and info.obsidianError or nil
|
||||
currentDir = ""
|
||||
selected = 1
|
||||
if actionAfterValidation == "save" then
|
||||
pendingNavigation = nil
|
||||
local dataDir = noctalia.pluginDataDir()
|
||||
if type(dataDir) == "string" then
|
||||
noctalia.writeFile(dataDir .. "/vault-path.txt", vaultPath)
|
||||
end
|
||||
end
|
||||
if pendingNavigation ~= nil and pendingNavigation.vaultPath == vaultPath then
|
||||
currentDir = pendingNavigation.currentDir
|
||||
else
|
||||
currentDir = ""
|
||||
end
|
||||
selected = 1
|
||||
refreshIndex()
|
||||
end, 10000)
|
||||
end
|
||||
@@ -969,11 +1030,12 @@ local function configuredVaultPath(): string
|
||||
end
|
||||
|
||||
function onClose()
|
||||
saveNavigation()
|
||||
end
|
||||
|
||||
function onOpen(_context)
|
||||
-- A plugin runtime can outlive panel-close/open cycles, but user navigation
|
||||
-- must always reopen at the finder root.
|
||||
-- A plugin runtime can outlive panel-close/open cycles; restore navigation
|
||||
-- only when it belongs to the currently configured vault.
|
||||
vaultEditMode = false
|
||||
vaultEditPath = ""
|
||||
searchMode = false
|
||||
@@ -987,6 +1049,7 @@ function onOpen(_context)
|
||||
readerMode = false
|
||||
readerNote = nil
|
||||
query = ""
|
||||
pendingNavigation = loadNavigation()
|
||||
currentDir = ""
|
||||
selected = 1
|
||||
previewTop = 1
|
||||
|
||||
@@ -4,7 +4,7 @@ local PANEL_ID = "alex/knowledge-lookup:panel"
|
||||
|
||||
function update()
|
||||
barWidget.setGlyph("book-2")
|
||||
barWidget.setText("KB")
|
||||
barWidget.setText("")
|
||||
barWidget.setTooltip("Knowledge lookup · Super+N")
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
.ruff_cache/
|
||||
@@ -0,0 +1,79 @@
|
||||
# system-config
|
||||
|
||||
A small, declarative Arch configuration managed by Decman.
|
||||
|
||||
## Design
|
||||
|
||||
- **Concerns live in `packages/`**: each concern has a native (`*-repo.txt`)
|
||||
and AUR (`*-aur.txt`) list.
|
||||
- **Hosts live in `hosts.py`**: a host composes concerns. `laptop()` contains
|
||||
every explicit package. `desktop()` begins with shared concerns only.
|
||||
- **System files live in `config/system/`**: shared files go in `common/`;
|
||||
hardware, sleep/logind, and boot policy go in the relevant host directory.
|
||||
- **State lives in `manifests/`**: units follow the same concern and host
|
||||
scopes as packages.
|
||||
- **Python glue lives in `modules/`**: package and system-state adapters only.
|
||||
|
||||
No yadm migration, user-home dotfiles, or application state is managed here.
|
||||
Those can be added later as small, explicit modules.
|
||||
|
||||
## System policy
|
||||
|
||||
- `config/system/common/pacman/pacman.conf` enables only the official core,
|
||||
extra, and multilib repositories. No debug repository is enabled.
|
||||
- `config/system/common/makepkg/makepkg.conf` sets `OPTIONS` with `!debug`, so
|
||||
newly built packages do not produce debug packages.
|
||||
- `config/system/common/locale/` owns locale generation and system locale.
|
||||
- `config/system/common/keyboard/` owns console and X11 keyboard policy.
|
||||
- `config/system/laptop/sleep.conf.d/` owns sleep policy; the logind drop-in
|
||||
remains in `config/system/laptop/systemd/`.
|
||||
- `config/system/laptop/power/tlp.conf` owns laptop power policy. TLP reads
|
||||
`/etc/tlp.conf` after drop-ins, so a whole-file policy is required here.
|
||||
- `config/system/laptop/boot/mkinitcpio.conf` owns encrypted-root and resume
|
||||
initramfs hooks; its module rebuilds the initramfs after a change.
|
||||
- `config/system/laptop/refind/` owns the laptop ESP rEFInd configuration and
|
||||
encrypted-root kernel options. It is intentionally laptop-only.
|
||||
- `config/system/laptop/iwlwifi.conf` retains the Wi-Fi 6 stability workaround;
|
||||
NetworkManager owns Wi-Fi power saving for battery use.
|
||||
- `config/user/{common,laptop,desktop}/` owns selected active user dotfiles.
|
||||
Host-specific Hyprland and Noctalia variants are selected by host composition.
|
||||
- EnvyControl's generated NVIDIA blacklist and udev files are intentionally
|
||||
unmanaged so GPU modes can be switched outside of Decman.
|
||||
|
||||
Changing the debug policy does not uninstall debug packages already installed;
|
||||
remove those explicitly in a separate reviewed package change.
|
||||
|
||||
## Package concerns
|
||||
|
||||
| Scope | Concerns |
|
||||
| --- | --- |
|
||||
| Shared | core, wayland, fonts, development, productivity, media, research, network, services |
|
||||
| Laptop | hardware, legacy; hardware units |
|
||||
| Desktop | shared concerns now; add `packages/desktop/<concern>-{repo,aur}.txt` when hardware/software differs |
|
||||
|
||||
Every package must have a named purpose. Add a new concern when an existing one
|
||||
does not explain a package. System and user units use the same naming:
|
||||
`manifests/common/<concern>-{system,user}.txt` or
|
||||
`manifests/laptop/<concern>-system.txt`.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
cd ~/system-config
|
||||
./scripts/verify.py
|
||||
sudo decman --source source.py --dry-run --no-hooks
|
||||
sudo decman --source source.py --no-hooks
|
||||
```
|
||||
|
||||
`verify.py` proves that every currently explicit package appears exactly once
|
||||
in the active laptop profile. The ignored dependency lists prevent Decman's
|
||||
orphan cleanup from removing dependencies during adoption.
|
||||
|
||||
After intentional package changes, regenerate and review concern lists:
|
||||
|
||||
```bash
|
||||
./scripts/split_packages.py
|
||||
./scripts/refresh_orphan_guards.py
|
||||
./scripts/verify.py
|
||||
git diff
|
||||
```
|
||||
@@ -0,0 +1,6 @@
|
||||
# Written by systemd-localed(8) or systemd-firstboot(1), read by systemd-localed
|
||||
# and systemd-vconsole-setup(8). Use localectl(1) to update this file.
|
||||
KEYMAP=us
|
||||
XKBLAYOUT=us
|
||||
XKBMODEL=variant
|
||||
XKBVARIANT=altgr-intl
|
||||
@@ -0,0 +1,9 @@
|
||||
# Written by systemd-localed(8), read by systemd-localed and Xorg. It's
|
||||
# probably wise not to edit this file manually. Use localectl(1) to
|
||||
# update this file.
|
||||
Section "InputClass"
|
||||
Identifier "system-keyboard"
|
||||
MatchIsKeyboard "on"
|
||||
Option "XkbLayout" "us"
|
||||
Option "XkbVariant" "intl"
|
||||
EndSection
|
||||
@@ -0,0 +1,20 @@
|
||||
[ids]
|
||||
|
||||
*
|
||||
|
||||
[main]
|
||||
capslock = layer(capslayer)
|
||||
' = G-'
|
||||
|
||||
|
||||
[capslayer]
|
||||
j = down
|
||||
h = left
|
||||
k = up
|
||||
l = right
|
||||
|
||||
a = G-q
|
||||
o = G-p
|
||||
u = G-y
|
||||
s = G-s
|
||||
e = G-5
|
||||
@@ -0,0 +1,3 @@
|
||||
# This is the fallback locale configuration provided by systemd.
|
||||
|
||||
LANG="en_US.UTF-8"
|
||||
@@ -0,0 +1 @@
|
||||
en_US.UTF-8 UTF-8
|
||||
@@ -0,0 +1,168 @@
|
||||
#!/hint/bash
|
||||
# shellcheck disable=2034
|
||||
|
||||
#
|
||||
# /etc/makepkg.conf
|
||||
#
|
||||
|
||||
#########################################################################
|
||||
# SOURCE ACQUISITION
|
||||
#########################################################################
|
||||
#
|
||||
#-- The download utilities that makepkg should use to acquire sources
|
||||
# Format: 'protocol::agent'
|
||||
DLAGENTS=('file::/usr/bin/curl -qgC - -o %o %u'
|
||||
'ftp::/usr/bin/curl -qgfC - --ftp-pasv --retry 3 --retry-delay 3 -o %o %u'
|
||||
'http::/usr/bin/curl -qgb "" -fLC - --retry 3 --retry-delay 3 -o %o %u'
|
||||
'https::/usr/bin/curl -qgb "" -fLC - --retry 3 --retry-delay 3 -o %o %u'
|
||||
'rsync::/usr/bin/rsync --no-motd -z %u %o'
|
||||
'scp::/usr/bin/scp -C %u %o')
|
||||
|
||||
# Other common tools:
|
||||
# /usr/bin/snarf
|
||||
# /usr/bin/lftpget -c
|
||||
# /usr/bin/wget
|
||||
|
||||
#-- The package required by makepkg to download VCS sources
|
||||
# Format: 'protocol::package'
|
||||
VCSCLIENTS=('bzr::breezy'
|
||||
'fossil::fossil'
|
||||
'git::git'
|
||||
'hg::mercurial'
|
||||
'svn::subversion')
|
||||
|
||||
#########################################################################
|
||||
# ARCHITECTURE, COMPILE FLAGS
|
||||
#########################################################################
|
||||
#
|
||||
CARCH="x86_64"
|
||||
CHOST="x86_64-pc-linux-gnu"
|
||||
|
||||
#NPROC=2
|
||||
|
||||
#-- Compiler and Linker Flags
|
||||
#CPPFLAGS=""
|
||||
CFLAGS="-march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions \
|
||||
-Wp,-D_FORTIFY_SOURCE=3 -Wformat -Werror=format-security \
|
||||
-fstack-clash-protection -fcf-protection \
|
||||
-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"
|
||||
CXXFLAGS="$CFLAGS -Wp,-D_GLIBCXX_ASSERTIONS"
|
||||
LDFLAGS="-Wl,-O1 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now \
|
||||
-Wl,-z,pack-relative-relocs"
|
||||
LTOFLAGS="-flto=auto"
|
||||
#-- Make Flags: change this for DistCC/SMP systems
|
||||
#MAKEFLAGS="-j2"
|
||||
#-- Debugging flags
|
||||
DEBUG_CFLAGS="-g"
|
||||
DEBUG_CXXFLAGS="$DEBUG_CFLAGS"
|
||||
|
||||
#########################################################################
|
||||
# BUILD ENVIRONMENT
|
||||
#########################################################################
|
||||
#
|
||||
# Makepkg defaults: BUILDENV=(!distcc !color !ccache check !sign)
|
||||
# A negated environment option will do the opposite of the comments below.
|
||||
#
|
||||
#-- distcc: Use the Distributed C/C++/ObjC compiler
|
||||
#-- color: Colorize output messages
|
||||
#-- ccache: Use ccache to cache compilation
|
||||
#-- check: Run the check() function if present in the PKGBUILD
|
||||
#-- sign: Generate PGP signature file
|
||||
#
|
||||
BUILDENV=(!distcc color !ccache check !sign)
|
||||
#
|
||||
#-- If using DistCC, your MAKEFLAGS will also need modification. In addition,
|
||||
#-- specify a space-delimited list of hosts running in the DistCC cluster.
|
||||
#DISTCC_HOSTS=""
|
||||
#
|
||||
#-- Specify a directory for package building.
|
||||
#BUILDDIR=/tmp/makepkg
|
||||
|
||||
#########################################################################
|
||||
# GLOBAL PACKAGE OPTIONS
|
||||
# These are default values for the options=() settings
|
||||
#########################################################################
|
||||
#
|
||||
# Makepkg defaults:
|
||||
# OPTIONS=(!strip docs libtool staticlibs emptydirs !zipman !purge !debug !lto !autodeps)
|
||||
# A negated option will do the opposite of the comments below.
|
||||
#
|
||||
#-- strip: Strip symbols from binaries/libraries
|
||||
#-- docs: Save doc directories specified by DOC_DIRS
|
||||
#-- libtool: Leave libtool (.la) files in packages
|
||||
#-- staticlibs: Leave static library (.a) files in packages
|
||||
#-- emptydirs: Leave empty directories in packages
|
||||
#-- zipman: Compress manual (man and info) pages in MAN_DIRS with gzip
|
||||
#-- purge: Remove files specified by PURGE_TARGETS
|
||||
#-- debug: Add debugging flags as specified in DEBUG_* variables
|
||||
#-- lto: Add compile flags for building with link time optimization
|
||||
#-- autodeps: Automatically add depends/provides
|
||||
#
|
||||
OPTIONS=(strip docs !libtool !staticlibs emptydirs zipman purge !debug lto)
|
||||
|
||||
#-- File integrity checks to use. Valid: md5, sha1, sha224, sha256, sha384, sha512, b2
|
||||
INTEGRITY_CHECK=(sha256)
|
||||
#-- Options to be used when stripping binaries. See `man strip' for details.
|
||||
STRIP_BINARIES="--strip-all"
|
||||
#-- Options to be used when stripping shared libraries. See `man strip' for details.
|
||||
STRIP_SHARED="--strip-unneeded"
|
||||
#-- Options to be used when stripping static libraries. See `man strip' for details.
|
||||
STRIP_STATIC="--strip-debug"
|
||||
#-- Manual (man and info) directories to compress (if zipman is specified)
|
||||
MAN_DIRS=(usr{,/local}{,/share}/{man,info})
|
||||
#-- Doc directories to remove (if !docs is specified)
|
||||
DOC_DIRS=(usr/{,local/}{,share/}{doc,gtk-doc})
|
||||
#-- Files to be removed from all packages (if purge is specified)
|
||||
PURGE_TARGETS=(usr/{,share}/info/dir .packlist *.pod)
|
||||
#-- Directory to store source code in for debug packages
|
||||
DBGSRCDIR="/usr/src/debug"
|
||||
#-- Prefix and directories for library autodeps
|
||||
LIB_DIRS=('lib:usr/lib' 'lib32:usr/lib32')
|
||||
|
||||
#########################################################################
|
||||
# PACKAGE OUTPUT
|
||||
#########################################################################
|
||||
#
|
||||
# Default: put built package and cached source in build directory
|
||||
#
|
||||
#-- Destination: specify a fixed directory where all packages will be placed
|
||||
#PKGDEST=/home/packages
|
||||
#-- Source cache: specify a fixed directory where source files will be cached
|
||||
#SRCDEST=/home/sources
|
||||
#-- Source packages: specify a fixed directory where all src packages will be placed
|
||||
#SRCPKGDEST=/home/srcpackages
|
||||
#-- Log files: specify a fixed directory where all log files will be placed
|
||||
#LOGDEST=/home/makepkglogs
|
||||
#-- Packager: name/email of the person or organization building packages
|
||||
#PACKAGER="John Doe <john@doe.com>"
|
||||
#-- Specify a key to use for package signing
|
||||
#GPGKEY=""
|
||||
|
||||
#########################################################################
|
||||
# COMPRESSION DEFAULTS
|
||||
#########################################################################
|
||||
#
|
||||
COMPRESSGZ=(gzip -c -f -n)
|
||||
COMPRESSBZ2=(bzip2 -c -f)
|
||||
COMPRESSXZ=(xz -c -z -)
|
||||
COMPRESSZST=(zstd -c -T0 -)
|
||||
COMPRESSLRZ=(lrzip -q)
|
||||
COMPRESSLZO=(lzop -q)
|
||||
COMPRESSZ=(compress -c -f)
|
||||
COMPRESSLZ4=(lz4 -q)
|
||||
COMPRESSLZ=(lzip -c -f)
|
||||
|
||||
#########################################################################
|
||||
# EXTENSION DEFAULTS
|
||||
#########################################################################
|
||||
#
|
||||
PKGEXT='.pkg.tar.zst'
|
||||
SRCEXT='.src.tar.gz'
|
||||
|
||||
#########################################################################
|
||||
# OTHER
|
||||
#########################################################################
|
||||
#
|
||||
#-- Command used to run pacman as root, instead of trying sudo and su
|
||||
#PACMAN_AUTH=()
|
||||
# vim: set ft=sh ts=2 sw=2 et:
|
||||
@@ -0,0 +1,99 @@
|
||||
#
|
||||
# /etc/pacman.conf
|
||||
#
|
||||
# See the pacman.conf(5) manpage for option and repository directives
|
||||
|
||||
#
|
||||
# GENERAL OPTIONS
|
||||
#
|
||||
[options]
|
||||
# The following paths are commented out with their default values listed.
|
||||
# If you wish to use different paths, uncomment and update the paths.
|
||||
#RootDir = /
|
||||
#DBPath = /var/lib/pacman/
|
||||
#CacheDir = /var/cache/pacman/pkg/
|
||||
#LogFile = /var/log/pacman.log
|
||||
#GPGDir = /etc/pacman.d/gnupg/
|
||||
#HookDir = /etc/pacman.d/hooks/
|
||||
HoldPkg = pacman glibc
|
||||
#XferCommand = /usr/bin/curl -L -C - -f -o %o %u
|
||||
#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u
|
||||
#CleanMethod = KeepInstalled
|
||||
Architecture = auto
|
||||
|
||||
# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup
|
||||
#IgnorePkg =
|
||||
#IgnoreGroup =
|
||||
|
||||
#NoUpgrade =
|
||||
#NoExtract =
|
||||
|
||||
# Misc options
|
||||
#UseSyslog
|
||||
#Color
|
||||
#NoProgressBar
|
||||
CheckSpace
|
||||
#VerbosePkgLists
|
||||
#ParallelDownloads = 5
|
||||
DownloadUser = alpm
|
||||
#DisableSandbox
|
||||
|
||||
# By default, pacman accepts packages signed by keys that its local keyring
|
||||
# trusts (see pacman-key and its man page), as well as unsigned packages.
|
||||
SigLevel = Required DatabaseOptional
|
||||
LocalFileSigLevel = Optional
|
||||
#RemoteFileSigLevel = Required
|
||||
|
||||
# NOTE: You must run `pacman-key --init` before first using pacman; the local
|
||||
# keyring can then be populated with the keys of all official Arch Linux
|
||||
# packagers with `pacman-key --populate archlinux`.
|
||||
|
||||
#
|
||||
# REPOSITORIES
|
||||
# - can be defined here or included from another file
|
||||
# - pacman will search repositories in the order defined here
|
||||
# - local/custom mirrors can be added here or in separate files
|
||||
# - repositories listed first will take precedence when packages
|
||||
# have identical names, regardless of version number
|
||||
# - URLs will have $repo replaced by the name of the current repo
|
||||
# - URLs will have $arch replaced by the name of the architecture
|
||||
#
|
||||
# Repository entries are of the format:
|
||||
# [repo-name]
|
||||
# Server = ServerName
|
||||
# Include = IncludePath
|
||||
#
|
||||
# The header [repo-name] is crucial - it must be present and
|
||||
# uncommented to enable the repo.
|
||||
#
|
||||
|
||||
# The testing repositories are disabled by default. To enable, uncomment the
|
||||
# repo name header and Include lines. You can add preferred servers immediately
|
||||
# after the header, and they will be used before the default mirrors.
|
||||
|
||||
#[core-testing]
|
||||
#Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
[core]
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
#[extra-testing]
|
||||
#Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
[extra]
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
# If you want to run 32 bit applications on your x86_64 system,
|
||||
# enable the multilib repositories as required here.
|
||||
|
||||
#[multilib-testing]
|
||||
#Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
[multilib]
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
# An example of a custom package repository. See the pacman manpage for
|
||||
# tips on creating your own repositories.
|
||||
#[custom]
|
||||
#SigLevel = Optional TrustAll
|
||||
#Server = file:///home/custompkgs
|
||||
@@ -0,0 +1,81 @@
|
||||
# vim:set ft=sh
|
||||
# MODULES
|
||||
# The following modules are loaded before any boot hooks are
|
||||
# run. Advanced users may wish to specify all system modules
|
||||
# in this array. For instance:
|
||||
# MODULES=(usbhid xhci_hcd)
|
||||
MODULES=()
|
||||
|
||||
# BINARIES
|
||||
# This setting includes any additional binaries a given user may
|
||||
# wish into the CPIO image. This is run last, so it may be used to
|
||||
# override the actual binaries included by a given hook
|
||||
# BINARIES are dependency parsed, so you may safely ignore libraries
|
||||
BINARIES=()
|
||||
|
||||
# FILES
|
||||
# This setting is similar to BINARIES above, however, files are added
|
||||
# as-is and are not parsed in any way. This is useful for config files.
|
||||
FILES=()
|
||||
|
||||
# HOOKS
|
||||
# This is the most important setting in this file. The HOOKS control the
|
||||
# modules and scripts added to the image, and what happens at boot time.
|
||||
# Order is important, and it is recommended that you do not change the
|
||||
# order in which HOOKS are added. Run 'mkinitcpio -H <hook name>' for
|
||||
# help on a given hook.
|
||||
# 'base' is _required_ unless you know precisely what you are doing.
|
||||
# 'udev' is _required_ in order to automatically load modules
|
||||
# 'filesystems' is _required_ unless you specify your fs modules in MODULES
|
||||
# Examples:
|
||||
## This setup specifies all modules in the MODULES setting above.
|
||||
## No RAID, lvm2, or encrypted root is needed.
|
||||
# HOOKS=(base)
|
||||
#
|
||||
## This setup will autodetect all modules for your system and should
|
||||
## work as a sane default
|
||||
# HOOKS=(base udev autodetect modconf block filesystems fsck)
|
||||
#
|
||||
## This setup will generate a 'full' image which supports most systems.
|
||||
## No autodetection is done.
|
||||
# HOOKS=(base udev modconf block filesystems fsck)
|
||||
#
|
||||
## This setup assembles a mdadm array with an encrypted root file system.
|
||||
## Note: See 'mkinitcpio -H mdadm_udev' for more information on RAID devices.
|
||||
# HOOKS=(base udev modconf keyboard keymap consolefont block mdadm_udev encrypt filesystems fsck)
|
||||
#
|
||||
## This setup loads an lvm2 volume group.
|
||||
# HOOKS=(base udev modconf block lvm2 filesystems fsck)
|
||||
#
|
||||
## This will create a systemd based initramfs which loads an encrypted root filesystem.
|
||||
# HOOKS=(base systemd autodetect modconf kms keyboard sd-vconsole sd-encrypt block filesystems fsck)
|
||||
#
|
||||
## NOTE: If you have /usr on a separate partition, you MUST include the
|
||||
# usr and fsck hooks.
|
||||
HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt filesystems resume fsck)
|
||||
|
||||
# COMPRESSION
|
||||
# Use this to compress the initramfs image. By default, zstd compression
|
||||
# is used for Linux ≥ 5.9 and gzip compression is used for Linux < 5.9.
|
||||
# Use 'cat' to create an uncompressed image.
|
||||
#COMPRESSION="zstd"
|
||||
#COMPRESSION="gzip"
|
||||
#COMPRESSION="bzip2"
|
||||
#COMPRESSION="lzma"
|
||||
#COMPRESSION="xz"
|
||||
#COMPRESSION="lzop"
|
||||
#COMPRESSION="lz4"
|
||||
|
||||
# COMPRESSION_OPTIONS
|
||||
# Additional options for the compressor
|
||||
#COMPRESSION_OPTIONS=()
|
||||
|
||||
# MODULES_DECOMPRESS
|
||||
# Decompress loadable kernel modules and their firmware during initramfs
|
||||
# creation. Switch (yes/no).
|
||||
# Enable to allow further decreasing image size when using high compression
|
||||
# (e.g. xz -9e or zstd --long --ultra -22) at the expense of increased RAM usage
|
||||
# at early boot.
|
||||
# Note that any compressed files will be placed in the uncompressed early CPIO
|
||||
# to avoid double compression.
|
||||
#MODULES_DECOMPRESS="no"
|
||||
@@ -0,0 +1,3 @@
|
||||
# Keep Wi-Fi 6 disabled for this laptop's known stability workaround.
|
||||
# NetworkManager owns association-level Wi-Fi power saving.
|
||||
options iwlwifi disable_11ax=1
|
||||
@@ -0,0 +1,11 @@
|
||||
DEVICES_TO_DISABLE_ON_STARTUP="bluetooth"
|
||||
DEVICES_TO_DISABLE_ON_BAT_NOT_IN_USE="bluetooth"
|
||||
|
||||
CPU_ENERGY_PERF_POLICY_ON_AC=balance
|
||||
CPU_ENERGY_PERF_POLICY_ON_BAT=power
|
||||
|
||||
CPU_BOOST_ON_AC=1
|
||||
CPU_BOOST_ON_BAT=0
|
||||
|
||||
CPU_MAX_PERF_ON_AC=100
|
||||
CPU_MAX_PERF_ON_BAT=70
|
||||
@@ -0,0 +1,732 @@
|
||||
#
|
||||
# refind.conf
|
||||
# Configuration file for the rEFInd boot menu
|
||||
#
|
||||
|
||||
# Timeout in seconds for the main menu screen. Setting the timeout to 0
|
||||
# disables automatic booting (i.e., no timeout). Setting it to -1 causes
|
||||
# an immediate boot to the default OS *UNLESS* a keypress is in the buffer
|
||||
# when rEFInd launches, in which case that keypress is interpreted as a
|
||||
# shortcut key. If no matching shortcut is found, rEFInd displays its
|
||||
# menu with no timeout.
|
||||
#
|
||||
timeout 20
|
||||
|
||||
# Set the logging level. When set to 0, rEFInd does not log its actions.
|
||||
# When set to 1 or above, rEFInd creates a file called refind.log in
|
||||
# its home directory on the ESP and records information about what it's
|
||||
# doing. Higher values record more information, up to a maximum of 4.
|
||||
# This token should be left at the default of 0 except when debugging
|
||||
# problems.
|
||||
# Default value is 0
|
||||
#
|
||||
#log_level 1
|
||||
|
||||
# Normally, when the timeout period has passed, rEFInd boots the
|
||||
# default_selection. If the following option is uncommented, though,
|
||||
# rEFInd will instead attempt to shut down the computer.
|
||||
# CAUTION: MANY COMPUTERS WILL INSTEAD HANG OR REBOOT! Macs and more
|
||||
# recent UEFI-based PCs are most likely to work with this feature.
|
||||
# Default value is true
|
||||
#
|
||||
#shutdown_after_timeout
|
||||
|
||||
# Whether to store rEFInd's rEFInd-specific variables in NVRAM (1, true,
|
||||
# or on) or in files in the "vars" subdirectory of rEFInd's directory on
|
||||
# disk (0, false, or off). Using NVRAM works well with most computers;
|
||||
# however, it increases wear on the motherboard's NVRAM, and if the EFI
|
||||
# is buggy or the NVRAM is old and worn out, it may not work at all.
|
||||
# Storing variables on disk is a viable alternative in such cases, or
|
||||
# if you want to minimize wear and tear on the NVRAM; however, it won't
|
||||
# work if rEFInd is stored on a filesystem that's read-only to the EFI
|
||||
# (such as an HFS+ volume), and it increases the risk of filesystem
|
||||
# damage. Note that this option affects ONLY rEFInd's own variables,
|
||||
# such as the PreviousBoot, HiddenTags, HiddenTools, and HiddenLegacy
|
||||
# variables. It does NOT affect Secure Boot or other non-rEFInd
|
||||
# variables.
|
||||
# Default is true
|
||||
#
|
||||
use_nvram false
|
||||
|
||||
# Screen saver timeout; the screen blanks after the specified number of
|
||||
# seconds with no keyboard input. The screen returns after most keypresses
|
||||
# (unfortunately, not including modifier keys such as Shift, Control, Alt,
|
||||
# or Option). Setting a value of "-1" causes rEFInd to start up with its
|
||||
# screen saver active. The default is 0, which disables the screen saver.
|
||||
#
|
||||
#screensaver 300
|
||||
|
||||
# Hide user interface elements for personal preference or to increase
|
||||
# security:
|
||||
# banner - the rEFInd title banner (built-in or loaded via "banner")
|
||||
# label - boot option text label in the menu
|
||||
# singleuser - remove the submenu options to boot macOS in single-user
|
||||
# or verbose modes; affects ONLY macOS
|
||||
# safemode - remove the submenu option to boot macOS in "safe mode"
|
||||
# hwtest - the submenu option to run Apple's hardware test
|
||||
# arrows - scroll arrows on the OS selection tag line
|
||||
# hints - brief command summary in the menu
|
||||
# editor - the options editor (+, F2, or Insert on boot options menu)
|
||||
# badges - device-type badges for boot options
|
||||
# all - all of the above
|
||||
# Default is none of these (all elements active)
|
||||
#
|
||||
#hideui singleuser
|
||||
#hideui all
|
||||
|
||||
# Set the name of a subdirectory in which icons are stored. Icons must
|
||||
# have the same names they have in the standard directory. The directory
|
||||
# name is specified relative to the main rEFInd binary's directory. If
|
||||
# an icon can't be found in the specified directory, an attempt is made
|
||||
# to load it from the default directory; thus, you can replace just some
|
||||
# icons in your own directory and rely on the default for others.
|
||||
# Icon files may be in any supported format -- ICNS (*.icns), BMP (*.bmp),
|
||||
# PNG (*.png), or JPEG (*.jpg or *.jpeg); however, rEFInd's BMP and JPEG
|
||||
# implementations do not support transparency, which is highly desirable
|
||||
# in icons.
|
||||
# Default is "icons".
|
||||
#
|
||||
#icons_dir myicons
|
||||
#icons_dir icons/snowy
|
||||
|
||||
# Use a custom title banner instead of the rEFInd icon and name. The file
|
||||
# path is relative to the directory where refind.efi is located. The color
|
||||
# in the top left corner of the image is used as the background color
|
||||
# for the menu screens. Currently uncompressed BMP images with color
|
||||
# depths of 24, 8, 4 or 1 bits are supported, as well as PNG and JPEG
|
||||
# images. (ICNS images can also be used, but ICNS has limitations that
|
||||
# make it a poor choice for this purpose.) PNG and JPEG support is
|
||||
# limited by the underlying libraries; some files, like progressive JPEGs,
|
||||
# will not work.
|
||||
#
|
||||
#banner hostname.bmp
|
||||
#banner mybanner.jpg
|
||||
#banner icons/snowy/banner-snowy.png
|
||||
|
||||
# Specify how to handle banners that aren't exactly the same as the screen
|
||||
# size:
|
||||
# noscale - Crop if too big, show with border if too small
|
||||
# fillscreen - Fill the screen
|
||||
# Default is noscale
|
||||
#
|
||||
#banner_scale fillscreen
|
||||
|
||||
# Icon sizes. All icons are square, so just one value is specified. The
|
||||
# big icons are used for OS selectors in the first row and the small
|
||||
# icons are used for tools on the second row. Drive-type badges are 1/4
|
||||
# the size of the big icons. Legal values are 32 and above. If the icon
|
||||
# files do not hold icons of the proper size, the icons are scaled to
|
||||
# the specified size. The default values are 48 and 128 for small and
|
||||
# big icons, respectively.
|
||||
#
|
||||
#small_icon_size 96
|
||||
#big_icon_size 256
|
||||
|
||||
# Custom images for the selection background. There is a big one (144 x 144)
|
||||
# for the OS icons, and a small one (64 x 64) for the function icons in the
|
||||
# second row. If only a small image is given, that one is also used for
|
||||
# the big icons by stretching it in the middle. If only a big one is given,
|
||||
# the built-in default will be used for the small icons. If an image other
|
||||
# than the optimal size is specified, it will be scaled in a way that may
|
||||
# be ugly.
|
||||
#
|
||||
# Like the banner option above, these options take a filename of an
|
||||
# uncompressed BMP, PNG, JPEG, or ICNS image file with a color depth of
|
||||
# 24, 8, 4, or 1 bits. The PNG or ICNS format is required if you need
|
||||
# transparency support (to let you "see through" to a full-screen banner).
|
||||
#
|
||||
#selection_big selection-big.bmp
|
||||
#selection_small selection-small.bmp
|
||||
|
||||
# Set the font to be used for all textual displays in graphics mode.
|
||||
# For best results, the font must be a PNG file with alpha channel
|
||||
# transparency. It must contain ASCII characters 32-126 (space through
|
||||
# tilde), inclusive, plus a glyph to be displayed in place of characters
|
||||
# outside of this range, for a total of 96 glyphs. Only monospaced fonts
|
||||
# are supported. Fonts may be of any size, although large fonts can
|
||||
# produce display irregularities.
|
||||
# The default is rEFInd's built-in font, Luxi Mono Regular 12 point.
|
||||
#
|
||||
#font myfont.png
|
||||
|
||||
# Use text mode only. When enabled, this option forces rEFInd into text mode.
|
||||
# Passing this option a "0" value causes graphics mode to be used. Pasing
|
||||
# it no value or any non-0 value causes text mode to be used.
|
||||
# Default is to use graphics mode.
|
||||
#
|
||||
#textonly
|
||||
|
||||
# Set the EFI text mode to be used for textual displays. This option
|
||||
# takes a single digit that refers to a mode number. Mode 0 is normally
|
||||
# 80x25, 1 is sometimes 80x50, and higher numbers are system-specific
|
||||
# modes. Mode 1024 is a special code that tells rEFInd to not set the
|
||||
# text mode; it uses whatever was in use when the program was launched.
|
||||
# If you specify an invalid mode, rEFInd pauses during boot to inform
|
||||
# you of valid modes.
|
||||
# CAUTION: On VirtualBox, and perhaps on some real computers, specifying
|
||||
# a text mode and uncommenting the "textonly" option while NOT specifying
|
||||
# a resolution can result in an unusable display in the booted OS.
|
||||
# Default is 1024 (no change)
|
||||
#
|
||||
#textmode 2
|
||||
|
||||
# Set the screen's video resolution. Pass this option one of the following:
|
||||
# * two integer values, corresponding to the X and Y resolutions
|
||||
# * one integer value, corresponding to a GOP (UEFI) video mode
|
||||
# * the string "max", which sets the maximum available resolution
|
||||
# Note that not all resolutions are supported. On UEFI systems, passing
|
||||
# an incorrect value results in a message being shown on the screen to
|
||||
# that effect, along with a list of supported modes. On EFI 1.x systems
|
||||
# (e.g., Macintoshes), setting an incorrect mode silently fails. On both
|
||||
# types of systems, setting an incorrect resolution results in the default
|
||||
# resolution being used. A resolution of 1024x768 usually works, but higher
|
||||
# values often don't.
|
||||
# Default is "0 0" (use the system default resolution, usually 800x600).
|
||||
#
|
||||
#resolution 1024 768
|
||||
#resolution 1440 900
|
||||
#resolution 3
|
||||
#resolution max
|
||||
|
||||
# Enable touch screen support. If active, this feature enables use of
|
||||
# touch screen controls (as on tablets). Note, however, that not all
|
||||
# tablets' EFIs provide the necessary underlying support, so this
|
||||
# feature may not work for you. If it does work, you should be able
|
||||
# to launch an OS or tool by touching it. In a submenu, touching
|
||||
# anywhere launches the currently-selection item; there is, at present,
|
||||
# no way to select a specific submenu item. This feature is mutually
|
||||
# exclusive with the enable_mouse feature. If both are uncommented,
|
||||
# the one read most recently takes precedence.
|
||||
#
|
||||
#enable_touch
|
||||
|
||||
# Enable mouse support. If active, this feature enables use of the
|
||||
# computer's mouse. Note, however, that not all computers' EFIs
|
||||
# provide the necessary underlying support, so this feature may not
|
||||
# work for you. If it does work, you should be able to launch an
|
||||
# OS or tool by clicking it with the mouse pointer. This feature
|
||||
# is mutually exclusive with the enable_touch feature. If both
|
||||
# are uncommented, the one read most recently takes precedence.
|
||||
#
|
||||
#enable_mouse
|
||||
|
||||
# Size of the mouse pointer, in pixels, per side.
|
||||
# Default is 16
|
||||
#
|
||||
#mouse_size 16
|
||||
|
||||
# Speed of mouse tracking. Higher numbers equate to faster
|
||||
# mouse movement. This option requires that enable_mouse be
|
||||
# uncommented.
|
||||
# Legal values are between 1 and 32. Default is 4.
|
||||
#
|
||||
#mouse_speed 4
|
||||
|
||||
# Launch specified OSes in graphics mode. By default, rEFInd switches
|
||||
# to text mode and displays basic pre-launch information when launching
|
||||
# all OSes except macOS. Using graphics mode can produce a more seamless
|
||||
# transition, but displays no information, which can make matters
|
||||
# difficult if you must debug a problem. Also, on at least one known
|
||||
# computer, using graphics mode prevents a crash when using the Linux
|
||||
# kernel's EFI stub loader. You can specify an empty list to boot all
|
||||
# OSes in text mode.
|
||||
# Valid options:
|
||||
# osx - macOS
|
||||
# linux - A Linux kernel with EFI stub loader
|
||||
# elilo - The ELILO boot loader
|
||||
# grub - The GRUB (Legacy or 2) boot loader
|
||||
# windows - Microsoft Windows
|
||||
# Default value: osx
|
||||
#
|
||||
#use_graphics_for osx,linux
|
||||
|
||||
# Which non-bootloader tools to show on the tools line, and in what
|
||||
# order to display them:
|
||||
# shell - the EFI shell (requires external program; see rEFInd
|
||||
# documentation for details)
|
||||
# memtest - the memtest86 program, in EFI/tools, EFI/memtest86,
|
||||
# EFI/memtest, EFI/tools/memtest86, or EFI/tools/memtest
|
||||
# gptsync - the (dangerous) gptsync.efi utility (requires external
|
||||
# program; see rEFInd documentation for details)
|
||||
# gdisk - the gdisk partitioning program
|
||||
# apple_recovery - boots the Apple Recovery HD partition, if present
|
||||
# windows_recovery - boots an OEM Windows recovery tool, if present
|
||||
# (see also the windows_recovery_files option)
|
||||
# mok_tool - makes available the Machine Owner Key (MOK) maintenance
|
||||
# tool, MokManager.efi, used on Secure Boot systems
|
||||
# csr_rotate - adjusts Apple System Integrity Protection (SIP)
|
||||
# policy. Requires "csr_values" to be set.
|
||||
# install - an option to install rEFInd from the current location
|
||||
# to another ESP
|
||||
# bootorder - adjust the EFI's (NOT rEFInd's) boot order
|
||||
# about - an "about this program" option
|
||||
# hidden_tags - manage hidden tags
|
||||
# exit - a tag to exit from rEFInd
|
||||
# shutdown - shuts down the computer (a bug causes this to reboot
|
||||
# many UEFI systems)
|
||||
# reboot - a tag to reboot the computer
|
||||
# firmware - a tag to reboot the computer into the firmware's
|
||||
# user interface (ignored on older computers)
|
||||
# fwupdate - a tag to update the firmware; launches the fwupx64.efi
|
||||
# (or similar) program
|
||||
# netboot - launch the ipxe.efi tool for network (PXE) booting
|
||||
# Default is shell,memtest,gdisk,apple_recovery,windows_recovery,mok_tool,about,hidden_tags,shutdown,reboot,firmware,fwupdate
|
||||
# To completely disable scanning for all tools, provide a showtools line
|
||||
# with no options.
|
||||
#
|
||||
#showtools shell, bootorder, gdisk, memtest, mok_tool, apple_recovery, windows_recovery, about, hidden_tags, reboot, exit, firmware, fwupdate
|
||||
|
||||
# Tool binaries to be excluded from the tools line, even if the
|
||||
# general class is specified in showtools. This enables trimming an
|
||||
# overabundance of tools, as when you see multiple mok_tool entries
|
||||
# after installing multiple Linux distributions.
|
||||
# Just as with dont_scan_files, you can specify a filename alone, a
|
||||
# full pathname, or a volume identifier (filesystem label, partition
|
||||
# name, or partition GUID) and a full pathname.
|
||||
# Default is an empty list (nothing is excluded)
|
||||
#
|
||||
#dont_scan_tools ESP2:/EFI/ubuntu/mmx64.efi,gptsync_x64.efi
|
||||
|
||||
# Boot loaders that can launch a Windows restore or emergency system.
|
||||
# These tend to be OEM-specific.
|
||||
# Default is LRS_ESP:/EFI/Microsoft/Boot/LrsBootmgr.efi
|
||||
#
|
||||
#windows_recovery_files LRS_ESP:/EFI/Microsoft/Boot/LrsBootmgr.efi
|
||||
|
||||
# Directories in which to search for EFI drivers. These drivers can
|
||||
# provide filesystem support, give access to hard disks on plug-in
|
||||
# controllers, etc. In most cases none are needed, but if you add
|
||||
# EFI drivers and you want rEFInd to automatically load them, you
|
||||
# should specify one or more paths here. rEFInd always scans the
|
||||
# "drivers" and "drivers_{arch}" subdirectories of its own installation
|
||||
# directory (where "{arch}" is your architecture code); this option
|
||||
# specifies ADDITIONAL directories to scan.
|
||||
# Default is to scan no additional directories for EFI drivers
|
||||
#
|
||||
#scan_driver_dirs EFI/tools/drivers,drivers
|
||||
|
||||
# Which types of boot loaders to search, and in what order to display them:
|
||||
# internal - internal EFI disk-based boot loaders
|
||||
# external - external EFI disk-based boot loaders
|
||||
# optical - EFI optical discs (CD, DVD, etc.)
|
||||
# netboot - EFI network (PXE) boot options
|
||||
# hdbios - BIOS disk-based boot loaders
|
||||
# biosexternal - BIOS external boot loaders (USB, eSATA, etc.)
|
||||
# cd - BIOS optical-disc boot loaders
|
||||
# manual - use stanzas later in this configuration file
|
||||
# firmware - boot EFI programs set in the firmware's NVRAM
|
||||
# Note that the legacy BIOS options require firmware support, which is
|
||||
# not present on all computers.
|
||||
# The netboot option is experimental and relies on the ipxe.efi and
|
||||
# ipxe_discover.efi program files.
|
||||
# On UEFI PCs, default is internal,external,optical,manual
|
||||
# On Macs, default is internal,hdbios,external,biosexternal,optical,cd,manual
|
||||
#
|
||||
#scanfor internal,external,optical,manual,firmware
|
||||
|
||||
# By default, rEFInd relies on the UEFI firmware to detect BIOS-mode boot
|
||||
# devices. This sometimes doesn't detect all the available devices, though.
|
||||
# For these cases, uefi_deep_legacy_scan results in a forced scan and
|
||||
# modification of NVRAM variables on each boot. Adding "0", "off", or
|
||||
# "false" resets to the default value. This token has no effect on Macs or
|
||||
# when no BIOS-mode options are set via scanfor.
|
||||
# Default is unset (or "uefi_deep_legacy_scan false")
|
||||
#
|
||||
#uefi_deep_legacy_scan
|
||||
|
||||
# Delay for the specified number of seconds before scanning disks.
|
||||
# This can help some users who find that some of their disks
|
||||
# (usually external or optical discs) aren't detected initially,
|
||||
# but are detected after pressing Esc.
|
||||
# The default is 0.
|
||||
#
|
||||
#scan_delay 5
|
||||
|
||||
# When scanning volumes for EFI boot loaders, rEFInd always looks for
|
||||
# macOS's and Microsoft Windows' boot loaders in their normal locations,
|
||||
# and scans the root directory and every subdirectory of the /EFI directory
|
||||
# for additional boot loaders, but it doesn't recurse into these directories.
|
||||
# The also_scan_dirs token adds more directories to the scan list.
|
||||
# Directories are specified relative to the volume's root directory. This
|
||||
# option applies to ALL the volumes that rEFInd scans UNLESS you include
|
||||
# a volume name and colon before the directory name, as in "myvol:/somedir"
|
||||
# to scan the somedir directory only on the filesystem named myvol. If a
|
||||
# specified directory doesn't exist, it's ignored (no error condition
|
||||
# results). The "+" symbol denotes appending to the list of scanned
|
||||
# directories rather than overwriting that list.
|
||||
# The default is to scan the "boot" and "@/boot" directories in addition
|
||||
# to various hard-coded directories.
|
||||
#
|
||||
#also_scan_dirs boot,ESP2:EFI/linux/kernels
|
||||
#also_scan_dirs boot,@/boot
|
||||
#also_scan_dirs +,@/kernels
|
||||
|
||||
# Partitions (or whole disks, for legacy-mode boots) to omit from scans.
|
||||
# For EFI-mode scans, you normally specify a volume by its label, which you
|
||||
# can obtain in an EFI shell by typing "vol", from Linux by typing
|
||||
# "blkid /dev/{devicename}", or by examining the disk's label in various
|
||||
# OSes' file browsers. It's also possible to identify a partition by its
|
||||
# unique GUID (aka its "PARTUUID" in Linux parlance). (Note that this is
|
||||
# NOT the partition TYPE CODE GUID.) This identifier can be obtained via
|
||||
# "blkid" in Linux or "diskutil info {partition-id}" in macOS.
|
||||
# For legacy-mode scans, you can specify any subset of the boot loader
|
||||
# description shown when you highlight the option in rEFInd.
|
||||
# The default is "LRS_ESP".
|
||||
#
|
||||
#dont_scan_volumes "Recovery HD"
|
||||
|
||||
# Directories that should NOT be scanned for boot loaders. By default,
|
||||
# rEFInd doesn't scan its own directory, the EFI/tools directory, the
|
||||
# EFI/memtest directory, the EFI/memtest86 directory, or the
|
||||
# com.apple.recovery.boot directory. Using the dont_scan_dirs option
|
||||
# enables you to "blacklist" other directories; but be sure to use "+"
|
||||
# as the first element if you want to continue blacklisting existing
|
||||
# directories. You might use this token to keep EFI/boot/bootx64.efi out
|
||||
# of the menu if that's a duplicate of another boot loader or to exclude
|
||||
# a directory that holds drivers or non-bootloader utilities provided by
|
||||
# a hardware manufacturer. If a directory is listed both here and in
|
||||
# also_scan_dirs, dont_scan_dirs takes precedence. Note that this
|
||||
# blacklist applies to ALL the filesystems that rEFInd scans, not just
|
||||
# the ESP, unless you precede the directory name by a filesystem name or
|
||||
# partition unique GUID, as in "myvol:EFI/somedir" to exclude EFI/somedir
|
||||
# from the scan on the myvol volume but not on other volumes.
|
||||
#
|
||||
#dont_scan_dirs ESP:/EFI/boot,EFI/Dell,EFI/memtest86
|
||||
|
||||
# Files that should NOT be included as EFI boot loaders (on the
|
||||
# first line of the display). If you're using a boot loader that
|
||||
# relies on support programs or drivers that are installed alongside
|
||||
# the main binary or if you want to "blacklist" certain loaders by
|
||||
# name rather than location, use this option. Note that this will
|
||||
# NOT prevent certain binaries from showing up in the second-row
|
||||
# set of tools. Most notably, various Secure Boot and recovery
|
||||
# tools are present in this list, but may appear as second-row
|
||||
# items.
|
||||
# The file may be specified as a bare name (e.g., "notme.efi"), as
|
||||
# a complete pathname (e.g., "/EFI/somedir/notme.efi"), or as a
|
||||
# complete pathname with volume (e.g., "SOMEDISK:/EFI/somedir/notme.efi"
|
||||
# or 2C17D5ED-850D-4F76-BA31-47A561740082:/EFI/somedir/notme.efi").
|
||||
# OS tags hidden via the Delete or '-' key in the rEFInd menu are
|
||||
# added to this list, but stored in NVRAM.
|
||||
# The default is shim.efi,shim-fedora.efi,shimx64.efi,PreLoader.efi,
|
||||
# TextMode.efi,ebounce.efi,GraphicsConsole.efi,MokManager.efi,HashTool.efi,
|
||||
# HashTool-signed.efi,bootmgr.efi,fb{arch}.efi
|
||||
# (where "{arch}" is the architecture code, like "x64").
|
||||
# If you want to keep these defaults but add to them, be sure to
|
||||
# specify "+" as the first item in the new list; if you don't, then
|
||||
# items from the default list are likely to appear.
|
||||
#
|
||||
#dont_scan_files shim.efi,MokManager.efi
|
||||
|
||||
# EFI NVRAM Boot#### variables that should NOT be presented as loaders
|
||||
# when "firmware" is an option to "scanfor". The comma-separated list
|
||||
# presented here contains strings that are matched against the
|
||||
# description field -- if a value here is a case-insensitive substring
|
||||
# of the boot option description, then it will be excluded from the
|
||||
# boot list. To specify a string that includes a space, enclose it
|
||||
# in quotes. Specifying "shell" will counteract the automatic
|
||||
# inclusion of built-in EFI shells.
|
||||
#
|
||||
#dont_scan_firmware HARDDISK,shell,"Removable Device"
|
||||
|
||||
# Scan for Linux kernels that lack a ".efi" filename extension. This is
|
||||
# useful for better integration with Linux distributions that provide
|
||||
# kernels with EFI stub loaders but that don't give those kernels filenames
|
||||
# that end in ".efi", particularly if the kernels are stored on a
|
||||
# filesystem that the EFI can read. When set to "1", "true", or "on", this
|
||||
# option causes all files in scanned directories with names that begin with
|
||||
# "vmlinuz", "bzImage", or "kernel" to be included as loaders, even if they
|
||||
# lack ".efi" extensions. Passing this option a "0", "false", or "off" value
|
||||
# causes kernels without ".efi" extensions to NOT be scanned.
|
||||
# Default is "true" -- to scan for kernels without ".efi" extensions.
|
||||
#
|
||||
#scan_all_linux_kernels false
|
||||
|
||||
# Support loaders that have been compressed with gzip.
|
||||
# On x86 and x86-64 platforms, Linux kernels are self-decompressing.
|
||||
# On ARM64, Linux kernel files are typically compressed with gzip,
|
||||
# including the EFI stub loader. This makes them unloadable in rEFInd
|
||||
# unless rEFInd itself uncompresses them. This option enables rEFInd
|
||||
# to do this. This feature is unnecessary on x86 and x86-64 systems.
|
||||
# Default is "false" on x86 and x86-64; "true" on ARM64.
|
||||
#
|
||||
#support_gzipped_loaders true
|
||||
|
||||
# Combine all Linux kernels in a given directory into a single entry.
|
||||
# When so set, the kernel with the most recent time stamp will be launched
|
||||
# by default, and its filename will appear in the entry's description.
|
||||
# To launch other kernels, the user must press F2 or Insert; alternate
|
||||
# kernels then appear as options on the sub-menu.
|
||||
# Default is "true" -- kernels are "folded" into a single menu entry.
|
||||
#
|
||||
#fold_linux_kernels false
|
||||
|
||||
# Comma-delimited list of strings to treat as if they were numbers for the
|
||||
# purpose of kernel version number detection. These strings are matched on a
|
||||
# first-found basis; that is, if you want to treat both "linux-lts" and
|
||||
# "linux" as version strings, they MUST be specified as "linux-lts,linux",
|
||||
# since if you specify it the other way, both vmlinuz-linux and
|
||||
# vmlinuz-linux-lts will return with "linux" as the "version string," which
|
||||
# is not what you'd want. Also, if the kernel or initrd file includes both a
|
||||
# specified string and digits, the "version string" includes both. For
|
||||
# instance, "vmlinuz-linux-4.8" would yield a version string of "linux-4.8".
|
||||
# This option is intended for Arch and other distributions that don't include
|
||||
# version numbers in their kernel filenames, but may provide other uniquely
|
||||
# identifying strings for multiple kernels. If this feature causes problems
|
||||
# (say, if your kernel filename includes "linux" but the initrd filename
|
||||
# doesn't), be sure this is set to an empty string
|
||||
# (extra_kernel_version_strings "") or comment out the option to disable it.
|
||||
# Default is no extra version strings
|
||||
#
|
||||
#extra_kernel_version_strings linux-lts,linux
|
||||
|
||||
# Write to systemd EFI variables (currently only LoaderDevicePartUUID) when
|
||||
# launching Linux via an EFI stub loader, ELILO, or GRUB. This variable,
|
||||
# when present, causes systemd to mount the ESP at /boot or /efi *IF* either
|
||||
# directory is empty and nothing else is mounted there.
|
||||
# Default is "false"
|
||||
#
|
||||
#write_systemd_vars true
|
||||
|
||||
# Symlinked loaders will be processed when this setting is set to true.
|
||||
# These are ignored by default as they may result in undesirable outcomes.
|
||||
# This token may, however, be useful on Linux setups that provide symbolic
|
||||
# links in scanned locations that point to kernels in unscanned locations,
|
||||
# such as some openSUSE installations.
|
||||
#
|
||||
#follow_symlinks true
|
||||
|
||||
# Set the maximum number of tags that can be displayed on the screen at
|
||||
# any time. If more loaders are discovered than this value, rEFInd shows
|
||||
# a subset in a scrolling list. If this value is set too high for the
|
||||
# screen to handle, it's reduced to the value that the screen can manage.
|
||||
# If this value is set to 0 (the default), it's adjusted to the number
|
||||
# that the screen can handle.
|
||||
#
|
||||
#max_tags 0
|
||||
|
||||
# Set the default menu selection. The available arguments match the
|
||||
# keyboard accelerators available within rEFInd. You may select the
|
||||
# default loader using:
|
||||
# - A digit between 1 and 9, in which case the Nth loader in the menu
|
||||
# will be the default.
|
||||
# - A "+" symbol at the start of the string, which refers to the most
|
||||
# recently booted loader.
|
||||
# - Any substring that corresponds to a portion of the loader's title
|
||||
# (usually the OS's name, boot loader's path, or a volume or
|
||||
# filesystem title).
|
||||
# You may also specify multiple selectors by separating them with commas
|
||||
# and enclosing the list in quotes. (The "+" option is only meaningful in
|
||||
# this context.)
|
||||
# If you follow the selector(s) with two times, in 24-hour format, the
|
||||
# default will apply only between those times. The times are in the
|
||||
# motherboard's time standard, whether that's UTC or local time, so if
|
||||
# you use UTC, you'll need to adjust this from local time manually.
|
||||
# Times may span midnight as in "23:30 00:30", which applies to 11:30 PM
|
||||
# to 12:30 AM. You may specify multiple default_selection lines, in which
|
||||
# case the last one to match takes precedence. Thus, you can set a main
|
||||
# option without a time followed by one or more that include times to
|
||||
# set different defaults for different times of day.
|
||||
# The default behavior is to boot the previously-booted OS.
|
||||
#
|
||||
#default_selection 1
|
||||
#default_selection Microsoft
|
||||
#default_selection "+,bzImage,vmlinuz"
|
||||
#default_selection Maintenance 23:30 2:00
|
||||
#default_selection "Maintenance,macOS" 1:00 2:30
|
||||
|
||||
# Enable VMX bit and lock the CPU MSR if unlocked.
|
||||
# On some Intel Apple computers, the firmware does not lock the MSR 0x3A.
|
||||
# The symptom on Windows is Hyper-V not working even if the CPU
|
||||
# meets the minimum requirements (HW assisted virtualization and SLAT)
|
||||
# DO NOT SET THIS EXCEPT ON INTEL CPUs THAT SUPPORT VMX! See
|
||||
# http://www.thomas-krenn.com/en/wiki/Activating_the_Intel_VT_Virtualization_Feature
|
||||
# for more on this subject.
|
||||
# The default is false: Don't try to enable and lock the MSR.
|
||||
#
|
||||
#enable_and_lock_vmx false
|
||||
|
||||
# Tell a Mac's EFI that macOS is about to be launched, even when it's not.
|
||||
# This option causes some Macs to initialize their hardware differently than
|
||||
# when a third-party OS is launched normally. In some cases (particularly on
|
||||
# Macs with multiple video cards), using this option can cause hardware to
|
||||
# work that would not otherwise work. On the other hand, using this option
|
||||
# when it is not necessary can cause hardware (such as keyboards and mice) to
|
||||
# become inaccessible. Therefore, you should not enable this option if your
|
||||
# non-Apple OSes work correctly; enable it only if you have problems with
|
||||
# some hardware devices. When needed, a value of "10.9" usually works, but
|
||||
# you can experiment with other values. This feature has no effect on
|
||||
# non-Apple computers.
|
||||
# The default is inactive (no macOS spoofing is done).
|
||||
#
|
||||
#spoof_osx_version 10.9
|
||||
|
||||
# Set the CSR values for Apple's System Integrity Protection (SIP) feature.
|
||||
# Values are two-byte (four-character) hexadecimal numbers. These values
|
||||
# define which specific security features are enabled. Below are the codes
|
||||
# for what the values mean. Add them up (in hexadecimal!) to set new values.
|
||||
# Apple's "csrutil enable" and "csrutil disable" commands set values of 10
|
||||
# and 877, respectively. (Prior to OS 11, 77 was used rather than 877; 877
|
||||
# is required for OS 11, and should work for OS X 10.x, too.)
|
||||
# CSR_ALLOW_UNTRUSTED_KEXTS 0x0001
|
||||
# CSR_ALLOW_UNRESTRICTED_FS 0x0002
|
||||
# CSR_ALLOW_TASK_FOR_PID 0x0004
|
||||
# CSR_ALLOW_KERNEL_DEBUGGER 0x0008
|
||||
# CSR_ALLOW_APPLE_INTERNAL 0x0010
|
||||
# CSR_ALLOW_UNRESTRICTED_DTRACE 0x0020
|
||||
# CSR_ALLOW_UNRESTRICTED_NVRAM 0x0040
|
||||
# CSR_ALLOW_DEVICE_CONFIGURATION 0x0080
|
||||
# CSR_ALLOW_ANY_RECOVERY_OS 0x0100
|
||||
# CSR_ALLOW_UNAPPROVED_KEXTS 0x0200
|
||||
# CSR_ALLOW_EXECUTABLE_POLICY_OVERRIDE 0x0400
|
||||
# CSR_ALLOW_UNAUTHENTICATED_ROOT 0x0800
|
||||
#csr_values 10,877
|
||||
|
||||
# Include a secondary configuration file within this one. This secondary
|
||||
# file is loaded as if its options appeared at the point of the "include"
|
||||
# token itself, so if you want to override a setting in the main file,
|
||||
# the secondary file must be referenced AFTER the setting you want to
|
||||
# override. Note that the secondary file may NOT load a tertiary file.
|
||||
#
|
||||
#include manual.conf
|
||||
|
||||
# Sample manual configuration stanzas. Each begins with the "menuentry"
|
||||
# keyword followed by a name that's to appear in the menu (use quotes
|
||||
# if you want the name to contain a space) and an open curly brace
|
||||
# ("{"). Each entry ends with a close curly brace ("}"). Common
|
||||
# keywords within each stanza include:
|
||||
#
|
||||
# volume - identifies the filesystem from which subsequent files
|
||||
# are loaded. You can specify the volume by filesystem
|
||||
# label, by partition label, or by partition GUID number
|
||||
# (but NOT yet by filesystem UUID number).
|
||||
# loader - identifies the boot loader file
|
||||
# initrd - Specifies an initial RAM disk file
|
||||
# icon - specifies a custom boot loader icon
|
||||
# ostype - OS type code to determine boot options available by
|
||||
# pressing Insert. Valid values are "MacOS", "Linux",
|
||||
# "Windows", and "XOM". Case-sensitive.
|
||||
# graphics - set to "on" to enable graphics-mode boot (useful
|
||||
# mainly for MacOS) or "off" for text-mode boot.
|
||||
# Default is auto-detected from loader filename.
|
||||
# options - sets options to be passed to the boot loader; use
|
||||
# quotes if more than one option should be passed or
|
||||
# if any options use characters that might be changed
|
||||
# by rEFInd parsing procedures (=, /, #, or tab).
|
||||
# disabled - use alone or set to "yes" to disable this entry.
|
||||
#
|
||||
# Note that you can use either DOS/Windows/EFI-style backslashes (\)
|
||||
# or Unix-style forward slashes (/) as directory separators. Either
|
||||
# way, all file references are on the ESP from which rEFInd was
|
||||
# launched.
|
||||
# Use of quotes around parameters causes them to be interpreted as
|
||||
# one keyword, and for parsing of special characters (spaces, =, /,
|
||||
# and #) to be disabled. This is useful mainly with the "options"
|
||||
# keyword. Use of quotes around parameters that specify filenames is
|
||||
# permissible, but you must then use backslashes instead of slashes,
|
||||
# except when you must pass a forward slash to the loader, as when
|
||||
# passing a root= option to a Linux kernel.
|
||||
|
||||
# Below are several sample boot stanzas. All are disabled by default.
|
||||
# Find one similar to what you need, copy it, remove the "disabled" line,
|
||||
# and adjust the entries to suit your needs.
|
||||
|
||||
# A sample entry for a Linux 3.13 kernel with EFI boot stub support
|
||||
# on a partition with a GUID of 904404F8-B481-440C-A1E3-11A5A954E601.
|
||||
# This entry includes Linux-specific boot options and specification
|
||||
# of an initial RAM disk. Note uses of Linux-style forward slashes.
|
||||
# Also note that a leading slash is optional in file specifications.
|
||||
menuentry Linux {
|
||||
icon EFI/refind/icons/os_linux.png
|
||||
volume 904404F8-B481-440C-A1E3-11A5A954E601
|
||||
loader bzImage-3.3.0-rc7
|
||||
initrd initrd-3.3.0.img
|
||||
options "ro root=UUID=5f96cafa-e0a7-4057-b18f-fa709db5b837"
|
||||
disabled
|
||||
}
|
||||
|
||||
# Below is a more complex Linux example, specifically for Arch Linux.
|
||||
# This example MUST be modified for your specific installation; if nothing
|
||||
# else, the PARTUUID code must be changed for your disk. Because Arch Linux
|
||||
# does not include version numbers in its kernel and initrd filenames, you
|
||||
# may need to use manual boot stanzas when using fallback initrds or
|
||||
# multiple kernels with Arch. This example is modified from one in the Arch
|
||||
# wiki page on rEFInd (https://wiki.archlinux.org/index.php/rEFInd).
|
||||
menuentry "Arch Linux" {
|
||||
icon /EFI/refind/icons/os_arch.png
|
||||
volume "Arch Linux"
|
||||
loader /boot/vmlinuz-linux
|
||||
initrd /boot/initramfs-linux.img
|
||||
options "root=PARTUUID=5028fa50-0079-4c40-b240-abfaf28693ea rw add_efi_memmap"
|
||||
submenuentry "Boot using fallback initramfs" {
|
||||
initrd /boot/initramfs-linux-fallback.img
|
||||
}
|
||||
submenuentry "Boot to terminal" {
|
||||
add_options "systemd.unit=multi-user.target"
|
||||
}
|
||||
disabled
|
||||
}
|
||||
|
||||
# A sample entry for loading Ubuntu using its standard name for
|
||||
# its GRUB 2 boot loader. Note uses of Linux-style forward slashes
|
||||
menuentry Ubuntu {
|
||||
loader /EFI/ubuntu/grubx64.efi
|
||||
icon /EFI/refind/icons/os_linux.png
|
||||
disabled
|
||||
}
|
||||
|
||||
# A minimal ELILO entry, which probably offers nothing that
|
||||
# auto-detection can't accomplish.
|
||||
menuentry "ELILO" {
|
||||
loader \EFI\elilo\elilo.efi
|
||||
disabled
|
||||
}
|
||||
|
||||
# Like the ELILO entry, this one offers nothing that auto-detection
|
||||
# can't do; but you might use it if you want to disable auto-detection
|
||||
# but still boot Windows....
|
||||
menuentry "Windows 7" {
|
||||
loader \EFI\Microsoft\Boot\bootmgfw.efi
|
||||
disabled
|
||||
}
|
||||
|
||||
# EFI shells are programs just like boot loaders, and can be
|
||||
# launched in the same way. You can pass a shell the name of a
|
||||
# script that it's to run on the "options" line. The script
|
||||
# could initialize hardware and then launch an OS, or it could
|
||||
# do something entirely different.
|
||||
menuentry "Windows via shell script" {
|
||||
icon \EFI\refind\icons\os_win.png
|
||||
loader \EFI\tools\shell.efi
|
||||
options "fs0:\EFI\tools\launch_windows.nsh"
|
||||
disabled
|
||||
}
|
||||
|
||||
# MacOS is normally detected and run automatically; however,
|
||||
# if you want to do something unusual, a manual boot stanza may
|
||||
# be the way to do it. This one does nothing very unusual, but
|
||||
# it may serve as a starting point. Note that you'll almost
|
||||
# certainly need to change the "volume" line for this example
|
||||
# to work.
|
||||
menuentry "My macOS" {
|
||||
icon \EFI\refind\icons\os_mac.png
|
||||
volume "macOS boot"
|
||||
loader \System\Library\CoreServices\boot.efi
|
||||
disabled
|
||||
}
|
||||
|
||||
# The firmware_bootnum token takes a HEXADECIMAL value as an option
|
||||
# and sets that value using the EFI's BootNext variable and then
|
||||
# reboots the computer. This then causes a one-time boot of the
|
||||
# computer using this EFI boot option. It can be used for various
|
||||
# purposes, but one that's likely to interest some rEFInd users is
|
||||
# that some Macs with HiDPI displays produce lower-resolution
|
||||
# desktops when booted through rEFInd than when booted via Apple's
|
||||
# own boot manager. Booting using the firmware_bootnum option
|
||||
# produces the better resolution. Note that no loader option is
|
||||
# used in this type of configuration.
|
||||
menuentry "macOS via BootNext" {
|
||||
icon /EFI/refind/icons/os_mac.png
|
||||
firmware_bootnum 80
|
||||
disabled
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
"Boot with standard options" "rw root=/dev/mapper/cryptroot cryptdevice=UUID=c452045f-1bad-48c0-9816-f53c67a416dc:cryptroot resume=UUID=11c0ac93-cd2a-451d-9a6e-cf7f855fb26a quiet"
|
||||
"Boot to single-user mode" "rw root=/dev/mapper/cryptroot cryptdevice=UUID=c452045f-1bad-48c0-9816-f53c67a416dc:cryptroot resume=UUID=11c0ac93-cd2a-451d-9a6e-cf7f855fb26a quiet single"
|
||||
"Boot with minimal options" "rw root=/dev/mapper/cryptroot cryptdevice=UUID=c452045f-1bad-48c0-9816-f53c67a416dc:cryptroot resume=UUID=11c0ac93-cd2a-451d-9a6e-cf7f855fb26a quiet"
|
||||
@@ -0,0 +1,6 @@
|
||||
# Laptop suspend and hibernation policy.
|
||||
[Sleep]
|
||||
AllowSuspend=yes
|
||||
AllowHibernation=yes
|
||||
AllowSuspendThenHibernate=yes
|
||||
HibernateDelaySec=15min
|
||||
@@ -0,0 +1,2 @@
|
||||
[Login]
|
||||
IdleAction=ignore
|
||||
@@ -0,0 +1,9 @@
|
||||
Section "InputClass"
|
||||
Identifier "touchpad"
|
||||
Driver "libinput"
|
||||
MatchIsTouchpad "on"
|
||||
Option "Tapping" "on"
|
||||
Option "TappingButtonMap" "lrm"
|
||||
Option "NaturalScrolling" "true"
|
||||
Option "ClickMethod" "clickfinger"
|
||||
EndSection
|
||||
@@ -0,0 +1,4 @@
|
||||
# File to be place under /etc/NetworkManager/conf.d
|
||||
[connection]
|
||||
# Values are 0 (use default), 1 (ignore/don't touch), 2 (disable) or 3 (enable).
|
||||
wifi.powersave = 3
|
||||
@@ -71,6 +71,7 @@ hl.bind(main_mod .. " + SHIFT + RETURN", hl.dsp.exec_cmd("rofi -show combi"))
|
||||
hl.bind(main_mod .. " + SPACE", hl.dsp.exec_cmd(pi_status_ui_toggle))
|
||||
hl.bind(main_mod .. " + N", hl.dsp.exec_cmd(noctalia_ipc .. "panel-toggle alex/knowledge-lookup:panel"))
|
||||
hl.bind(main_mod .. " + S", hl.dsp.exec_cmd(noctalia_ipc .. "panel-toggle control-center"))
|
||||
hl.bind(main_mod .. " + 0", hl.dsp.exec_cmd(noctalia_ipc .. "panel-toggle session"))
|
||||
hl.bind(main_mod .. " + SHIFT + F", hl.dsp.exec_cmd(noctalia_ipc .. "bar-toggle main"))
|
||||
hl.bind(main_mod .. " + SHIFT + R", hl.dsp.exec_cmd("hyprctl reload"))
|
||||
hl.bind(main_mod .. " + CTRL + L", hl.dsp.exec_cmd("command -v hyprlock >/dev/null && hyprlock || loginctl lock-session"))
|
||||
@@ -0,0 +1,35 @@
|
||||
# Match the active Alacritty look while retaining Kitty's native graphics protocol.
|
||||
font_family MesloLGS NF
|
||||
font_size 15.0
|
||||
|
||||
# Palette: active ~/.config/alacritty/alacritty.toml plus Noctalia cursor/selection.
|
||||
foreground #FCFCFA
|
||||
background #2D2A2E
|
||||
cursor #fff1e6
|
||||
cursor_text_color #000000
|
||||
selection_foreground #fff1e6
|
||||
selection_background #3b220f
|
||||
|
||||
color0 #403E41
|
||||
color1 #FF6188
|
||||
color2 #A9DC76
|
||||
color3 #FFD866
|
||||
color4 #FC9867
|
||||
color5 #AB9DF2
|
||||
color6 #78DCE8
|
||||
color7 #FCFCFA
|
||||
color8 #727072
|
||||
color9 #FF6188
|
||||
color10 #A9DC76
|
||||
color11 #FFD866
|
||||
color12 #FC9867
|
||||
color13 #AB9DF2
|
||||
color14 #78DCE8
|
||||
color15 #FCFCFA
|
||||
|
||||
# Preserve Alacritty-like minimal window behavior.
|
||||
window_padding_width 0
|
||||
copy_on_select no
|
||||
|
||||
# Keep the shell integration and graphics protocol available to Ranger.
|
||||
shell_integration enabled
|
||||
@@ -0,0 +1,10 @@
|
||||
[Unit]
|
||||
Description=OpenSSH key agent
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket
|
||||
ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 yazi-rs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Catppuccin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,36 @@
|
||||
<div align="center">
|
||||
<img src="https://github.com/sxyazi/yazi/blob/main/assets/logo.png?raw=true" alt="Yazi logo" width="20%">
|
||||
</div>
|
||||
|
||||
<h3 align="center">
|
||||
Catppuccin Macchiato Flavor for <a href="https://github.com/sxyazi/yazi">Yazi</a>
|
||||
</h3>
|
||||
|
||||
## 👀 Preview
|
||||
|
||||
<img src="preview.png" width="600" />
|
||||
|
||||
## 🎨 Installation
|
||||
|
||||
```sh
|
||||
ya pkg add yazi-rs/flavors:catppuccin-macchiato
|
||||
```
|
||||
|
||||
## ⚙️ Usage
|
||||
|
||||
Set the content of your `theme.toml` to enable it as your _dark_ flavor:
|
||||
|
||||
```toml
|
||||
[flavor]
|
||||
dark = "catppuccin-macchiato"
|
||||
```
|
||||
|
||||
Make sure your `theme.toml` doesn't contain anything other than `[flavor]`, unless you want to override certain styles of this flavor.
|
||||
|
||||
See the [Yazi flavor documentation](https://yazi-rs.github.io/docs/flavors/overview) for more details.
|
||||
|
||||
## 📜 License
|
||||
|
||||
The flavor is MIT-licensed, and the included tmTheme is also MIT-licensed.
|
||||
|
||||
Check the [LICENSE](LICENSE) and [LICENSE-tmtheme](LICENSE-tmtheme) file for more details.
|
||||
@@ -0,0 +1,215 @@
|
||||
# vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
# : Manager {{{
|
||||
|
||||
[mgr]
|
||||
cwd = { fg = "#8bd5ca" }
|
||||
|
||||
# Find
|
||||
find_keyword = { fg = "#eed49f", bold = true, italic = true, underline = true }
|
||||
find_position = { fg = "#f5bde6", bg = "reset", bold = true, italic = true }
|
||||
|
||||
# Marker
|
||||
marker_copied = { fg = "#a6da95", bg = "#a6da95" }
|
||||
marker_cut = { fg = "#ed8796", bg = "#ed8796" }
|
||||
marker_marked = { fg = "#8bd5ca", bg = "#8bd5ca" }
|
||||
marker_selected = { fg = "#eed49f", bg = "#eed49f" }
|
||||
|
||||
# Count
|
||||
count_copied = { fg = "#24273a", bg = "#a6da95" }
|
||||
count_cut = { fg = "#24273a", bg = "#ed8796" }
|
||||
count_selected = { fg = "#24273a", bg = "#eed49f" }
|
||||
|
||||
# Border
|
||||
border_symbol = "│"
|
||||
border_style = { fg = "#8087a2" }
|
||||
|
||||
# : }}}
|
||||
|
||||
|
||||
# : Tabs {{{
|
||||
|
||||
[tabs]
|
||||
active = { fg = "#24273a", bg = "#8aadf4", bold = true }
|
||||
inactive = { fg = "#8aadf4", bg = "#363a4f" }
|
||||
|
||||
# : }}}
|
||||
|
||||
|
||||
# : Mode {{{
|
||||
|
||||
[mode]
|
||||
|
||||
normal_main = { fg = "#24273a", bg = "#8aadf4", bold = true }
|
||||
normal_alt = { fg = "#8aadf4", bg = "#363a4f" }
|
||||
|
||||
# Select mode
|
||||
select_main = { fg = "#24273a", bg = "#8bd5ca", bold = true }
|
||||
select_alt = { fg = "#8bd5ca", bg = "#363a4f" }
|
||||
|
||||
# Unset mode
|
||||
unset_main = { fg = "#24273a", bg = "#f0c6c6", bold = true }
|
||||
unset_alt = { fg = "#f0c6c6", bg = "#363a4f" }
|
||||
|
||||
# : }}}
|
||||
|
||||
|
||||
# : Status bar {{{
|
||||
|
||||
[status]
|
||||
# Permissions
|
||||
perm_sep = { fg = "#8087a2" }
|
||||
perm_type = { fg = "#8aadf4" }
|
||||
perm_read = { fg = "#eed49f" }
|
||||
perm_write = { fg = "#ed8796" }
|
||||
perm_exec = { fg = "#a6da95" }
|
||||
|
||||
# Progress
|
||||
progress_label = { fg = "#ffffff", bold = true }
|
||||
progress_normal = { fg = "#a6da95", bg = "#494d64" }
|
||||
progress_error = { fg = "#eed49f", bg = "#ed8796" }
|
||||
|
||||
# : }}}
|
||||
|
||||
|
||||
# : Pick {{{
|
||||
|
||||
[pick]
|
||||
border = { fg = "#8aadf4" }
|
||||
active = { fg = "#f5bde6", bold = true }
|
||||
inactive = {}
|
||||
|
||||
# : }}}
|
||||
|
||||
|
||||
# : Input {{{
|
||||
|
||||
[input]
|
||||
border = { fg = "#8aadf4" }
|
||||
title = {}
|
||||
value = {}
|
||||
selected = { reversed = true }
|
||||
|
||||
# : }}}
|
||||
|
||||
|
||||
# : Completion {{{
|
||||
|
||||
[cmp]
|
||||
border = { fg = "#8aadf4" }
|
||||
|
||||
# : }}}
|
||||
|
||||
|
||||
# : Tasks {{{
|
||||
|
||||
[tasks]
|
||||
border = { fg = "#8aadf4" }
|
||||
title = {}
|
||||
hovered = { fg = "#f5bde6", bold = true }
|
||||
|
||||
# : }}}
|
||||
|
||||
|
||||
# : Which {{{
|
||||
|
||||
[which]
|
||||
border = { fg = "#8aadf4" }
|
||||
cand = { fg = "#8bd5ca" }
|
||||
rest = { fg = "#939ab7" }
|
||||
desc = { fg = "#f5bde6" }
|
||||
separator = " "
|
||||
separator_style = { fg = "#5b6078" }
|
||||
|
||||
# : }}}
|
||||
|
||||
|
||||
# : Help {{{
|
||||
|
||||
[help]
|
||||
on = { fg = "#8bd5ca" }
|
||||
run = { fg = "#f5bde6" }
|
||||
hovered = { reversed = true, bold = true }
|
||||
footer = { fg = "#363a4f", bg = "#cad3f5" }
|
||||
|
||||
# : }}}
|
||||
|
||||
|
||||
# : Spotter {{{
|
||||
|
||||
[spot]
|
||||
border = { fg = "#8aadf4" }
|
||||
title = { fg = "#8aadf4" }
|
||||
tbl_col = { fg = "#8bd5ca" }
|
||||
tbl_cell = { fg = "#f5bde6", bg = "#494d64" }
|
||||
|
||||
# : }}}
|
||||
|
||||
|
||||
# : Notification {{{
|
||||
|
||||
[notify]
|
||||
title_info = { fg = "#a6da95" }
|
||||
title_warn = { fg = "#eed49f" }
|
||||
title_error = { fg = "#ed8796" }
|
||||
|
||||
# : }}}
|
||||
|
||||
|
||||
# : File-specific styles {{{
|
||||
|
||||
[filetype]
|
||||
|
||||
rules = [
|
||||
# Image
|
||||
{ mime = "**/image/*", fg = "#8bd5ca" },
|
||||
# Media
|
||||
{ mime = "**/{audio,video}/*", fg = "#eed49f" },
|
||||
# Archive
|
||||
{ mime = "**/application/{zip,rar,7z*,tar,gzip,xz,zstd,bzip*,lzma,compress,archive,cpio,arj,xar,ms-cab*}", fg = "#f5bde6" },
|
||||
# Document
|
||||
{ mime = "**/application/{pdf,doc,rtf}", fg = "#a6da95" },
|
||||
# Virtual file system
|
||||
{ mime = "vfs/{absent,stale}", fg = "#939ab7" },
|
||||
# Fallback
|
||||
{ url = "*", fg = "#cad3f5" },
|
||||
{ url = "*/", fg = "#8aadf4" },
|
||||
]
|
||||
|
||||
# : }}}
|
||||
|
||||
[icon]
|
||||
|
||||
dirs = [
|
||||
{ name = ".config", text = "", fg = "#f5bde6" },
|
||||
{ name = ".git", text = "", fg = "#8bd5ca" },
|
||||
{ name = ".github", text = "", fg = "#8aadf4" },
|
||||
{ name = ".npm", text = "", fg = "#8aadf4" },
|
||||
{ name = "Desktop", text = "", fg = "#8bd5ca" },
|
||||
{ name = "Development", text = "", fg = "#8bd5ca" },
|
||||
{ name = "Documents", text = "", fg = "#8bd5ca" },
|
||||
{ name = "Downloads", text = "", fg = "#8bd5ca" },
|
||||
{ name = "Library", text = "", fg = "#8bd5ca" },
|
||||
{ name = "Movies", text = "", fg = "#8bd5ca" },
|
||||
{ name = "Music", text = "", fg = "#8bd5ca" },
|
||||
{ name = "Pictures", text = "", fg = "#8bd5ca" },
|
||||
{ name = "Public", text = "", fg = "#8bd5ca" },
|
||||
{ name = "Videos", text = "", fg = "#8bd5ca" },
|
||||
]
|
||||
conds = [
|
||||
# Special files
|
||||
{ if = "orphan", text = "", fg = "#cad3f5" },
|
||||
{ if = "link", text = "", fg = "#8087a2" },
|
||||
{ if = "block", text = "", fg = "#f0c6c6" },
|
||||
{ if = "char", text = "", fg = "#f0c6c6" },
|
||||
{ if = "fifo", text = "", fg = "#f0c6c6" },
|
||||
{ if = "sock", text = "", fg = "#f0c6c6" },
|
||||
{ if = "sticky", text = "", fg = "#f0c6c6" },
|
||||
{ if = "dummy", text = "", fg = "#ed8796" },
|
||||
|
||||
# Fallback
|
||||
{ if = "dir & hovered", text = "", fg = "#8aadf4" },
|
||||
{ if = "dir", text = "", fg = "#8aadf4" },
|
||||
{ if = "exec", text = "", fg = "#a6da95" },
|
||||
{ if = "!dir", text = "", fg = "#cad3f5" },
|
||||
]
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 674 KiB |
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
||||
require("git"):setup {
|
||||
order = 1500,
|
||||
}
|
||||
|
||||
require("githead"):setup {
|
||||
branch_prefix = "on ",
|
||||
branch_symbol = " ",
|
||||
branch_borders = "()",
|
||||
branch_color = "#ffb05c",
|
||||
remote_branch_color = "#f4c7a1",
|
||||
tag_color = "#ffcc99",
|
||||
commit_color = "#f4c7a1",
|
||||
behind_remote_color = "#ff6b4a",
|
||||
ahead_remote_color = "#ff8800",
|
||||
stashes_color = "#c98a45",
|
||||
state_color = "#ff6b4a",
|
||||
staged_color = "#ff8800",
|
||||
unstaged_color = "#ffb05c",
|
||||
untracked_color = "#f4c7a1",
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#:schema https://yazi-rs.github.io/schemas/keymap.json
|
||||
|
||||
[[mgr.prepend_keymap]]
|
||||
on = "l"
|
||||
run = "plugin smart-enter"
|
||||
desc = "Enter the child directory, or open the file"
|
||||
|
||||
[[mgr.prepend_keymap]]
|
||||
on = ["g", "d"]
|
||||
run = "cd ~/downloads"
|
||||
desc = "Cd to Downloads"
|
||||
|
||||
[[mgr.prepend_keymap]]
|
||||
on = ["g", "D"]
|
||||
run = "cd ~/cloud/documents"
|
||||
desc = "Cd to Documents"
|
||||
@@ -0,0 +1,19 @@
|
||||
[[plugin.deps]]
|
||||
use = "yazi-rs/plugins:smart-enter"
|
||||
rev = "0be29a9"
|
||||
hash = "187cc58ba7ac3befd49c342129e6f1b6"
|
||||
|
||||
[[plugin.deps]]
|
||||
use = "yazi-rs/plugins:git"
|
||||
rev = "3f2b882"
|
||||
hash = "336548d9f67926e12d5584f60b790f1"
|
||||
|
||||
[[plugin.deps]]
|
||||
use = "llanosrocas/githead"
|
||||
rev = "317d09f"
|
||||
hash = "41dc37a724b2afd21da4f1ea6c1182d8"
|
||||
|
||||
[[flavor.deps]]
|
||||
use = "yazi-rs/flavors:catppuccin-macchiato"
|
||||
rev = "be0b21d"
|
||||
hash = "5b1bf96d1cba26376087c37de993c517"
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 yazi-rs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,84 @@
|
||||
# git.yazi
|
||||
|
||||
Show the status of Git file changes as linemode in the file list.
|
||||
|
||||
https://github.com/user-attachments/assets/34976be9-a871-4ffe-9d5a-c4cdd0bf4576
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
ya pkg add yazi-rs/plugins:git
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
Add the following to your `~/.config/yazi/init.lua`:
|
||||
|
||||
```lua
|
||||
require("git"):setup {
|
||||
-- Order of status signs showing in the linemode
|
||||
order = 1500,
|
||||
}
|
||||
```
|
||||
|
||||
And register it as fetchers in your `~/.config/yazi/yazi.toml`:
|
||||
|
||||
```toml
|
||||
[[plugin.prepend_fetchers]]
|
||||
url = "*"
|
||||
run = "git"
|
||||
group = "git"
|
||||
|
||||
[[plugin.prepend_fetchers]]
|
||||
url = "*/"
|
||||
run = "git"
|
||||
group = "git"
|
||||
```
|
||||
|
||||
## Advanced
|
||||
|
||||
You can customize the [Style](https://yazi-rs.github.io/docs/configuration/theme#types.style) of the status sign with:
|
||||
|
||||
- `[git].unknown` - status cannot/not yet determined
|
||||
- `[git].modified` - modified file
|
||||
- `[git].added` - added file
|
||||
- `[git].untracked` - untracked file
|
||||
- `[git].ignored` - ignored file
|
||||
- `[git].deleted` - deleted file
|
||||
- `[git].updated` - updated file
|
||||
- `[git].clean` - clean file
|
||||
|
||||
For example:
|
||||
|
||||
```toml
|
||||
# theme.toml / flavor.toml
|
||||
[git]
|
||||
modified = { fg = "blue" }
|
||||
deleted = { fg = "red", bold = true }
|
||||
```
|
||||
|
||||
You can also customize the text of the status sign with:
|
||||
|
||||
- `[git].unknown_sign` - status cannot/not yet determined
|
||||
- `[git].modified_sign` - modified file
|
||||
- `[git].added_sign` - added file
|
||||
- `[git].untracked_sign` - untracked file
|
||||
- `[git].ignored_sign` - ignored file
|
||||
- `[git].deleted_sign` - deleted file
|
||||
- `[git].updated_sign` - updated file
|
||||
- `[git].clean_sign` - clean file
|
||||
|
||||
For example:
|
||||
|
||||
```toml
|
||||
# theme.toml / flavor.toml
|
||||
[git]
|
||||
unknown_sign = " "
|
||||
modified_sign = "M"
|
||||
deleted_sign = "D"
|
||||
clean_sign = "✔"
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This plugin is MIT-licensed. For more information check the [LICENSE](LICENSE) file.
|
||||
@@ -0,0 +1,279 @@
|
||||
--- @since 26.5.6
|
||||
|
||||
local WINDOWS = ya.target_family() == "windows"
|
||||
|
||||
-- The code of supported git status,
|
||||
-- also used to determine which status to show for directories when they contain different statuses
|
||||
-- see `bubble_up`
|
||||
---@enum CODES
|
||||
local CODES = {
|
||||
unknown = 100, -- status cannot/not yet determined
|
||||
excluded = 99, -- ignored directory
|
||||
ignored = 6, -- ignored file
|
||||
untracked = 5,
|
||||
modified = 4,
|
||||
added = 3,
|
||||
deleted = 2,
|
||||
updated = 1,
|
||||
clean = 0,
|
||||
}
|
||||
|
||||
local PATTERNS = {
|
||||
{ "!$", CODES.ignored },
|
||||
{ "?$", CODES.untracked },
|
||||
{ "[MT]", CODES.modified },
|
||||
{ "[AC]", CODES.added },
|
||||
{ "D", CODES.deleted },
|
||||
{ "U", CODES.updated },
|
||||
{ "[AD][AD]", CODES.updated },
|
||||
}
|
||||
|
||||
local function theme()
|
||||
local t = th.git or {}
|
||||
return {
|
||||
[CODES.unknown] = t.unknown or ui.Style(),
|
||||
[CODES.ignored] = t.ignored or ui.Style():fg("darkgray"),
|
||||
[CODES.untracked] = t.untracked or ui.Style():fg("magenta"),
|
||||
[CODES.modified] = t.modified or ui.Style():fg("yellow"),
|
||||
[CODES.added] = t.added or ui.Style():fg("green"),
|
||||
[CODES.deleted] = t.deleted or ui.Style():fg("red"),
|
||||
[CODES.updated] = t.updated or ui.Style():fg("yellow"),
|
||||
[CODES.clean] = t.clean or ui.Style(),
|
||||
}, {
|
||||
[CODES.unknown] = t.unknown_sign or "",
|
||||
[CODES.ignored] = t.ignored_sign or " ",
|
||||
[CODES.untracked] = t.untracked_sign or "? ",
|
||||
[CODES.modified] = t.modified_sign or " ",
|
||||
[CODES.added] = t.added_sign or " ",
|
||||
[CODES.deleted] = t.deleted_sign or " ",
|
||||
[CODES.updated] = t.updated_sign or " ",
|
||||
[CODES.clean] = t.clean_sign or "",
|
||||
}
|
||||
end
|
||||
|
||||
---@param line string
|
||||
---@return CODES, string
|
||||
local function match(line)
|
||||
local signs = line:sub(1, 2)
|
||||
for _, p in ipairs(PATTERNS) do
|
||||
local path, pattern, code = nil, p[1], p[2]
|
||||
if signs:find(pattern) then
|
||||
path = line:sub(4, 4) == '"' and line:sub(5, -2) or line:sub(4)
|
||||
path = WINDOWS and path:gsub("/", "\\") or path
|
||||
end
|
||||
if not path then
|
||||
elseif path:find("[/\\]$") then
|
||||
-- Mark the ignored directory as `excluded`, so we can process it further within `propagate_down`
|
||||
return code == CODES.ignored and CODES.excluded or code, path:sub(1, -2)
|
||||
else
|
||||
return code, path
|
||||
end
|
||||
---@diagnostic disable-next-line: missing-return
|
||||
end
|
||||
end
|
||||
|
||||
---@param cwd Url
|
||||
---@return string?
|
||||
local function root(cwd)
|
||||
local is_worktree = function(url)
|
||||
local file, head = io.open(tostring(url)), nil
|
||||
if file then
|
||||
head = file:read(8)
|
||||
file:close()
|
||||
end
|
||||
return head == "gitdir: "
|
||||
end
|
||||
|
||||
repeat
|
||||
local next = cwd:join(".git")
|
||||
local cha = fs.cha(next)
|
||||
if cha and (cha.is_dir or is_worktree(next)) then
|
||||
return tostring(cwd)
|
||||
end
|
||||
cwd = cwd.parent
|
||||
until not cwd
|
||||
end
|
||||
|
||||
---@param changed Changes
|
||||
---@return Changes
|
||||
local function bubble_up(changed)
|
||||
local new, empty = {}, Url("")
|
||||
for path, code in pairs(changed) do
|
||||
if code ~= CODES.ignored then
|
||||
local url = Url(path).parent
|
||||
while url and url ~= empty do
|
||||
local s = tostring(url)
|
||||
new[s] = (new[s] or CODES.clean) > code and new[s] or code
|
||||
url = url.parent
|
||||
end
|
||||
end
|
||||
end
|
||||
return new
|
||||
end
|
||||
|
||||
---@param excluded string[]
|
||||
---@param cwd Url
|
||||
---@param repo Url
|
||||
---@return Changes
|
||||
local function propagate_down(excluded, cwd, repo)
|
||||
local new, rel = {}, cwd:strip_prefix(repo)
|
||||
for _, path in ipairs(excluded) do
|
||||
if rel:starts_with(path) then
|
||||
-- If `cwd` is a subdirectory of an excluded directory, also mark it as `excluded`
|
||||
new[tostring(cwd)] = CODES.excluded
|
||||
elseif cwd == repo:join(path).parent then
|
||||
-- If `path` is a direct subdirectory of `cwd`, mark it as `ignored`
|
||||
new[path] = CODES.ignored
|
||||
else
|
||||
-- Skipping, we only care about `cwd` itself and its direct subdirectories for maximum performance
|
||||
end
|
||||
end
|
||||
return new
|
||||
end
|
||||
|
||||
---@param cwd string
|
||||
---@param repo string
|
||||
---@param changed Changes
|
||||
local add = ya.sync(function(st, cwd, repo, changed)
|
||||
---@cast st State
|
||||
|
||||
st.dirs[cwd] = repo
|
||||
st.repos[repo] = st.repos[repo] or {}
|
||||
for path, code in pairs(changed) do
|
||||
if code == CODES.clean then
|
||||
st.repos[repo][path] = nil
|
||||
elseif code == CODES.excluded then
|
||||
-- Mark the directory with a special value `excluded` so that it can be distinguished during UI rendering
|
||||
st.dirs[path] = CODES.excluded
|
||||
else
|
||||
st.repos[repo][path] = code
|
||||
end
|
||||
end
|
||||
ui.render()
|
||||
end)
|
||||
|
||||
---@param cwd string
|
||||
local remove = ya.sync(function(st, cwd)
|
||||
---@cast st State
|
||||
|
||||
local repo = st.dirs[cwd]
|
||||
if not repo then
|
||||
return
|
||||
end
|
||||
|
||||
ui.render()
|
||||
st.dirs[cwd] = nil
|
||||
if not st.repos[repo] then
|
||||
return
|
||||
end
|
||||
|
||||
for _, r in pairs(st.dirs) do
|
||||
if r == repo then
|
||||
return
|
||||
end
|
||||
end
|
||||
st.repos[repo] = nil
|
||||
end)
|
||||
|
||||
---@param st State
|
||||
---@param opts Options
|
||||
local function setup(st, opts)
|
||||
st.dirs = {}
|
||||
st.repos = {}
|
||||
|
||||
opts = opts or {}
|
||||
opts.order = opts.order or 1500
|
||||
|
||||
local styles, signs = theme()
|
||||
ps.sub("theme", function()
|
||||
styles, signs = theme()
|
||||
end)
|
||||
|
||||
Linemode:children_add(function(self)
|
||||
if not self._file.in_current then
|
||||
return ""
|
||||
end
|
||||
|
||||
local url = self._file.url
|
||||
local repo = st.dirs[tostring(url.base or url.parent)]
|
||||
local code = CODES.unknown
|
||||
if repo then
|
||||
code = repo == CODES.excluded and CODES.ignored or st.repos[repo][tostring(url):sub(#repo + 2)] or CODES.clean
|
||||
end
|
||||
|
||||
if signs[code] == "" then
|
||||
return ""
|
||||
elseif self._file.is_hovered then
|
||||
return ui.Line { " ", signs[code] }
|
||||
else
|
||||
return ui.Line { " ", ui.Span(signs[code]):style(styles[code]) }
|
||||
end
|
||||
end, opts.order)
|
||||
end
|
||||
|
||||
---@type UnstableFetcher
|
||||
local function fetch(_, job)
|
||||
local cwd = job.files[1].url.base or job.files[1].url.parent
|
||||
local repo = root(cwd)
|
||||
if not repo then
|
||||
remove(tostring(cwd))
|
||||
return true
|
||||
end
|
||||
|
||||
local paths = {}
|
||||
for _, file in ipairs(job.files) do
|
||||
paths[#paths + 1] = tostring(file.url)
|
||||
end
|
||||
|
||||
-- stylua: ignore
|
||||
local output, err = Command("git")
|
||||
:cwd(tostring(cwd))
|
||||
:arg({ "--no-optional-locks", "-c", "core.quotePath=", "status", "--porcelain", "-unormal", "--no-renames", "--ignored=matching" })
|
||||
:arg(paths)
|
||||
:output()
|
||||
if not output then
|
||||
return true, Err("Cannot spawn `git` command, error: %s", err)
|
||||
end
|
||||
|
||||
local changed, excluded = {}, {}
|
||||
for line in output.stdout:gmatch("[^\r\n]+") do
|
||||
local code, path = match(line)
|
||||
if code == CODES.excluded then
|
||||
excluded[#excluded + 1] = path
|
||||
else
|
||||
changed[path] = code
|
||||
end
|
||||
end
|
||||
|
||||
if job.files[1].cha.is_dir then
|
||||
ya.dict_merge(changed, bubble_up(changed))
|
||||
end
|
||||
ya.dict_merge(changed, propagate_down(excluded, cwd, Url(repo)))
|
||||
|
||||
-- Reset the status of any files that don't appear in the output of `git status` to `clean`,
|
||||
-- so that cleaning up outdated statuses from `st.repos`
|
||||
for _, path in ipairs(paths) do
|
||||
local s = path:sub(#repo + 2)
|
||||
changed[s] = changed[s] or CODES.clean
|
||||
end
|
||||
|
||||
add(tostring(cwd), repo, changed)
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- TODO: remove
|
||||
local function fetch_compact(self, job)
|
||||
if ya.throttle then
|
||||
fetch(self, job)
|
||||
return ya.co(function()
|
||||
for _, file in ipairs(job.files) do
|
||||
coroutine.yield(file, { retry = true })
|
||||
end
|
||||
end)
|
||||
else
|
||||
return fetch(self, job)
|
||||
end
|
||||
end
|
||||
|
||||
return { setup = setup, fetch = fetch_compact }
|
||||
@@ -0,0 +1,12 @@
|
||||
---@class State
|
||||
---@field dirs table<string, string|CODES> Mapping between a directory and its corresponding repository
|
||||
---@field repos table<string, Changes> Mapping between a repository and the status of each of its files
|
||||
|
||||
---@class Options
|
||||
---@field order number The order in which the status is displayed
|
||||
---@field renamed boolean Whether to include renamed files in the status (or treat them as modified)
|
||||
|
||||
-- TODO: move this to `types.yazi` once it's get stable
|
||||
---@alias UnstableFetcher fun(self: unknown, job: { files: File[] }): boolean, Error?
|
||||
|
||||
---@alias Changes table<string, CODES>
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 llanosrocas
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,422 @@
|
||||
# githead.yazi
|
||||
|
||||
Git status header for yazi inspired by [powerlevel10k](https://github.com/romkatv/powerlevel10k?tab=readme-ov-file#what-do-different-symbols-in-git-status-mean).
|
||||
|
||||

|
||||

|
||||
|
||||
All supported features are listed [here](#features). More presets are available [here](#presets).
|
||||
|
||||
## Requirements
|
||||
|
||||
- yazi version >= [26.1.22](https://github.com/sxyazi/yazi/releases/tag/v26.1.22).
|
||||
- Font with symbol support. For example [Nerd Fonts](https://www.nerdfonts.com/).
|
||||
|
||||
## Compatibility
|
||||
|
||||
To keep the plugin up to date, there are two branches: `main` and `nightly`.
|
||||
The `main` branch follows major yazi releases, while `nightly` is linked to specific yazi commits or changes.
|
||||
|
||||
This setup allows shipping stable versions on time, while giving early access to "cutting-edge" changes. See matrix below.
|
||||
|
||||
<details close>
|
||||
<summary>Compatibility matrix</summary>
|
||||
|
||||
| githead | yazi |
|
||||
| :-------------------------------------------------------------------------------------------------------: | ----------------------------------------------------------------------------------------- |
|
||||
| [v2.0.2](https://github.com/llanosrocas/githead.yazi/releases/tag/v2.0.2) | [v26.1.22](https://github.com/sxyazi/yazi/releases/tag/v26.1.22) |
|
||||
| [v2.0.2](https://github.com/llanosrocas/githead.yazi/releases/tag/v2.0.2) | [v25.12.29](https://github.com/sxyazi/yazi/releases/tag/v25.12.29) |
|
||||
| [v2.0.2-nightly.292d37c](https://github.com/llanosrocas/githead.yazi/releases/tag/v2.0.2-nightly.292d37c) | [2f66561](https://github.com/sxyazi/yazi/commit/2f66561a8251f8788b2b0fd366af90555ecafc86) |
|
||||
| [v2.0.2-nightly.292d37c](https://github.com/llanosrocas/githead.yazi/releases/tag/v2.0.2-nightly.292d37c) | [6cfa92f](https://github.com/sxyazi/yazi/commit/6cfa92f11205d212155579b5b76d4cbabe723829) |
|
||||
| [v2.0.2-nightly.292d37c](https://github.com/llanosrocas/githead.yazi/releases/tag/v2.0.2-nightly.292d37c) | [292d37c](https://github.com/sxyazi/yazi/commit/292d37ccde5fb09dc7318247caf552213d16ec36) |
|
||||
| [v2.0.1](https://github.com/llanosrocas/githead.yazi/releases/tag/v2.0.1) | [917e1f5](https://github.com/sxyazi/yazi/commit/917e1f54a10445f2e25147c4b81a3c77d8233632) |
|
||||
| [v2.0.0](https://github.com/llanosrocas/githead.yazi/releases/tag/v2.0.0) | [693dff2](https://github.com/sxyazi/yazi/commit/693dff25e3165e357cc9d0b94ca3f2b176741a36) |
|
||||
| [v1.7.0](https://github.com/llanosrocas/githead.yazi/releases/tag/v1.7.0) | [693dff2](https://github.com/sxyazi/yazi/tree/693dff25e3165e357cc9d0b94ca3f2b176741a36) |
|
||||
| [v1.6.0](https://github.com/llanosrocas/githead.yazi/releases/tag/v1.6.0) | [v25.5.31](https://github.com/sxyazi/yazi/releases/tag/v25.5.31) |
|
||||
|
||||
</details>
|
||||
|
||||
## Installation
|
||||
|
||||
1. Using yazi package manager
|
||||
|
||||
```sh
|
||||
ya pkg add llanosrocas/githead
|
||||
```
|
||||
|
||||
_Or manually copy `main.lua` to the `~/.config/yazi/plugins/githead.yazi/main.lua`_
|
||||
|
||||
2. Add this line to your `~/.config/yazi/init.lua`:
|
||||
|
||||
```lua
|
||||
require("githead"):setup()
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
This is default config, if you want to see copy-paste presets go to [this section](#presets).
|
||||
|
||||
```lua
|
||||
require("githead"):setup({
|
||||
order = {
|
||||
"__spacer__",
|
||||
"branch",
|
||||
"remote",
|
||||
"__spacer__",
|
||||
"tag",
|
||||
"__spacer__",
|
||||
"commit",
|
||||
"__spacer__",
|
||||
"behind_ahead_remote",
|
||||
"__spacer__",
|
||||
"stashes",
|
||||
"__spacer__",
|
||||
"state",
|
||||
"__spacer__",
|
||||
"staged",
|
||||
"__spacer__",
|
||||
"unstaged",
|
||||
"__spacer__",
|
||||
"untracked",
|
||||
},
|
||||
|
||||
show_numbers = true, -- shows staged, unstaged, untracked, stashes count
|
||||
|
||||
show_branch = true,
|
||||
branch_prefix = "",
|
||||
branch_color = "blue",
|
||||
branch_symbol = "",
|
||||
branch_borders = "",
|
||||
|
||||
show_remote_branch = true, -- only shown if different from local branch
|
||||
always_show_remote_branch = false, -- always show remote branch even if it the same as local branch
|
||||
always_show_remote_repo = false, -- Adds `origin/` if `always_show_remote_branch` is enabled
|
||||
remote_branch_prefix = ":",
|
||||
remote_branch_color = "bright magenta",
|
||||
|
||||
show_tag = true, -- only shown if branch is not available
|
||||
always_show_tag = false,
|
||||
tag_color = "magenta",
|
||||
tag_symbol = "#",
|
||||
|
||||
show_commit = true, -- only shown if branch AND tag are not available
|
||||
always_show_commit = false,
|
||||
commit_color = "bright magenta",
|
||||
commit_symbol = "@",
|
||||
|
||||
show_behind_ahead_remote = true,
|
||||
behind_remote_color = "bright magenta",
|
||||
behind_remote_symbol = "⇣",
|
||||
ahead_remote_color = "bright magenta",
|
||||
ahead_remote_symbol = "⇡",
|
||||
|
||||
show_stashes = true,
|
||||
stashes_color = "bright magenta",
|
||||
stashes_symbol = "$",
|
||||
|
||||
show_state = true,
|
||||
show_state_prefix = true,
|
||||
state_color = "red",
|
||||
state_symbol = "~",
|
||||
|
||||
show_staged = true,
|
||||
staged_color = "bright yellow",
|
||||
staged_symbol = "+",
|
||||
|
||||
show_unstaged = true,
|
||||
unstaged_color = "bright yellow",
|
||||
unstaged_symbol = "!",
|
||||
|
||||
show_untracked = true,
|
||||
untracked_color = "blue",
|
||||
untracked_symbol = "?",
|
||||
})
|
||||
```
|
||||
|
||||
```
|
||||
/cwd on ( feature):origin/main #v1.0.0 #1234567 ⇣2⇡3 $1 rebase 1/2 ~2 +4 !1 ?5
|
||||
| | | | ││ | | | | | | | | | | | |
|
||||
| | | | ││ | | | | | | | | | | | └─── untracked_symbol
|
||||
| | | | ││ | | | | | | | | | | └────── unstaged_symbol
|
||||
| | | | ││ | | | | | | | | | └───────── staged_symbol
|
||||
| | | | ││ | | | | | | | | └──────────── state_symbol
|
||||
| | | | ││ | | | | | | | └─────────────────────── state_prefix
|
||||
| | | | ││ | | | | | | └────────────────────────── stashes_symbol
|
||||
| | | | ││ | | | | | └───────────────────────────── ahead_symbol
|
||||
| | | | ││ | | | | └─────────────────────────────── behind_symbol
|
||||
| | | | ││ | | | └──────────────────────────────────────── commit_symbol
|
||||
| | | | ││ | | └──────────────────────────────────────────────── tag_symbol
|
||||
| | | | ││ | └───────────────────────────────────────────────────── remote_branch
|
||||
| | | | ││ └─────────────────────────────────────────────────────────── remote_repo
|
||||
| | | | |└───────────────────────────────────────────────────────────── remote_branch_prefix
|
||||
| | | | └────────────────────────────────────────────────────────────── branch_borders
|
||||
| | | └──────────────────────────────────────────────────────────────────── branch
|
||||
| | └─────────────────────────────────────────────────────────────────────── branch_symbol
|
||||
| └─────────────────────────────────────────────────────────────────────────── branch_prefix
|
||||
└──────────────────────────────────────────────────────────────────────────────── cwd
|
||||
```
|
||||
|
||||
## Presets
|
||||
|
||||
- v1 default (My config)
|
||||
|
||||

|
||||
|
||||
<details>
|
||||
<summary>Config</summary>
|
||||
|
||||
```lua
|
||||
require("githead"):setup({
|
||||
branch_prefix = "on",
|
||||
branch_symbol = " ",
|
||||
branch_borders = "()",
|
||||
})
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
- [spaceship-prompt](https://github.com/spaceship-prompt/spaceship-prompt)
|
||||
|
||||

|
||||
|
||||
<details>
|
||||
<summary>Config</summary>
|
||||
|
||||
```lua
|
||||
require("githead"):setup({
|
||||
order = {
|
||||
"__spacer__",
|
||||
"branch",
|
||||
"remote",
|
||||
"__spacer__",
|
||||
"tag",
|
||||
"__spacer__",
|
||||
"commit",
|
||||
"__spacer__",
|
||||
"behind_ahead_remote",
|
||||
"stashes",
|
||||
"state",
|
||||
"staged",
|
||||
"unstaged",
|
||||
"untracked",
|
||||
},
|
||||
|
||||
show_numbers = false,
|
||||
|
||||
branch_symbol = " ",
|
||||
branch_prefix = "on",
|
||||
})
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
- [robertgzr/porcelain](https://github.com/robertgzr/porcelain)
|
||||
|
||||

|
||||
|
||||
<details>
|
||||
<summary>Config</summary>
|
||||
|
||||
```lua
|
||||
require("githead"):setup({
|
||||
order = {
|
||||
"__spacer__",
|
||||
"branch",
|
||||
"commit",
|
||||
"__spacer__",
|
||||
"behind_ahead_remote",
|
||||
"__spacer__",
|
||||
"untracked",
|
||||
"state",
|
||||
"unstaged",
|
||||
"__spacer__",
|
||||
"staged",
|
||||
},
|
||||
|
||||
show_numbers = false,
|
||||
|
||||
show_branch = true,
|
||||
branch_prefix = "",
|
||||
branch_color = "#288BD2",
|
||||
|
||||
always_show_commit = true,
|
||||
commit_color = "#859A00",
|
||||
|
||||
show_behind_ahead_remote = true,
|
||||
behind_remote_symbol = "↓",
|
||||
ahead_remote_symbol = "↑",
|
||||
behind_remote_color = "#DC322E",
|
||||
ahead_remote_color = "#4DB6AC",
|
||||
|
||||
show_state = true,
|
||||
show_state_prefix = false,
|
||||
state_symbol = "!!",
|
||||
state_color = "#B58901",
|
||||
|
||||
staged_symbol = "✔",
|
||||
staged_color = "green",
|
||||
|
||||
unstaged_symbol = "Δ",
|
||||
unstaged_color = "#288BD2",
|
||||
|
||||
untracked_symbol = "?",
|
||||
untracked_color = "#415F65",
|
||||
})
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
- Minimal (No color)
|
||||
|
||||

|
||||
|
||||
<details>
|
||||
<summary>Config</summary>
|
||||
|
||||
```lua
|
||||
require("githead"):setup({
|
||||
branch_color = "",
|
||||
|
||||
remote_branch_prefix = "@",
|
||||
remote_branch_color = "",
|
||||
|
||||
tag_color = "",
|
||||
|
||||
commit_color = "",
|
||||
|
||||
ahead_remote_symbol = "+",
|
||||
ahead_remote_color = "",
|
||||
behind_remote_symbol = "-",
|
||||
behind_remote_color = "",
|
||||
|
||||
stashes_symbol = "*",
|
||||
stashes_color = "",
|
||||
|
||||
show_state_prefix = false,
|
||||
state_symbol = "~",
|
||||
state_color = "",
|
||||
|
||||
staged_symbol = "S",
|
||||
staged_color = "",
|
||||
|
||||
unstaged_symbol = "U",
|
||||
unstaged_color = "",
|
||||
|
||||
untracked_symbol = "N",
|
||||
untracked_color = "",
|
||||
})
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
- Vibrant (Full)
|
||||
|
||||

|
||||
|
||||
<details>
|
||||
<summary>Config</summary>
|
||||
|
||||
```lua
|
||||
require("githead"):setup({
|
||||
order = {
|
||||
"__spacer__",
|
||||
"stashes",
|
||||
"__spacer__",
|
||||
"state",
|
||||
"__spacer__",
|
||||
"staged",
|
||||
"__spacer__",
|
||||
"unstaged",
|
||||
"__spacer__",
|
||||
"untracked",
|
||||
"__spacer__",
|
||||
"branch",
|
||||
"remote_branch",
|
||||
"__spacer__",
|
||||
"tag",
|
||||
"__spacer__",
|
||||
"commit",
|
||||
"__spacer__",
|
||||
"behind_ahead_remote",
|
||||
"__spacer__",
|
||||
},
|
||||
|
||||
branch_borders = "{}",
|
||||
branch_prefix = "|",
|
||||
branch_color = "#7aa2f7",
|
||||
remote_branch_color = "#9ece6a",
|
||||
always_show_remote_branch = true,
|
||||
always_show_remote_repo = true,
|
||||
|
||||
tag_symbol = "",
|
||||
always_show_tag = true,
|
||||
tag_color = "#bb9af7",
|
||||
|
||||
commit_symbol = "",
|
||||
always_show_commit = true,
|
||||
commit_color = "#e0af68",
|
||||
|
||||
staged_color = "#73daca",
|
||||
staged_symbol = "●",
|
||||
|
||||
unstaged_color = "#e0af68",
|
||||
unstaged_symbol = "✗",
|
||||
|
||||
untracked_color = "#f7768e",
|
||||
untracked_symbol = "?",
|
||||
|
||||
state_color = "#f5c359",
|
||||
state_symbol = "",
|
||||
|
||||
stashes_color = "#565f89",
|
||||
stashes_symbol = "⚑",
|
||||
})
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Features
|
||||
|
||||
- [x] Current branch
|
||||
- [x] Remote and remote branch
|
||||
- [x] Latest tag
|
||||
- [x] Latest commit
|
||||
- [x] Behind/Ahead of the remote
|
||||
- [x] Stashes
|
||||
- [x] States
|
||||
- [x] merge
|
||||
- [x] cherry
|
||||
- [x] rebase (+ done counter)
|
||||
- [x] revert
|
||||
- [x] bisect
|
||||
- [x] Staged
|
||||
- [x] Unstaged
|
||||
- [x] Untracked
|
||||
|
||||
### Under the hood
|
||||
|
||||
The goal is to use minimum amount of shell commands.
|
||||
|
||||
- Branch, stashes, staged files, unstaged files, untracked files.
|
||||
|
||||
```shell
|
||||
git status --ignore-submodules=dirty --branch --show-stash --ahead-behind
|
||||
```
|
||||
|
||||
- Remote branch and repo:
|
||||
|
||||
```shell
|
||||
git rev-parse --abbrev-ref --symbolic-full-name @{upstream}
|
||||
```
|
||||
|
||||
- Latest tag and commit:
|
||||
|
||||
```shell
|
||||
git log --format="commit %h%d" -n 1
|
||||
```
|
||||
|
||||
## Credits
|
||||
|
||||
- [yazi source code](https://github.com/sxyazi/yazi)
|
||||
- [powerlevel10k](https://github.com/romkatv/powerlevel10k)
|
||||
- [twio142](https://github.com/twio142/githead.yazi)
|
||||
@@ -0,0 +1,598 @@
|
||||
---@diagnostic disable: undefined-global
|
||||
|
||||
local save = ya.sync(function(this, cwd, output)
|
||||
if cwd:match("%.git[/\\]") or cwd:match("%.git$") then
|
||||
this.output = nil
|
||||
return
|
||||
end
|
||||
if cx.active.current.cwd == Url(cwd) then
|
||||
this.output = output
|
||||
ui.render()
|
||||
end
|
||||
end)
|
||||
|
||||
return {
|
||||
setup = function(this, options)
|
||||
options = options or {}
|
||||
|
||||
local config = {
|
||||
order = options.order or {
|
||||
"__spacer__",
|
||||
"branch",
|
||||
"remote_branch",
|
||||
"__spacer__",
|
||||
"tag",
|
||||
"__spacer__",
|
||||
"commit",
|
||||
"__spacer__",
|
||||
"behind_ahead_remote",
|
||||
"__spacer__",
|
||||
"stashes",
|
||||
"__spacer__",
|
||||
"state",
|
||||
"__spacer__",
|
||||
"staged",
|
||||
"__spacer__",
|
||||
"unstaged",
|
||||
"__spacer__",
|
||||
"untracked",
|
||||
},
|
||||
|
||||
show_numbers = options.show_numbers == nil and true
|
||||
or options.show_numbers,
|
||||
|
||||
show_branch = options.show_branch == nil and true or options.show_branch,
|
||||
branch_prefix = options.branch_prefix or "",
|
||||
branch_color = options.branch_color or "blue",
|
||||
branch_symbol = options.branch_symbol or "",
|
||||
branch_borders = options.branch_borders or "",
|
||||
|
||||
show_remote_branch = options.show_remote_branch == nil and true
|
||||
or options.show_remote_branch,
|
||||
always_show_remote_branch = options.always_show_remote_branch == nil
|
||||
and false
|
||||
or options.always_show_remote_branch,
|
||||
always_show_remote_repo = options.always_show_remote_repo == nil
|
||||
and false
|
||||
or options.always_show_remote_repo,
|
||||
remote_branch_prefix = options.remote_branch_prefix or ":",
|
||||
remote_branch_color = options.remote_branch_color or "bright magenta",
|
||||
|
||||
show_tag = options.show_tag == nil and true or options.show_tag,
|
||||
always_show_tag = options.always_show_tag == nil and false
|
||||
or options.always_show_tag,
|
||||
tag_color = options.tag_color or "magenta",
|
||||
tag_symbol = options.tag_symbol == nil and "#" or options.tag_symbol,
|
||||
|
||||
show_commit = options.show_commit == nil and true or options.show_commit,
|
||||
always_show_commit = options.always_show_commit == nil and false
|
||||
or options.always_show_commit,
|
||||
commit_color = options.commit_color or "bright magenta",
|
||||
commit_symbol = options.commit_symbol == nil and "@"
|
||||
or options.commit_symbol,
|
||||
|
||||
show_behind_ahead_remote = options.show_behind_ahead_remote == nil
|
||||
and true
|
||||
or options.show_behind_ahead_remote,
|
||||
behind_remote_color = options.behind_remote_color or "bright magenta",
|
||||
behind_remote_symbol = options.behind_remote_symbol or "⇣",
|
||||
ahead_remote_color = options.ahead_remote_color or "bright magenta",
|
||||
ahead_remote_symbol = options.ahead_remote_symbol or "⇡",
|
||||
|
||||
show_stashes = options.show_stashes == nil and true
|
||||
or options.show_stashes,
|
||||
stashes_color = options.stashes_color or "bright magenta",
|
||||
stashes_symbol = options.stashes_symbol or "$",
|
||||
|
||||
show_state = options.show_state == nil and true or options.show_state,
|
||||
show_state_prefix = options.show_state_prefix == nil and true
|
||||
or options.show_state_prefix,
|
||||
state_color = options.state_color or "red",
|
||||
state_symbol = options.state_symbol or "~",
|
||||
|
||||
show_staged = options.show_staged == nil and true or options.show_staged,
|
||||
staged_color = options.staged_color or "bright yellow",
|
||||
staged_symbol = options.staged_symbol or "+",
|
||||
|
||||
show_unstaged = options.show_unstaged == nil and true
|
||||
or options.show_unstaged,
|
||||
unstaged_color = options.unstaged_color or "bright yellow",
|
||||
unstaged_symbol = options.unstaged_symbol or "!",
|
||||
|
||||
show_untracked = options.show_untracked == nil and true
|
||||
or options.show_untracked,
|
||||
untracked_color = options.untracked_color or "bright blue",
|
||||
untracked_symbol = options.untracked_symbol or "?",
|
||||
}
|
||||
|
||||
--- @param data GitStatusData
|
||||
function Header:render_branch(data)
|
||||
local branch = data.branch
|
||||
|
||||
if not branch then
|
||||
return nil
|
||||
end
|
||||
|
||||
local left_border = config.branch_borders:sub(1, 1)
|
||||
local right_border = config.branch_borders:sub(2, 2)
|
||||
|
||||
local branch_string = ""
|
||||
|
||||
if config.branch_symbol == "" then
|
||||
branch_string = left_border .. branch .. right_border
|
||||
else
|
||||
branch_string = left_border
|
||||
.. config.branch_symbol
|
||||
.. branch
|
||||
.. right_border
|
||||
end
|
||||
|
||||
local branch_prefix = config.branch_prefix == "" and ""
|
||||
or config.branch_prefix .. " "
|
||||
|
||||
return ui.Line({
|
||||
ui.Span(branch_prefix),
|
||||
ui.Span(branch_string):fg(config.branch_color),
|
||||
})
|
||||
end
|
||||
|
||||
--- @param data GitStatusData
|
||||
function Header:render_remote_branch(data)
|
||||
local branch = data.branch
|
||||
local remote_branch = data.remote_branch
|
||||
local remote_repo = data.remote_repo
|
||||
|
||||
if not remote_branch then
|
||||
return nil
|
||||
end
|
||||
|
||||
local show_remote = config.always_show_remote_branch
|
||||
or branch ~= remote_branch
|
||||
if not show_remote then
|
||||
return nil
|
||||
end
|
||||
|
||||
local remote_branch_label = config.always_show_remote_repo
|
||||
and (remote_repo .. "/" .. remote_branch)
|
||||
or remote_branch
|
||||
|
||||
return ui.Line({
|
||||
ui.Span(config.remote_branch_prefix),
|
||||
ui.Span(remote_branch_label):fg(config.remote_branch_color),
|
||||
})
|
||||
end
|
||||
|
||||
--- @param data GitStatusData
|
||||
function Header:render_tag(data)
|
||||
local branch = data.branch
|
||||
local tag = data.tag
|
||||
|
||||
if not tag then
|
||||
return nil
|
||||
end
|
||||
|
||||
if not branch or config.always_show_tag then
|
||||
return ui.Line({
|
||||
ui.Span(config.tag_symbol),
|
||||
ui.Span(tag):fg(config.tag_color),
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
--- @param data GitStatusData
|
||||
function Header:render_commit(data)
|
||||
local branch = data.branch
|
||||
local tag = data.tag
|
||||
local commit = data.commit
|
||||
|
||||
if not commit then
|
||||
return nil
|
||||
end
|
||||
|
||||
if (not branch and not tag) or config.always_show_commit then
|
||||
return ui.Line({
|
||||
ui.Span(config.commit_symbol),
|
||||
ui.Span(commit):fg(config.commit_color),
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
--- @param data GitStatusData
|
||||
function Header:render_behind_ahead_remote(data)
|
||||
local behind = data.behind_remote
|
||||
local ahead = data.ahead_remote
|
||||
|
||||
local behind_label = behind
|
||||
and behind > 0
|
||||
and ui.Span(
|
||||
config.behind_remote_symbol .. (config.show_numbers and behind or "")
|
||||
):fg(config.behind_remote_color)
|
||||
|
||||
local ahead_label = ahead
|
||||
and ahead > 0
|
||||
and ui.Span(
|
||||
config.ahead_remote_symbol .. (config.show_numbers and ahead or "")
|
||||
):fg(config.ahead_remote_color)
|
||||
|
||||
if ahead_label and behind_label then
|
||||
return ui.Line({
|
||||
behind_label,
|
||||
ahead_label,
|
||||
})
|
||||
elseif ahead_label then
|
||||
return ahead_label
|
||||
elseif behind_label then
|
||||
return behind_label
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
--- @param data GitStatusData
|
||||
function Header:render_stashes(data)
|
||||
local stashes_count = data.stashes
|
||||
|
||||
if not stashes_count then
|
||||
return nil
|
||||
end
|
||||
|
||||
local stashes_label = config.stashes_symbol
|
||||
|
||||
if config.show_numbers then
|
||||
stashes_label = stashes_label .. stashes_count
|
||||
end
|
||||
|
||||
return ui.Span(stashes_label):fg(config.stashes_color)
|
||||
end
|
||||
|
||||
--- @param data GitStatusData
|
||||
function Header:render_state(data)
|
||||
local state_prefix = data.state_prefix
|
||||
local unmerged_count = data.unmerged_count
|
||||
local rebase_done = data.rebase_done
|
||||
local rebase_total = data.rebase_total
|
||||
|
||||
if state_prefix then
|
||||
local state_label = ""
|
||||
if config.show_state_prefix then
|
||||
state_label = state_prefix
|
||||
if
|
||||
state_prefix == "rebase-i"
|
||||
and config.show_numbers
|
||||
and rebase_done
|
||||
and rebase_total
|
||||
then
|
||||
state_label = state_label
|
||||
.. " "
|
||||
.. rebase_done
|
||||
.. "/"
|
||||
.. rebase_total
|
||||
end
|
||||
end
|
||||
|
||||
local unmerged_label = ""
|
||||
local symbol = ""
|
||||
|
||||
if unmerged_count and unmerged_count > 0 then
|
||||
symbol = " " .. config.state_symbol
|
||||
if config.show_numbers then
|
||||
unmerged_label = tostring(unmerged_count)
|
||||
end
|
||||
end
|
||||
|
||||
return ui.Span(state_label .. symbol .. unmerged_label)
|
||||
:fg(config.state_color)
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
--- @param data GitStatusData
|
||||
function Header:render_staged(data)
|
||||
local staged = data.staged
|
||||
|
||||
if staged then
|
||||
local staged_label = config.staged_symbol
|
||||
|
||||
if config.show_numbers then
|
||||
local filtered_staged = staged:gsub("^[%s]*%b()[%s]*", "")
|
||||
|
||||
local staged_count = 0
|
||||
for line in filtered_staged:gmatch("[^\r\n]+") do
|
||||
if line:match("%S") then
|
||||
staged_count = staged_count + 1
|
||||
end
|
||||
end
|
||||
|
||||
staged_label = staged_label .. staged_count
|
||||
end
|
||||
|
||||
return ui.Span(staged_label):fg(config.staged_color)
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- @param data GitStatusData
|
||||
function Header:render_unstaged(data)
|
||||
local unstaged = data.unstaged
|
||||
|
||||
if unstaged then
|
||||
local unstaged_label = config.unstaged_symbol
|
||||
|
||||
if config.show_numbers then
|
||||
local filtered_unstaged =
|
||||
unstaged:gsub("^[%s]*%b()[\r\n]*", ""):gsub("^[%s]*%b()[\r\n]*", "")
|
||||
|
||||
local unstaged_count = 0
|
||||
for line in filtered_unstaged:gmatch("[^\r\n]+") do
|
||||
if line:match("%S") then
|
||||
unstaged_count = unstaged_count + 1
|
||||
end
|
||||
end
|
||||
|
||||
unstaged_label = unstaged_label .. unstaged_count
|
||||
end
|
||||
|
||||
return ui.Span(unstaged_label):fg(config.unstaged_color)
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- @param data GitStatusData
|
||||
function Header:render_untracked(data)
|
||||
local untracked = data.untracked
|
||||
|
||||
if untracked then
|
||||
local untracked_label = config.untracked_symbol
|
||||
|
||||
if config.show_numbers then
|
||||
local filtered_untracked = untracked:gsub("^[%s]*%b()[\r\n]*", "")
|
||||
local untracked_count = 0
|
||||
|
||||
for line in filtered_untracked:gmatch("[^\r\n]+") do
|
||||
if line:match("%S") then
|
||||
untracked_count = untracked_count + 1
|
||||
end
|
||||
end
|
||||
|
||||
untracked_label = untracked_label .. untracked_count
|
||||
end
|
||||
|
||||
return ui.Span(untracked_label):fg(config.untracked_color)
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function Header:githead()
|
||||
--- @type GitStatusData
|
||||
local data = this.output
|
||||
|
||||
if not data then
|
||||
return ui.Line({})
|
||||
end
|
||||
|
||||
local head = {}
|
||||
|
||||
for _, key in ipairs(config.order) do
|
||||
if key == "__spacer__" then
|
||||
if head[#head] ~= " " then
|
||||
table.insert(head, " ")
|
||||
end
|
||||
else
|
||||
local fn = self["render_" .. key]
|
||||
local is_shown = config["show_" .. key]
|
||||
|
||||
if fn and is_shown then
|
||||
local value = fn(self, data)
|
||||
if value then
|
||||
table.insert(head, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return ui.Line(head)
|
||||
end
|
||||
|
||||
Header:children_add(Header.githead, 2000, Header.LEFT)
|
||||
|
||||
local callback = function()
|
||||
local cwd = cx.active.current.cwd
|
||||
ya.emit("plugin", {
|
||||
this._id,
|
||||
ya.quote(tostring(cwd), true),
|
||||
})
|
||||
end
|
||||
|
||||
ps.sub("cd", callback)
|
||||
ps.sub("rename", callback)
|
||||
ps.sub("bulk", callback)
|
||||
ps.sub("move", callback)
|
||||
ps.sub("trash", callback)
|
||||
ps.sub("delete", callback)
|
||||
ps.sub("tab", callback)
|
||||
end,
|
||||
|
||||
entry = function(_, job)
|
||||
local args = job.args or job
|
||||
|
||||
---@class GitStatusData
|
||||
---@field ahead_remote? integer
|
||||
---@field behind_remote? integer
|
||||
---@field branch? string
|
||||
---@field commit? string
|
||||
---@field rebase_done? integer
|
||||
---@field remote_branch? string
|
||||
---@field remote_repo? string
|
||||
---@field staged? string
|
||||
---@field stashes? integer
|
||||
---@field state_prefix? "bisect"|"cherry"|"merge"|"rebase-i"|"revert"
|
||||
---@field tag? string
|
||||
---@field unmerged_count? integer
|
||||
---@field unstaged? string
|
||||
---@field untracked? string
|
||||
local data = {}
|
||||
|
||||
--- @param status string
|
||||
local get_behind_ahead_remote = function(status)
|
||||
local diverged_ahead, diverged_behind =
|
||||
status:match("have (%d+) and (%d+) different")
|
||||
if diverged_ahead and diverged_behind then
|
||||
data.behind_remote = tonumber(diverged_behind)
|
||||
data.ahead_remote = tonumber(diverged_ahead)
|
||||
else
|
||||
local behind_remote = status:match("behind %S+ by (%d+) commits?")
|
||||
local ahead_remote = status:match("ahead of %S+ by (%d+) commits?")
|
||||
|
||||
data.behind_remote = tonumber(behind_remote)
|
||||
data.ahead_remote = tonumber(ahead_remote)
|
||||
end
|
||||
end
|
||||
|
||||
--- @param status string
|
||||
local get_branch = function(status)
|
||||
data.branch = status:match("On branch (%S+)")
|
||||
end
|
||||
|
||||
--- @param status string
|
||||
local get_stashes = function(status)
|
||||
data.stashes = tonumber(status:match("Your stash currently has (%d+)"))
|
||||
end
|
||||
|
||||
--- @param status string
|
||||
local get_state = function(status)
|
||||
local unmerged = status:match("Unmerged paths:%s*(.-)%s*\n\n")
|
||||
if unmerged then
|
||||
local filtered_unmerged =
|
||||
unmerged:gsub("^[%s]*%b()[%s]*", ""):gsub("^[%s]*%b()[%s]*", "")
|
||||
local count = 0
|
||||
for line in filtered_unmerged:gmatch("[^\r\n]+") do
|
||||
if line:match("%S") then
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
data.unmerged_count = count
|
||||
end
|
||||
|
||||
if status:find("git merge") then
|
||||
data.state_prefix = "merge"
|
||||
elseif status:find("git cherry%-pick") then
|
||||
data.state_prefix = "cherry"
|
||||
elseif status:find("git rebase") then
|
||||
data.state_prefix = "rebase-i"
|
||||
local commands_done = status:match("%((%d+) commands? done%)")
|
||||
if commands_done then
|
||||
data.rebase_done = commands_done
|
||||
if not data.unmerged_count then
|
||||
data.rebase_total = commands_done
|
||||
else
|
||||
data.rebase_total = data.unmerged_count
|
||||
end
|
||||
end
|
||||
elseif status:find("git revert") then
|
||||
data.state_prefix = "revert"
|
||||
elseif status:find("git bisect") then
|
||||
data.state_prefix = "bisect"
|
||||
end
|
||||
end
|
||||
|
||||
--- @param status string
|
||||
local get_staged = function(status)
|
||||
data.staged = status:match("Changes to be committed:%s*(.-)%s*\n\n")
|
||||
end
|
||||
|
||||
--- @param status string
|
||||
local get_unstaged = function(status)
|
||||
data.unstaged =
|
||||
status:match("Changes not staged for commit:%s*(.-)%s*\n\n")
|
||||
end
|
||||
|
||||
--- @param status string
|
||||
local get_untracked = function(status)
|
||||
data.untracked = status:match("Untracked files:%s*(.-)%s*\n\n")
|
||||
end
|
||||
|
||||
local get_status = function()
|
||||
local cmd = Command("git")
|
||||
:arg({
|
||||
"status",
|
||||
"--ignore-submodules=dirty",
|
||||
"--branch",
|
||||
"--show-stash",
|
||||
"--ahead-behind",
|
||||
})
|
||||
:cwd(args[1])
|
||||
:env("LANGUAGE", "en_US.UTF-8")
|
||||
:stdout(Command.PIPED)
|
||||
local cmd_output = cmd:output()
|
||||
|
||||
if cmd_output then
|
||||
local status = cmd_output.stdout
|
||||
|
||||
get_branch(status)
|
||||
get_behind_ahead_remote(status)
|
||||
get_stashes(status)
|
||||
get_state(status)
|
||||
get_staged(status)
|
||||
get_unstaged(status)
|
||||
get_untracked(status)
|
||||
end
|
||||
end
|
||||
|
||||
local get_remote_branch = function()
|
||||
local cmd = Command("git")
|
||||
:arg({
|
||||
"rev-parse",
|
||||
"--abbrev-ref",
|
||||
"--symbolic-full-name",
|
||||
"@{upstream}",
|
||||
})
|
||||
:cwd(args[1])
|
||||
:env("LANGUAGE", "en_US.UTF-8")
|
||||
:stdout(Command.PIPED)
|
||||
local cmd_output = cmd:output()
|
||||
|
||||
if cmd_output then
|
||||
local remote_branch = cmd_output.stdout
|
||||
|
||||
data.remote_branch =
|
||||
remote_branch:gsub("[\r\n]", ""):match("^[^/]+/(.+)")
|
||||
data.remote_repo = remote_branch:gsub("[\r\n]", ""):match("^([^/]+)/")
|
||||
end
|
||||
end
|
||||
|
||||
--- @param log string
|
||||
local get_tag = function(log)
|
||||
data.tag = log:match("tag: ([^, )]+)")
|
||||
end
|
||||
|
||||
--- @param log string
|
||||
local get_commit = function(log)
|
||||
data.commit = log:match("^commit%s+([a-f0-9]+)")
|
||||
end
|
||||
|
||||
local get_git_log = function()
|
||||
local cmd = Command("git")
|
||||
:arg({ "log", "--format=commit %h%d", "-n", "1" })
|
||||
:cwd(args[1])
|
||||
:env("LANGUAGE", "en_US.UTF-8")
|
||||
:stdout(Command.PIPED)
|
||||
local cmd_output = cmd:output()
|
||||
|
||||
if cmd_output then
|
||||
local log = cmd_output.stdout
|
||||
|
||||
get_tag(log)
|
||||
get_commit(log)
|
||||
end
|
||||
end
|
||||
|
||||
get_status()
|
||||
get_remote_branch()
|
||||
get_git_log()
|
||||
|
||||
save(args[1], data)
|
||||
end,
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 yazi-rs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,40 @@
|
||||
# smart-enter.yazi
|
||||
|
||||
[`Open`][open] files or [`enter`][enter] directories all in one key!
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
ya pkg add yazi-rs/plugins:smart-enter
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Bind your <kbd>l</kbd> key to the plugin, in your `~/.config/yazi/keymap.toml`:
|
||||
|
||||
```toml
|
||||
[[mgr.prepend_keymap]]
|
||||
on = "l"
|
||||
run = "plugin smart-enter"
|
||||
desc = "Enter the child directory, or open the file"
|
||||
```
|
||||
|
||||
## Advanced
|
||||
|
||||
By default, `--hovered` is passed to the [`open`][open] action, make the behavior consistent with [`enter`][enter] avoiding accidental triggers,
|
||||
which means both will only target the currently hovered file.
|
||||
|
||||
If you still want `open` to target multiple selected files, add this to your `~/.config/yazi/init.lua`:
|
||||
|
||||
```lua
|
||||
require("smart-enter"):setup {
|
||||
open_multi = true,
|
||||
}
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This plugin is MIT-licensed. For more information check the [LICENSE](LICENSE) file.
|
||||
|
||||
[open]: https://yazi-rs.github.io/docs/configuration/keymap/#mgr.open
|
||||
[enter]: https://yazi-rs.github.io/docs/configuration/keymap/#mgr.enter
|
||||
@@ -0,0 +1,11 @@
|
||||
--- @since 25.5.31
|
||||
--- @sync entry
|
||||
|
||||
local function setup(self, opts) self.open_multi = opts.open_multi end
|
||||
|
||||
local function entry(self)
|
||||
local h = cx.active.current.hovered
|
||||
ya.emit(h and h.cha.is_dir and "enter" or "open", { hovered = not self.open_multi })
|
||||
end
|
||||
|
||||
return { entry = entry, setup = setup }
|
||||
@@ -0,0 +1,125 @@
|
||||
# Ember OLED: aligned with Noctalia's "Ember OLED" palette and tmux status line.
|
||||
[flavor]
|
||||
dark = "catppuccin-macchiato"
|
||||
|
||||
[mgr]
|
||||
cwd = { fg = "#ffb05c", bold = true }
|
||||
find_keyword = { fg = "#ffcc99", bold = true, underline = true }
|
||||
find_position = { fg = "#ff8800", bold = true }
|
||||
marker_copied = { fg = "#c98a45", bg = "#c98a45" }
|
||||
marker_cut = { fg = "#ff6b4a", bg = "#ff6b4a" }
|
||||
marker_marked = { fg = "#ff8800", bg = "#ff8800" }
|
||||
marker_selected = { fg = "#ffcc99", bg = "#ffcc99" }
|
||||
count_copied = { fg = "#050403", bg = "#c98a45" }
|
||||
count_cut = { fg = "#050403", bg = "#ff6b4a" }
|
||||
count_selected = { fg = "#050403", bg = "#ffcc99" }
|
||||
border_symbol = "│"
|
||||
border_style = { fg = "#6e4a31" }
|
||||
|
||||
[tabs]
|
||||
active = { fg = "#fff1e6", bg = "#1a110c", bold = true }
|
||||
inactive = { fg = "#f4c7a1", bg = "#050403" }
|
||||
|
||||
[mode]
|
||||
normal_main = { fg = "#050403", bg = "#ff8800", bold = true }
|
||||
normal_alt = { fg = "#ffb05c", bg = "#1a110c" }
|
||||
select_main = { fg = "#050403", bg = "#ffb05c", bold = true }
|
||||
select_alt = { fg = "#ffb05c", bg = "#1a110c" }
|
||||
unset_main = { fg = "#050403", bg = "#ff6b4a", bold = true }
|
||||
unset_alt = { fg = "#ff6b4a", bg = "#1a110c" }
|
||||
|
||||
[status]
|
||||
perm_sep = { fg = "#6e4a31" }
|
||||
perm_type = { fg = "#ffb05c" }
|
||||
perm_read = { fg = "#fff1e6" }
|
||||
perm_write = { fg = "#ff6b4a" }
|
||||
perm_exec = { fg = "#c98a45" }
|
||||
progress_label = { fg = "#fff1e6", bold = true }
|
||||
progress_normal = { fg = "#ff8800", bg = "#1a110c" }
|
||||
progress_error = { fg = "#fff1e6", bg = "#ff6b4a" }
|
||||
|
||||
[pick]
|
||||
border = { fg = "#ff8800" }
|
||||
active = { fg = "#ffb05c", bold = true }
|
||||
|
||||
[input]
|
||||
border = { fg = "#ff8800" }
|
||||
selected = { fg = "#050403", bg = "#ffb05c" }
|
||||
|
||||
[cmp]
|
||||
border = { fg = "#ff8800" }
|
||||
|
||||
[tasks]
|
||||
border = { fg = "#ff8800" }
|
||||
title = { fg = "#fff1e6" }
|
||||
hovered = { fg = "#ffb05c", bold = true }
|
||||
|
||||
[which]
|
||||
border = { fg = "#ff8800" }
|
||||
cand = { fg = "#ffb05c" }
|
||||
rest = { fg = "#f4c7a1" }
|
||||
desc = { fg = "#fff1e6" }
|
||||
separator = " "
|
||||
separator_style = { fg = "#6e4a31" }
|
||||
|
||||
[help]
|
||||
on = { fg = "#ffb05c" }
|
||||
run = { fg = "#fff1e6" }
|
||||
hovered = { fg = "#050403", bg = "#ffb05c", bold = true }
|
||||
footer = { fg = "#fff1e6", bg = "#1a110c" }
|
||||
|
||||
[spot]
|
||||
border = { fg = "#ff8800" }
|
||||
title = { fg = "#ffb05c" }
|
||||
tbl_col = { fg = "#ffb05c" }
|
||||
tbl_cell = { fg = "#fff1e6", bg = "#1a110c" }
|
||||
|
||||
[notify]
|
||||
title_info = { fg = "#c98a45" }
|
||||
title_warn = { fg = "#ffb05c" }
|
||||
title_error = { fg = "#ff6b4a" }
|
||||
|
||||
[filetype]
|
||||
rules = [
|
||||
{ mime = "**/image/*", fg = "#ffcc99" },
|
||||
{ mime = "**/{audio,video}/*", fg = "#c98a45" },
|
||||
{ mime = "**/application/{zip,rar,7z*,tar,gzip,xz,zstd,bzip*,lzma,compress,archive,cpio,arj,xar,ms-cab*}", fg = "#ffb05c" },
|
||||
{ mime = "**/application/{pdf,doc,rtf}", fg = "#f4c7a1" },
|
||||
{ mime = "vfs/{absent,stale}", fg = "#6e4a31" },
|
||||
{ url = "*", fg = "#fff1e6" },
|
||||
{ url = "*/", fg = "#ffb05c" },
|
||||
]
|
||||
|
||||
[icon]
|
||||
dirs = [
|
||||
{ name = ".config", text = "", fg = "#ffb05c" },
|
||||
{ name = ".git", text = "", fg = "#ff8800" },
|
||||
{ name = ".github", text = "", fg = "#ffb05c" },
|
||||
{ name = "Desktop", text = "", fg = "#ffb05c" },
|
||||
{ name = "Documents", text = "", fg = "#ffb05c" },
|
||||
{ name = "Downloads", text = "", fg = "#ffb05c" },
|
||||
{ name = "Pictures", text = "", fg = "#ffcc99" },
|
||||
{ name = "Videos", text = "", fg = "#c98a45" },
|
||||
]
|
||||
conds = [
|
||||
{ if = "orphan", text = "", fg = "#ff6b4a" },
|
||||
{ if = "link", text = "", fg = "#6e4a31" },
|
||||
{ if = "dir & hovered", text = "", fg = "#ffcc99" },
|
||||
{ if = "dir", text = "", fg = "#ffb05c" },
|
||||
{ if = "exec", text = "", fg = "#c98a45" },
|
||||
{ if = "!dir", text = "", fg = "#fff1e6" },
|
||||
]
|
||||
|
||||
[git]
|
||||
modified = { fg = "#ffb05c" }
|
||||
added = { fg = "#c98a45" }
|
||||
untracked = { fg = "#f4c7a1" }
|
||||
deleted = { fg = "#ff6b4a", bold = true }
|
||||
updated = { fg = "#ff8800" }
|
||||
ignored = { fg = "#6e4a31" }
|
||||
modified_sign = "M "
|
||||
added_sign = "A "
|
||||
untracked_sign = "? "
|
||||
deleted_sign = "D "
|
||||
updated_sign = "U "
|
||||
ignored_sign = "I "
|
||||
@@ -0,0 +1,9 @@
|
||||
[[plugin.prepend_fetchers]]
|
||||
url = "*"
|
||||
run = "git"
|
||||
group = "git"
|
||||
|
||||
[[plugin.prepend_fetchers]]
|
||||
url = "*/"
|
||||
run = "git"
|
||||
group = "git"
|
||||
@@ -0,0 +1,59 @@
|
||||
# Local, untracked Noctalia overrides.
|
||||
# This file is loaded after the shared base (10-base.toml) and machine profile
|
||||
# (90-machine.toml). Keep host-only experiments and machine-local adjustments here.
|
||||
#
|
||||
# Example:
|
||||
# [bar.main]
|
||||
# thickness = 32
|
||||
|
||||
[plugins]
|
||||
enabled = [
|
||||
"alex/system-status",
|
||||
"alex/pi-status-bridge",
|
||||
"alex/knowledge-lookup",
|
||||
]
|
||||
|
||||
[widget.pi-status]
|
||||
type = "alex/pi-status-bridge:bridge"
|
||||
|
||||
[widget.knowledge-lookup]
|
||||
type = "alex/knowledge-lookup:bar"
|
||||
|
||||
[bar.main]
|
||||
center = ["pi-status", "knowledge-lookup", "group:g3", "notifications"]
|
||||
end = ["group:g2", "group:g6", "group:g5", "group:g1", "session"]
|
||||
|
||||
# Migrated from Noctalia's GUI-managed state so these host preferences survive
|
||||
# resetting the state override file.
|
||||
[location]
|
||||
address = "Leipzig, Germany"
|
||||
|
||||
[lockscreen_widgets]
|
||||
enabled = false
|
||||
schema_version = 2
|
||||
widget_order = ["lockscreen-login-box@eDP-1"]
|
||||
|
||||
[lockscreen_widgets.grid]
|
||||
cell_size = 16
|
||||
major_interval = 4
|
||||
visible = true
|
||||
|
||||
[lockscreen_widgets.widget."lockscreen-login-box@eDP-1"]
|
||||
box_height = 70.0
|
||||
box_width = 400.0
|
||||
cx = 960.0
|
||||
cy = 1081.0
|
||||
output = "eDP-1"
|
||||
rotation = 0.0
|
||||
type = "login_box"
|
||||
|
||||
[lockscreen_widgets.widget."lockscreen-login-box@eDP-1".settings]
|
||||
background_color = "surface_variant"
|
||||
background_opacity = 0.88
|
||||
background_radius = 12.0
|
||||
center_password_text = false
|
||||
input_opacity = 1.0
|
||||
input_radius = 6.0
|
||||
show_caps_lock = true
|
||||
show_keyboard_layout = true
|
||||
show_login_button = true
|
||||
@@ -0,0 +1,32 @@
|
||||
"""Machine profiles compose concerns; concerns never depend on a host."""
|
||||
|
||||
from modules.host_system import desktop_system, laptop_system
|
||||
from modules.packages import PackageConcern
|
||||
|
||||
COMMON = (
|
||||
"common/core",
|
||||
"common/wayland",
|
||||
"common/fonts",
|
||||
"common/development",
|
||||
"common/productivity",
|
||||
"common/media",
|
||||
"common/research",
|
||||
"common/network",
|
||||
"common/services",
|
||||
)
|
||||
LAPTOP = ("laptop/hardware",)
|
||||
DESKTOP = ()
|
||||
|
||||
|
||||
def _concerns(names: tuple[str, ...]) -> list[PackageConcern]:
|
||||
return [PackageConcern(name) for name in names]
|
||||
|
||||
|
||||
def laptop() -> list:
|
||||
"""Laptop: shared concerns, laptop hardware, and laptop system configuration."""
|
||||
return [*_concerns((*COMMON, *LAPTOP)), *laptop_system()]
|
||||
|
||||
|
||||
def desktop() -> list:
|
||||
"""Future desktop: shared concerns plus desktop-only concerns when declared."""
|
||||
return [*_concerns((*COMMON, *DESKTOP)), *desktop_system()]
|
||||
@@ -0,0 +1,7 @@
|
||||
getty@.service
|
||||
remote-fs.target
|
||||
systemd-resolved-monitor.socket
|
||||
systemd-resolved-varlink.socket
|
||||
systemd-resolved.service
|
||||
systemd-timesyncd.service
|
||||
systemd-userdbd.socket
|
||||
@@ -0,0 +1,6 @@
|
||||
gnome-keyring-daemon.socket
|
||||
p11-kit-server.socket
|
||||
pipewire-pulse.socket
|
||||
pipewire.socket
|
||||
wireplumber.service
|
||||
xdg-user-dirs.service
|
||||
@@ -0,0 +1 @@
|
||||
docker.service
|
||||
@@ -0,0 +1,3 @@
|
||||
idle-inhibitor-monitor.service
|
||||
pi-status-bridge.service
|
||||
ssh-agent.service
|
||||
@@ -0,0 +1,6 @@
|
||||
avahi-daemon.service
|
||||
avahi-daemon.socket
|
||||
avahi-dnsconfd.service
|
||||
cups.path
|
||||
cups.service
|
||||
cups.socket
|
||||
@@ -0,0 +1,3 @@
|
||||
NetworkManager-dispatcher.service
|
||||
NetworkManager-wait-online.service
|
||||
NetworkManager.service
|
||||
@@ -0,0 +1,2 @@
|
||||
mullvad-daemon.service
|
||||
mullvad-early-boot-blocking.service
|
||||
@@ -0,0 +1,6 @@
|
||||
bluetooth.service
|
||||
keyd.service
|
||||
lm_sensors.service
|
||||
thermald.service
|
||||
tlp-pd.service
|
||||
tlp.service
|
||||
@@ -0,0 +1,10 @@
|
||||
# Modules
|
||||
|
||||
Only two adapters belong here:
|
||||
|
||||
- `packages.py` turns package concern lists into Decman package declarations.
|
||||
- `host_system.py` deploys reviewed system policy, user configuration, and enabled units for a host.
|
||||
|
||||
Keep policy in `packages/`, `config/`, and `manifests/`; keep this directory
|
||||
thin and reusable. User configuration belongs under `config/user/{common,laptop,desktop}/`
|
||||
and is installed with owner `alex`.
|
||||
@@ -0,0 +1,238 @@
|
||||
"""System files and concern-scoped unit enablement for machine profiles."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import decman
|
||||
from decman.plugins import systemd
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
MANIFESTS = ROOT / "manifests"
|
||||
|
||||
|
||||
def _units(*names: str) -> set[str]:
|
||||
units: set[str] = set()
|
||||
for name in names:
|
||||
units |= {
|
||||
line.strip()
|
||||
for line in (MANIFESTS / name).read_text(encoding="utf-8").splitlines()
|
||||
if line.strip()
|
||||
}
|
||||
return units
|
||||
|
||||
|
||||
class UserConfigConcern(decman.Module):
|
||||
"""Home-directory configuration owned by a named local user."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
files: dict[str, str] | None = None,
|
||||
directories: dict[str, str] | None = None,
|
||||
user: str = "alex",
|
||||
) -> None:
|
||||
super().__init__(f"user:{name}")
|
||||
self._files = files or {}
|
||||
self._directories = directories or {}
|
||||
self.user = user
|
||||
|
||||
def files(self) -> dict[str, decman.File]:
|
||||
return {
|
||||
target: decman.File(
|
||||
source_file=str(ROOT / source), owner=self.user, permissions=0o644
|
||||
)
|
||||
for target, source in self._files.items()
|
||||
}
|
||||
|
||||
def directories(self) -> dict[str, decman.Directory]:
|
||||
return {
|
||||
target: decman.Directory(
|
||||
source_directory=str(ROOT / source),
|
||||
bin_files=True,
|
||||
owner=self.user,
|
||||
permissions=0o644,
|
||||
)
|
||||
for target, source in self._directories.items()
|
||||
}
|
||||
|
||||
|
||||
class SystemConcern(decman.Module):
|
||||
"""One host/system concern with explicit files and unit manifests."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
files: dict[str, str | tuple[str, int]] | None = None,
|
||||
system_manifests: tuple[str, ...] = (),
|
||||
user_manifests: tuple[str, ...] = (),
|
||||
user: str = "alex",
|
||||
) -> None:
|
||||
super().__init__(f"system:{name}")
|
||||
self._files = files or {}
|
||||
self._system_manifests = system_manifests
|
||||
self._user_manifests = user_manifests
|
||||
self.user = user
|
||||
|
||||
def files(self) -> dict[str, decman.File]:
|
||||
return {
|
||||
target: decman.File(
|
||||
source_file=str(
|
||||
ROOT / (source[0] if isinstance(source, tuple) else source)
|
||||
),
|
||||
permissions=source[1] if isinstance(source, tuple) else 0o644,
|
||||
)
|
||||
for target, source in self._files.items()
|
||||
}
|
||||
|
||||
def on_change(self, store: decman.Store) -> None:
|
||||
if self.name == "system:locale":
|
||||
decman.prg(["locale-gen"])
|
||||
if self.name == "system:boot":
|
||||
decman.prg(["mkinitcpio", "-P"])
|
||||
|
||||
@systemd.units
|
||||
def system_units(self) -> set[str]:
|
||||
return _units(*self._system_manifests)
|
||||
|
||||
@systemd.user_units
|
||||
def user_units(self) -> dict[str, set[str]]:
|
||||
return {self.user: _units(*self._user_manifests)}
|
||||
|
||||
|
||||
def common_user_config() -> list[UserConfigConcern]:
|
||||
return [
|
||||
UserConfigConcern(
|
||||
"common-config",
|
||||
{
|
||||
"/home/alex/.config/environment.d/pi-status-bridge.conf": (
|
||||
"config/user/common/environment.d/pi-status-bridge.conf"
|
||||
),
|
||||
"/home/alex/.config/fish/config.fish": "config/user/common/fish/config.fish",
|
||||
"/home/alex/.config/hypr/hypridle.conf": "config/user/common/hypr/hypridle.conf",
|
||||
"/home/alex/.config/hypr/hyprland.lua": "config/user/common/hypr/hyprland.lua",
|
||||
"/home/alex/.config/hypr/hyprlock.conf": "config/user/common/hypr/hyprlock.conf",
|
||||
"/home/alex/.config/kitty/kitty.conf": "config/user/common/kitty/kitty.conf",
|
||||
"/home/alex/.config/noctalia/10-base.toml": "config/user/common/noctalia/10-base.toml",
|
||||
"/home/alex/.config/noctalia/palettes/Ember OLED.json": (
|
||||
"config/user/common/noctalia/palettes/Ember OLED.json"
|
||||
),
|
||||
"/home/alex/.config/systemd/user/idle-inhibitor-monitor.service": (
|
||||
"config/user/common/systemd/user/idle-inhibitor-monitor.service"
|
||||
),
|
||||
"/home/alex/.config/systemd/user/pi-status-bridge.service": (
|
||||
"config/user/common/systemd/user/pi-status-bridge.service"
|
||||
),
|
||||
"/home/alex/.config/systemd/user/ssh-agent.service": (
|
||||
"config/user/common/systemd/user/ssh-agent.service"
|
||||
),
|
||||
},
|
||||
{"/home/alex/.config/yazi": "config/user/common/yazi"},
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def laptop_user_config() -> list[UserConfigConcern]:
|
||||
return [
|
||||
UserConfigConcern(
|
||||
"laptop-config",
|
||||
{
|
||||
"/home/alex/.config/hypr/machine.lua": "config/user/laptop/hypr/machine.lua",
|
||||
"/home/alex/.config/noctalia/90-machine.toml": (
|
||||
"config/user/laptop/noctalia/90-machine.toml"
|
||||
),
|
||||
"/home/alex/.config/noctalia/99-extend.toml": (
|
||||
"config/user/laptop/noctalia/99-extend.toml"
|
||||
),
|
||||
},
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def desktop_user_config() -> list[UserConfigConcern]:
|
||||
return [
|
||||
UserConfigConcern(
|
||||
"desktop-config",
|
||||
{
|
||||
"/home/alex/.config/hypr/machine.lua": "config/user/desktop/hypr/machine.lua",
|
||||
"/home/alex/.config/noctalia/90-machine.toml": (
|
||||
"config/user/desktop/noctalia/90-machine.toml"
|
||||
),
|
||||
},
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def common_system() -> list[SystemConcern | UserConfigConcern]:
|
||||
return [
|
||||
SystemConcern(
|
||||
"package-policy",
|
||||
{
|
||||
"/etc/pacman.conf": "config/system/common/pacman/pacman.conf",
|
||||
"/etc/makepkg.conf": "config/system/common/makepkg/makepkg.conf",
|
||||
},
|
||||
),
|
||||
SystemConcern(
|
||||
"locale",
|
||||
{
|
||||
"/etc/locale.conf": "config/system/common/locale/locale.conf",
|
||||
"/etc/locale.gen": "config/system/common/locale/locale.gen",
|
||||
},
|
||||
),
|
||||
SystemConcern(
|
||||
"keyboard",
|
||||
{
|
||||
"/etc/vconsole.conf": "config/system/common/keyboard/vconsole.conf",
|
||||
"/etc/X11/xorg.conf.d/00-keyboard.conf": "config/system/common/keyboard/x11.conf",
|
||||
},
|
||||
),
|
||||
SystemConcern("base", system_manifests=("common/base-system.txt",)),
|
||||
SystemConcern("network", system_manifests=("common/network-system.txt",)),
|
||||
SystemConcern("desktop", user_manifests=("common/desktop-user.txt",)),
|
||||
SystemConcern("local", user_manifests=("common/local-user.txt",)),
|
||||
SystemConcern(
|
||||
"network-services", system_manifests=("common/network-services-system.txt",)
|
||||
),
|
||||
SystemConcern(
|
||||
"development", system_manifests=("common/development-system.txt",)
|
||||
),
|
||||
SystemConcern("privacy", system_manifests=("common/privacy-system.txt",)),
|
||||
*common_user_config(),
|
||||
]
|
||||
|
||||
|
||||
def laptop_system() -> list[SystemConcern | UserConfigConcern]:
|
||||
return [
|
||||
*common_system(),
|
||||
SystemConcern(
|
||||
"laptop",
|
||||
{
|
||||
"/etc/keyd/default.conf": "config/system/common/keyd.conf",
|
||||
"/etc/NetworkManager/conf.d/wifi-powersave.conf": "config/system/laptop/wifi-powersave.conf",
|
||||
"/etc/modprobe.d/iwlwifi.conf": "config/system/laptop/iwlwifi.conf",
|
||||
"/etc/X11/xorg.conf.d/30-touchpad.conf": "config/system/laptop/touchpad.conf",
|
||||
"/etc/tlp.conf": "config/system/laptop/power/tlp.conf",
|
||||
"/etc/systemd/sleep.conf.d/90-laptop.conf": "config/system/laptop/sleep.conf.d/90-laptop.conf",
|
||||
"/etc/systemd/logind.conf.d/90-noctalia-battery-idle.conf": "config/system/laptop/systemd/90-noctalia-battery-idle.conf",
|
||||
"/boot/EFI/refind/refind.conf": (
|
||||
"config/system/laptop/refind/refind.conf",
|
||||
0o755,
|
||||
),
|
||||
"/boot/refind_linux.conf": (
|
||||
"config/system/laptop/refind/refind_linux.conf",
|
||||
0o755,
|
||||
),
|
||||
},
|
||||
system_manifests=("laptop/hardware-system.txt",),
|
||||
),
|
||||
SystemConcern(
|
||||
"boot",
|
||||
{"/etc/mkinitcpio.conf": "config/system/laptop/boot/mkinitcpio.conf"},
|
||||
),
|
||||
*laptop_user_config(),
|
||||
]
|
||||
|
||||
|
||||
def desktop_system() -> list[SystemConcern | UserConfigConcern]:
|
||||
"""Desktop: shared policy plus desktop-specific home configuration."""
|
||||
return [*common_system(), *desktop_user_config()]
|
||||
@@ -0,0 +1,43 @@
|
||||
"""Package concern loading for Decman profiles."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import decman
|
||||
from decman.plugins import aur, pacman
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
PACKAGES = ROOT / "packages"
|
||||
|
||||
|
||||
def _names(path: Path) -> set[str]:
|
||||
return {
|
||||
line.strip()
|
||||
for line in path.read_text(encoding="utf-8").splitlines()
|
||||
if line.strip()
|
||||
}
|
||||
|
||||
|
||||
class PackageConcern(decman.Module):
|
||||
"""One named concern backed by native and AUR package lists."""
|
||||
|
||||
def __init__(self, concern: str) -> None:
|
||||
super().__init__(f"packages:{concern}")
|
||||
self.concern = concern
|
||||
|
||||
@pacman.packages
|
||||
def native_packages(self) -> set[str]:
|
||||
return _names(PACKAGES / f"{self.concern}-repo.txt")
|
||||
|
||||
@aur.packages
|
||||
def aur_packages(self) -> set[str]:
|
||||
return _names(PACKAGES / f"{self.concern}-aur.txt")
|
||||
|
||||
|
||||
def configure_no_removal_guard() -> None:
|
||||
"""Keep Decman from pruning current dependency-orphans during adoption."""
|
||||
if decman.pacman is None or decman.aur is None:
|
||||
raise decman.SourceError("pacman and AUR plugins must be available")
|
||||
decman.pacman.ignored_packages |= _names(PACKAGES / "ignored/repo-dependencies.txt")
|
||||
decman.aur.ignored_packages |= _names(PACKAGES / "ignored/aur-dependencies.txt")
|
||||
@@ -0,0 +1,11 @@
|
||||
# Package lists
|
||||
|
||||
Each concern owns package names exactly once:
|
||||
|
||||
- `common/` is portable workstation functionality.
|
||||
- `laptop/` is hardware and power support for this laptop.
|
||||
- `desktop/` is empty until a desktop-specific dependency exists.
|
||||
- `ignored/` contains dependency packages Decman must not prune during adoption.
|
||||
|
||||
A host composes concerns in `../hosts.py`. Add a package to the narrowest
|
||||
concern that explains why it exists, then run `../scripts/verify.py`.
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
7zip
|
||||
arch-install-scripts
|
||||
base
|
||||
base-devel
|
||||
catdoc
|
||||
cowsay
|
||||
cryptsetup
|
||||
dmidecode
|
||||
ex-vi-compat
|
||||
fd
|
||||
fish
|
||||
fwupd
|
||||
fzf
|
||||
git
|
||||
glances
|
||||
htop
|
||||
hunspell-de
|
||||
jq
|
||||
libsmbios
|
||||
linux
|
||||
linux-firmware
|
||||
linux-headers
|
||||
man-db
|
||||
mtools
|
||||
ntfs-3g
|
||||
odt2txt
|
||||
openssh
|
||||
os-prober
|
||||
refind
|
||||
ripgrep
|
||||
rsync
|
||||
starship
|
||||
unzip
|
||||
yadm
|
||||
zoxide
|
||||
zsh
|
||||
@@ -0,0 +1,9 @@
|
||||
decman
|
||||
engram-bin
|
||||
gti
|
||||
mongodb-compass-bin
|
||||
pi
|
||||
postman-bin
|
||||
pycharm
|
||||
vagrant
|
||||
yay
|
||||
@@ -0,0 +1,14 @@
|
||||
cloudflared
|
||||
docker
|
||||
docker-compose
|
||||
fcron
|
||||
jdk-openjdk
|
||||
npm
|
||||
openbsd-netcat
|
||||
podman
|
||||
pyenv
|
||||
python-pip
|
||||
uv
|
||||
virtualbox
|
||||
virtualbox-host-dkms
|
||||
yarn
|
||||
@@ -0,0 +1,2 @@
|
||||
ttf-icomoon-feather
|
||||
ttf-meslo-nerd-font-powerlevel10k
|
||||
@@ -0,0 +1,4 @@
|
||||
noto-fonts
|
||||
noto-fonts-cjk
|
||||
noto-fonts-emoji
|
||||
ttf-jetbrains-mono-nerd
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
audacity
|
||||
cudnn
|
||||
imagemagick
|
||||
smplayer
|
||||
steam
|
||||
vlc
|
||||
@@ -0,0 +1 @@
|
||||
mullvad-vpn-beta-bin
|
||||
@@ -0,0 +1,8 @@
|
||||
avahi
|
||||
cups
|
||||
cups-pdf
|
||||
dhcpcd
|
||||
gvfs-smb
|
||||
network-manager-applet
|
||||
networkmanager
|
||||
nss-mdns
|
||||
@@ -0,0 +1,4 @@
|
||||
brave-bin
|
||||
nomacs
|
||||
spotify
|
||||
zotero-bin
|
||||
@@ -0,0 +1,15 @@
|
||||
bitwarden
|
||||
chromium
|
||||
evince
|
||||
firefox
|
||||
libreoffice-fresh
|
||||
nextcloud-client
|
||||
obsidian
|
||||
okular
|
||||
qalculate-gtk
|
||||
qbittorrent
|
||||
signal-desktop
|
||||
teamspeak3
|
||||
telegram-desktop
|
||||
thunderbird
|
||||
torbrowser-launcher
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
biber
|
||||
r
|
||||
resvg
|
||||
texlive-basic
|
||||
texlive-bibtexextra
|
||||
texlive-binextra
|
||||
texlive-context
|
||||
texlive-fontsextra
|
||||
texlive-fontsrecommended
|
||||
texlive-fontutils
|
||||
texlive-formatsextra
|
||||
texlive-games
|
||||
texlive-humanities
|
||||
texlive-latex
|
||||
texlive-latexextra
|
||||
texlive-latexrecommended
|
||||
texlive-luatex
|
||||
texlive-mathscience
|
||||
texlive-metapost
|
||||
texlive-music
|
||||
texlive-pictures
|
||||
texlive-plaingeneric
|
||||
texlive-pstricks
|
||||
texlive-publishers
|
||||
texlive-xetex
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
libva-utils
|
||||
ly
|
||||
pcmanfm
|
||||
sddm
|
||||
@@ -0,0 +1,2 @@
|
||||
noctalia-git
|
||||
ranger-git
|
||||
@@ -0,0 +1,31 @@
|
||||
alacritty
|
||||
blueman
|
||||
bluez
|
||||
bluez-utils
|
||||
flameshot
|
||||
gnome-keyring
|
||||
grim
|
||||
hypridle
|
||||
hyprland
|
||||
hyprlock
|
||||
kitty
|
||||
mako
|
||||
neovim
|
||||
pamixer
|
||||
pavucontrol
|
||||
pipewire-alsa
|
||||
pipewire-pulse
|
||||
playerctl
|
||||
satty
|
||||
slurp
|
||||
tmux
|
||||
ueberzugpp
|
||||
vim
|
||||
waybar
|
||||
wireplumber
|
||||
wl-clipboard
|
||||
wlr-randr
|
||||
wofi
|
||||
xdg-desktop-portal-hyprland
|
||||
xorg-xwayland
|
||||
yazi
|
||||
@@ -0,0 +1,20 @@
|
||||
accounts-qml-module
|
||||
electron36
|
||||
gti-debug
|
||||
gtk2
|
||||
libmongocrypt-debug
|
||||
light-debug
|
||||
litehtml0.9
|
||||
mbedtls2
|
||||
mongodb-compass-debug
|
||||
mullvad-vpn-beta-bin-debug
|
||||
python-pkg_resources
|
||||
python-pulsectl
|
||||
qtkeychain-qt5
|
||||
teams-debug
|
||||
vagrant-debug
|
||||
way-displays-debug
|
||||
xautolock-debug
|
||||
yay-debug
|
||||
zotero-bin-debug
|
||||
zsh-theme-powerlevel10k-git-debug
|
||||
@@ -0,0 +1,188 @@
|
||||
adobe-source-code-pro-fonts
|
||||
aribb24
|
||||
attica5
|
||||
boost
|
||||
cantarell-fonts
|
||||
clang
|
||||
cmake
|
||||
compiler-rt
|
||||
cppdap
|
||||
cython
|
||||
doxygen
|
||||
extra-cmake-modules
|
||||
ffmpeg4.4
|
||||
git-lfs
|
||||
go
|
||||
gperf
|
||||
ibus
|
||||
imake
|
||||
karchive5
|
||||
kauth
|
||||
kauth5
|
||||
kbookmarks5
|
||||
kcodecs5
|
||||
kcompletion5
|
||||
kconfig5
|
||||
kconfigwidgets5
|
||||
kcoreaddons5
|
||||
kcrash5
|
||||
kdbusaddons5
|
||||
kdeclarative5
|
||||
kded5
|
||||
kglobalaccel5
|
||||
kguiaddons5
|
||||
ki18n5
|
||||
kiconthemes5
|
||||
kio5
|
||||
kirigami2
|
||||
kitemviews5
|
||||
kjobwidgets5
|
||||
knewstuff5
|
||||
knotifications5
|
||||
kpackage5
|
||||
kpty
|
||||
kservice5
|
||||
ktextwidgets5
|
||||
kwallet5
|
||||
kwidgetsaddons5
|
||||
kwindowsystem5
|
||||
kxmlgui5
|
||||
lib32-audit
|
||||
lib32-harfbuzz
|
||||
lib32-libcap
|
||||
lib32-libnsl
|
||||
lib32-libtirpc
|
||||
lib32-pam
|
||||
libcamera
|
||||
libcamera-ipa
|
||||
libdbusmenu-qt5
|
||||
libdca
|
||||
libdispatch
|
||||
libdvbpsi
|
||||
libgit2
|
||||
libibus
|
||||
libindicator
|
||||
libjcat
|
||||
libmad
|
||||
libmfx
|
||||
libmpcdec
|
||||
libmpeg2
|
||||
libomxil-bellagio
|
||||
libtar
|
||||
libupnp
|
||||
libxdg-basedir
|
||||
libxres
|
||||
lld
|
||||
llhttp
|
||||
meson
|
||||
minizip-ng
|
||||
ninja
|
||||
nlohmann-json
|
||||
nvm
|
||||
perl-sub-identify
|
||||
plasma-activities
|
||||
polkit-qt5
|
||||
polkit-qt6
|
||||
python-babel
|
||||
python-build
|
||||
python-chardet
|
||||
python-dbus
|
||||
python-docopt
|
||||
python-docutils
|
||||
python-fastjsonschema
|
||||
python-html5lib
|
||||
python-imagesize
|
||||
python-inflect
|
||||
python-iniconfig
|
||||
python-installer
|
||||
python-jaraco.collections
|
||||
python-numpy
|
||||
python-ordered-set
|
||||
python-pillow
|
||||
python-pluggy
|
||||
python-pygments
|
||||
python-pyproject-hooks
|
||||
python-pyqt5
|
||||
python-pyqt5-sip
|
||||
python-pyqt6
|
||||
python-pyqt6-sip
|
||||
python-pytest
|
||||
python-pytest-mock
|
||||
python-pytz
|
||||
python-pyxdg
|
||||
python-roman-numerals-py
|
||||
python-setproctitle
|
||||
python-setuptools
|
||||
python-snowballstemmer
|
||||
python-sphinx
|
||||
python-sphinx-alabaster-theme
|
||||
python-sphinxcontrib-applehelp
|
||||
python-sphinxcontrib-devhelp
|
||||
python-sphinxcontrib-htmlhelp
|
||||
python-sphinxcontrib-jsmath
|
||||
python-sphinxcontrib-qthelp
|
||||
python-sphinxcontrib-serializinghtml
|
||||
python-tomli
|
||||
python-tqdm
|
||||
python-trove-classifiers
|
||||
python-typeguard
|
||||
python-validate-pyproject
|
||||
python-webencodings
|
||||
qca-qt5
|
||||
qt5-graphicaleffects
|
||||
qt5-multimedia
|
||||
qt5-quickcontrols
|
||||
qt5-quickcontrols2
|
||||
qt5-speech
|
||||
qt5-tools
|
||||
qt6-doc
|
||||
rapidjson
|
||||
rhash
|
||||
rtkit
|
||||
ruby-abbrev
|
||||
ruby-base64
|
||||
ruby-bigdecimal
|
||||
ruby-bundled-gems
|
||||
ruby-bundler
|
||||
ruby-csv
|
||||
ruby-debug
|
||||
ruby-default-gems
|
||||
ruby-drb
|
||||
ruby-erb
|
||||
ruby-getoptlong
|
||||
ruby-irb
|
||||
ruby-matrix
|
||||
ruby-minitest
|
||||
ruby-mutex_m
|
||||
ruby-net-ftp
|
||||
ruby-net-imap
|
||||
ruby-net-pop
|
||||
ruby-net-smtp
|
||||
ruby-nkf
|
||||
ruby-observer
|
||||
ruby-power_assert
|
||||
ruby-prime
|
||||
ruby-racc
|
||||
ruby-rake
|
||||
ruby-rbs
|
||||
ruby-rdoc
|
||||
ruby-repl_type_completor
|
||||
ruby-resolv-replace
|
||||
ruby-rexml
|
||||
ruby-rinda
|
||||
ruby-rss
|
||||
ruby-stdlib
|
||||
ruby-syslog
|
||||
ruby-test-unit
|
||||
ruby-typeprof
|
||||
rust
|
||||
scdoc
|
||||
solid5
|
||||
sonnet5
|
||||
stb
|
||||
syndication5
|
||||
tree-sitter-bash
|
||||
tree-sitter-python
|
||||
vte-common
|
||||
vulkan-headers
|
||||
xorg-xset
|
||||
@@ -0,0 +1,4 @@
|
||||
caffeine
|
||||
envycontrol
|
||||
light
|
||||
woeusb
|
||||
@@ -0,0 +1,19 @@
|
||||
ddcutil
|
||||
intel-gpu-tools
|
||||
intel-media-driver
|
||||
intel-ucode
|
||||
keyd
|
||||
mesa-utils
|
||||
nvidia-open
|
||||
nvidia-prime
|
||||
nvtop
|
||||
nwg-displays
|
||||
powertop
|
||||
psensor
|
||||
thermald
|
||||
tlp
|
||||
tlp-pd
|
||||
tlp-rdw
|
||||
vulkan-intel
|
||||
vulkan-tools
|
||||
wireless_tools
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"include": ["source.py", "hosts.py", "modules", "scripts"],
|
||||
"executionEnvironments": [{ "root": ".", "extraPaths": ["."] }]
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Refresh dependency packages that Decman must ignore to guarantee no removal."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import pyalpm
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
OUTPUT = ROOT / "packages" / "ignored"
|
||||
|
||||
|
||||
def repository_names(handle: pyalpm.Handle) -> set[str]:
|
||||
return {
|
||||
package.name
|
||||
for database in handle.get_syncdbs()
|
||||
for package in database.pkgcache
|
||||
}
|
||||
|
||||
|
||||
def deep_orphans(handle: pyalpm.Handle, predicate) -> set[str]:
|
||||
local = {package.name: package for package in handle.get_localdb().pkgcache}
|
||||
candidates = {
|
||||
package.name
|
||||
for package in local.values()
|
||||
if package.reason == pyalpm.PKG_REASON_DEPEND and predicate(package.name)
|
||||
}
|
||||
while True:
|
||||
retained = {
|
||||
name
|
||||
for name in candidates
|
||||
if not (set(local[name].compute_requiredby()) - candidates)
|
||||
}
|
||||
if retained == candidates:
|
||||
return retained
|
||||
candidates = retained
|
||||
|
||||
|
||||
def write(name: str, values: set[str]) -> None:
|
||||
(OUTPUT / name).write_text("\n".join(sorted(values)) + "\n", encoding="utf-8")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
handle = pyalpm.Handle("/", "/var/lib/pacman")
|
||||
repositories = subprocess.run(
|
||||
["pacman-conf", "--repo-list"], check=True, text=True, stdout=subprocess.PIPE
|
||||
).stdout.split()
|
||||
for repository in repositories:
|
||||
handle.register_syncdb(repository, 0)
|
||||
native = repository_names(handle)
|
||||
write("repo-dependencies.txt", deep_orphans(handle, lambda name: name in native))
|
||||
write("aur-dependencies.txt", deep_orphans(handle, lambda name: name not in native))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+90
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate disjoint, concern-scoped package lists from the current machine."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Final
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
PACKAGES = ROOT / "packages"
|
||||
|
||||
# A concern is reusable; a machine profile composes concerns elsewhere.
|
||||
# Every installed explicit package must be assigned exactly once on this laptop.
|
||||
CONCERNS: Final = {
|
||||
"common/core": """base base-devel linux linux-firmware linux-headers cryptsetup refind
|
||||
arch-install-scripts git yadm openssh man-db jq ripgrep fd fzf 7zip unzip rsync
|
||||
ntfs-3g os-prober fwupd fish zsh zoxide htop glances starship cowsay ex-vi-compat
|
||||
mtools dmidecode libsmbios catdoc odt2txt hunspell-de""",
|
||||
"common/wayland": """hyprland hypridle hyprlock xdg-desktop-portal-hyprland
|
||||
pipewire-alsa pipewire-pulse wireplumber pavucontrol pamixer mako waybar wofi grim
|
||||
slurp satty wl-clipboard wlr-randr alacritty kitty tmux neovim vim yazi ueberzugpp
|
||||
flameshot playerctl bluez bluez-utils blueman gnome-keyring xorg-xwayland
|
||||
noctalia-git ranger-git""",
|
||||
"common/fonts": """noto-fonts noto-fonts-cjk noto-fonts-emoji ttf-jetbrains-mono-nerd
|
||||
ttf-icomoon-feather ttf-meslo-nerd-font-powerlevel10k""",
|
||||
"common/development": """nodejs npm yarn python python-pip pyenv uv rust cargo go ruby
|
||||
jdk-openjdk docker docker-compose podman vagrant virtualbox virtualbox-host-dkms
|
||||
cloudflared openbsd-netcat pycharm postman-bin mongodb-compass-bin pi engram-bin
|
||||
decman yay gti fcron""",
|
||||
"common/productivity": """brave-bin firefox chromium thunderbird obsidian bitwarden
|
||||
nextcloud-client signal-desktop telegram-desktop libreoffice-fresh evince okular
|
||||
nomacs zotero-bin qalculate-gtk qbittorrent teams teamspeak3 cerebro-bin chatgtk
|
||||
torbrowser-launcher spotify""",
|
||||
"common/media": """vlc mpv smplayer audacity imagemagick steam cudnn""",
|
||||
"common/research": """biber r texlive-basic texlive-bibtexextra texlive-binextra
|
||||
texlive-context texlive-fontsextra texlive-fontsrecommended texlive-fontutils
|
||||
texlive-formatsextra texlive-games texlive-humanities texlive-latex texlive-latexextra
|
||||
texlive-latexrecommended texlive-luatex texlive-mathscience texlive-metapost
|
||||
texlive-music texlive-pictures texlive-plaingeneric texlive-pstricks texlive-publishers
|
||||
texlive-xetex resvg""",
|
||||
"common/network": """networkmanager network-manager-applet avahi nss-mdns dhcpcd gvfs-smb
|
||||
cups cups-pdf mullvad-vpn-beta-bin""",
|
||||
"laptop/hardware": """intel-ucode thermald tlp tlp-pd tlp-rdw powertop psensor lm_sensors
|
||||
ddcutil intel-gpu-tools intel-media-driver mesa-utils vulkan-intel vulkan-tools
|
||||
nvidia-open nvidia-prime nvtop envycontrol light keyd nwg-displays
|
||||
wireless_tools caffeine woeusb""",
|
||||
"common/services": """sddm ly pcmanfm libva-utils""",
|
||||
}
|
||||
|
||||
|
||||
def explicit(command: str) -> set[str]:
|
||||
return set(
|
||||
subprocess.run(
|
||||
["pacman", command], check=True, text=True, stdout=subprocess.PIPE
|
||||
).stdout.split()
|
||||
)
|
||||
|
||||
|
||||
def write(path: Path, values: set[str]) -> None:
|
||||
resolved = path.resolve()
|
||||
package_root = PACKAGES.resolve()
|
||||
if package_root not in resolved.parents:
|
||||
raise ValueError(f"refusing to write outside packages: {path}")
|
||||
resolved.parent.mkdir(parents=True, exist_ok=True)
|
||||
resolved.write_text("\n".join(sorted(values)) + "\n", encoding="utf-8")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
official, aur = explicit("-Qqen"), explicit("-Qqem")
|
||||
assigned: set[str] = set()
|
||||
for name, raw in CONCERNS.items():
|
||||
selected = set(raw.split()) & (official | aur)
|
||||
overlap = selected & assigned
|
||||
if overlap:
|
||||
raise SystemExit(f"duplicate ownership in {name}: {sorted(overlap)}")
|
||||
assigned |= selected
|
||||
write(PACKAGES / f"{name}-repo.txt", selected & official)
|
||||
write(PACKAGES / f"{name}-aur.txt", selected & aur)
|
||||
remaining = (official | aur) - assigned
|
||||
if remaining:
|
||||
raise SystemExit(
|
||||
"unclassified explicit packages; add them to a named concern: "
|
||||
+ ", ".join(sorted(remaining))
|
||||
)
|
||||
print(f"assigned={len(assigned)}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+92
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Read-only invariant checks for the active Decman configuration."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import runpy
|
||||
import subprocess
|
||||
import sys
|
||||
from collections import Counter
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
from typing import cast
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
PACKAGES = ROOT / "packages"
|
||||
|
||||
|
||||
def lines(path: Path) -> set[str]:
|
||||
return {
|
||||
line.strip()
|
||||
for line in path.read_text(encoding="utf-8").splitlines()
|
||||
if line.strip()
|
||||
}
|
||||
|
||||
|
||||
def actual(command: str) -> set[str]:
|
||||
return set(
|
||||
subprocess.run(
|
||||
["pacman", command], check=True, text=True, stdout=subprocess.PIPE
|
||||
).stdout.split()
|
||||
)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
repo_files = list(PACKAGES.glob("**/*-repo.txt"))
|
||||
aur_files = list(PACKAGES.glob("**/*-aur.txt"))
|
||||
repo = [name for path in repo_files for name in lines(path)]
|
||||
aur = [name for path in aur_files for name in lines(path)]
|
||||
duplicate = {name for name, count in Counter(repo + aur).items() if count > 1}
|
||||
if duplicate:
|
||||
raise SystemExit(f"duplicate package ownership: {sorted(duplicate)}")
|
||||
installed_repo = actual("-Qqen")
|
||||
installed_aur = actual("-Qqem")
|
||||
|
||||
os.chdir(ROOT)
|
||||
sys.path.insert(0, str(ROOT))
|
||||
import decman
|
||||
|
||||
runpy.run_path(str(ROOT / "source.py"))
|
||||
loaded_repo: set[str] = set()
|
||||
loaded_aur: set[str] = set()
|
||||
for module in decman.modules:
|
||||
native = getattr(module, "native_packages", None)
|
||||
foreign = getattr(module, "aur_packages", None)
|
||||
if callable(native):
|
||||
loaded_repo |= cast(Callable[[], set[str]], native)()
|
||||
if callable(foreign):
|
||||
loaded_aur |= cast(Callable[[], set[str]], foreign)()
|
||||
if loaded_repo != set(repo) or loaded_aur != set(aur):
|
||||
raise SystemExit("active profile does not compose the full laptop package set")
|
||||
expected_system = set().union(
|
||||
*(lines(path) for path in (ROOT / "manifests").glob("**/*-system.txt"))
|
||||
)
|
||||
expected_user = set().union(
|
||||
*(lines(path) for path in (ROOT / "manifests").glob("**/*-user.txt"))
|
||||
)
|
||||
loaded_system: set[str] = set()
|
||||
loaded_user: set[str] = set()
|
||||
for module in decman.modules:
|
||||
system = getattr(module, "system_units", None)
|
||||
user = getattr(module, "user_units", None)
|
||||
if callable(system):
|
||||
loaded_system |= cast(Callable[[], set[str]], system)()
|
||||
if callable(user):
|
||||
loaded_user |= cast(Callable[[], dict[str, set[str]]], user)().get(
|
||||
"alex", set()
|
||||
)
|
||||
if loaded_system != expected_system or loaded_user != expected_user:
|
||||
raise SystemExit("active profile does not compose the complete unit manifests")
|
||||
pending_remove = sorted((installed_repo - set(repo)) | (installed_aur - set(aur)))
|
||||
pending_install = sorted((set(repo) - installed_repo) | (set(aur) - installed_aur))
|
||||
print(
|
||||
f"OK: repo={len(repo)} aur={len(aur)} system={len(loaded_system)} "
|
||||
f"user={len(loaded_user)} concerns={len(repo_files)} profile=laptop"
|
||||
)
|
||||
print(f"PENDING REMOVE: {' '.join(pending_remove) or 'none'}")
|
||||
print(f"PENDING INSTALL: {' '.join(pending_install) or 'none'}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,14 @@
|
||||
"""Decman entrypoint for this machine.
|
||||
|
||||
Select one profile only. The package lists describe the complete current laptop
|
||||
state, so the first Decman run must not remove a package.
|
||||
"""
|
||||
|
||||
import decman
|
||||
|
||||
from modules.packages import configure_no_removal_guard
|
||||
from hosts import laptop
|
||||
|
||||
configure_no_removal_guard()
|
||||
decman.modules += laptop()
|
||||
decman.execution_order = ["files", "pacman", "aur", "systemd"]
|
||||
Reference in New Issue
Block a user