Compare commits

...

4 commits

Author SHA1 Message Date
0a6281b543
install.sh: quitar los enlaces a archivos borrados del repo
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C5v1qWDwgkaVM5kjVHGGh8
2026-09-28 12:18:28 +02:00
1f4a6a8803
turnstile en vez de elogind
turnstile solo crea XDG_RUNTIME_DIR (backend none, sin exportar el bus de
D-Bus, que lo abre .xinitrc). Xorg ya arranca como root con Xorg.wrap y la
tapa y los botones los lleva acpid, así que elogind sobraba. Fuera su
logind.conf.d.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C5v1qWDwgkaVM5kjVHGGh8
2026-09-28 12:15:50 +02:00
9f3863ac33
wpa_supplicant y dhcpcd en vez de NetworkManager; fuera polkitd y rtkit
- wifi: menú de dmenu con wpa_cli (buscar, conectar y guardar redes).
- install.sh prepara wpa_supplicant.conf para wpa_cli sin root (wheel).
- polkitd ya no es un servicio: D-Bus lo arranca si algo lo pide.
- Audio en tiempo real con el grupo _pipewire en vez de rtkit.
- Clic derecho en la red: wpa_cli en una st flotante.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C5v1qWDwgkaVM5kjVHGGh8
2026-09-28 12:14:24 +02:00
a83294ace4
doas, pinentry-dmenu y scripts en vez de blueman, autorandr y gammastep
- doas en vez de sudo (sistema/etc/doas.conf; xbps.d permite quitar sudo).
- pinentry-dmenu en X y pinentry-curses en una tty (pinentry-menu); fuera
  GTK 2 (.gtkrc-2.0 y el arreglo de colores del tema).
- bluetooth: menú de dmenu con bluetoothctl en vez de blueman.
- pantallas: xrandr a pelo en vez de autorandr, también desde udev.
- luz: sct cada minuto en vez de gammastep.
- xwallpaper para el fondo y nsxiv para las imágenes de st, en vez de feh.
- volumen salida en vez de pavucontrol; menu reúne los colores de dmenu.
- mpv en vez de vlc; fuera btop.
- install.sh: paso quitar para desinstalar lo sustituido.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C5v1qWDwgkaVM5kjVHGGh8
2026-09-28 12:12:51 +02:00
26 changed files with 550 additions and 461 deletions

View file

@ -16,54 +16,85 @@ real names you type; this README explains what each one does.
|---|---|
| `suckless/` | The programs, each with its own `config.h` and patches |
| `home/` | Files that go in `~`, at the same path (they are symlinked) |
| `sistema/` | Files that go in `/` (acpid, zzz, elogind, udev, sudoers, runit) |
| `sistema/` | Files that go in `/` (acpid, zzz, turnstile, udev, doas, xbps, runit) |
| `install.sh` | Installs everything on a fresh Void system |
## Install
On a fresh Void install, as your normal user (it asks for sudo when needed):
On a fresh Void install, as your normal user (it asks for the root
password when needed: through sudo until doas is ready, then through doas):
git clone ssh://forgejo@ssh.alejandrogs.es/alejandrogs73/suckless.git ~/suckless
cd ~/suckless && ./install.sh
It runs six steps, which can also be run on their own (`./install.sh enlaces`,
It runs seven steps, which can also be run on their own (`./install.sh enlaces`,
for example) and repeated safely:
1. `paquetes` (packages): installs with xbps everything the setup uses.
2. `suckless`: builds the programs and installs them in `/usr/local`.
3. `enlaces` (links): symlinks every file in `home/` into `~`. If a different
file was already there, it is kept as `.bak`. Since they are symlinks,
editing `~/.bashrc` edits the repo. It also creates the user folders and
editing `~/.bashrc` edits the repo. Links to files deleted from the repo
are removed. It also creates the user folders and
sets `~/.ssh` to 700.
4. `gtk`: builds the [Everforest GTK](https://github.com/Fausto-Korpsvart/Everforest-GTK-Theme)
theme (green, dark, medium palette) in `~/.themes` from a pinned commit,
and links it for GTK 4 apps. It fixes the colours of the GTK 2 part (the
theme ships Gruvbox ones) and makes the Papirus folders green. Icons are
links it for GTK 4 apps and makes the Papirus folders green. Icons are
Papirus-Dark everywhere. Qt 5 and Qt 6 apps use qt5ct/qt6ct
(`QT_QPA_PLATFORMTHEME` in `.xinitrc`) with the Fusion style and an
Everforest palette (`home/.config/qt*ct/`). If a `papirus-icon-theme`
update turns the folders blue again, just run this step again.
5. `gnupg`: for after copying `~/.gnupg` by hand (from a USB stick, for
example). It fixes the permissions, sets `pinentry-gtk` (falls back to
curses on a tty), enables gpg's SSH agent, adds the authentication subkeys
example). It fixes the permissions, sets `pinentry-dmenu` with the dmenu
colours (`pinentry-curses` on a tty: `home/.local/bin/pinentry-menu`
picks one), enables gpg's SSH agent, adds the authentication subkeys
to `sshcontrol` and caches the passphrase for one hour. `.bashrc` already
points `SSH_AUTH_SOCK` at the agent. If `~/.gnupg` does not exist yet, it
does nothing.
6. `sistema` (system): copies `sistema/` into `/`, enables the runit services
(dbus, elogind, polkitd, NetworkManager, bluetoothd, acpid, chronyd, tlp,
automontaje, cupsd), removes dhcpcd and wpa_supplicant (NetworkManager
already manages the network) and adds the user to the audio, video, input,
network, bluetooth and lpadmin (printer management) groups. Files in
`sudoers.d` are checked with `visudo` and installed with mode 440.
6. `sistema` (system): copies `sistema/` into `/`, sets up
`wpa_supplicant.conf` so wheel users can use `wpa_cli` without root and
save networks, enables the runit services (dbus, turnstiled,
wpa_supplicant, dhcpcd, bluetoothd, acpid, chronyd, tlp, automontaje,
cupsd), removes NetworkManager, elogind and polkitd (if something asks for
polkit, like udisks2 or libvirt, D-Bus starts it on its own) and adds the
user to the audio, video, input, network, bluetooth, lpadmin (printer
management) and `_pipewire` (realtime priority for audio without rtkit)
groups. `doas.conf` is checked with `doas -C` before it is installed with
mode 400.
7. `quitar` (remove): uninstalls what the repo no longer uses because
something else replaces it: sudo (doas), feh (xwallpaper and nsxiv),
gammastep (sct), autorandr (`pantallas`), blueman and pavucontrol (the
`bluetooth` and `volumen` scripts), pinentry-gtk (pinentry-dmenu), vlc
(mpv), btop, NetworkManager and tlp-rdw (wpa_supplicant, dhcpcd and the
`wifi` script), rtkit and elogind (turnstile). sudo can be removed thanks
to `sistema/etc/xbps.d/sin-sudo.conf` (base-system depends on it), and it
is only removed once `/etc/doas.conf` is installed.
Afterwards, log out and back in (for the groups) and run `startx`.
Nix is not installed: the little that comes from it (webcord) is installed by
hand.
## Without elogind
elogind is systemd's logind on its own, and it is not needed here:
- `XDG_RUNTIME_DIR` (`/run/user/UID`) is created by turnstile at login
(`sistema/etc/turnstile/turnstiled.conf`: only that, no user services).
- Xorg runs as root through `Xorg.wrap` (`needs_root_rights = yes` in
`/etc/X11/Xwrapper.config`, shipped by Void).
- The lid and the power and suspend buttons are handled by acpid, which
calls `zzz`. Power off and reboot are runit's.
- Devices (sound, video, input, bluetooth) are reached through the user's
groups, not through the ACLs elogind gave the active session.
What stops working: mounting disks from a file manager (udisks2 asks polkit
for an active session, and there is none). USB sticks are mounted by
`automontaje`.
## Rebuilding after changing the config
cd suckless/dwm && make && sudo make install
cd suckless/dwm && make && doas make install
## Updating from upstream
@ -110,6 +141,18 @@ The audio keys (and clicks on VOL in the bar) use the `volumen` script
(`home/.local/bin/volumen`): it changes the volume with `wpctl`, refreshes
slstatus and shows a notification with the level.
The script menus (`apagado`, `bluetooth`, `volumen salida`...) use `menu`,
which is dmenu with the dwm font and colours.
### Bar clicks
| Area | Left | Middle | Right | Wheel |
|---|---|---|---|---|
| Network | Connect to a network (`wifi`) | | `wpa_cli` | |
| VOL | Pick the audio output (`volumen salida`) | Mute | Mute the mic | Volume ± |
| BT | Bluetooth menu (`bluetooth`): connect, disconnect, scan and pair, power off | | Power on or off | |
| Date | This month's calendar | | | |
Screenshots are saved in `~/Images/Screenshots`, copied to the clipboard and
shown in a notification.
@ -117,13 +160,19 @@ shown in a notification.
- Logging in on tty1 starts `startx` automatically (`.bash_profile`); other
ttys do not.
- `.xinitrc` also starts `gammastep` (warm light from 20:00 to 8:00, with a
one-hour transition) and `bateria` (warns at 15 % and, in red, at 5 %; at
3 % it suspends with `sudo -n zzz`). Suspend, power off and reboot need no
password (`sistema/etc/sudoers.d/energia`).
- Screens: `autorandr` lines them up (the laptop one on the left and as
primary) at startup and whenever one is plugged or unplugged (udev rule in
`sistema/`), then repaints the wallpaper.
- `.xinitrc` also starts `luz` (warm light with `sct` from 20:00 to 8:00,
with a one-hour transition) and `bateria` (warns at 15 % and, in red, at
5 %; at 3 % it suspends with `doas -n zzz`). Suspend, power off and reboot
need no password (`sistema/etc/doas.conf`).
- Screens: `pantallas` (`sistema/usr/local/bin`) lines them up with `xrandr`
(the laptop one on the left and as primary) at startup and whenever one is
plugged or unplugged (udev rule in `sistema/`), then repaints the
wallpaper with `xwallpaper`.
- WiFi: `wifi` scans with `wpa_cli` and lists the networks in dmenu by
signal (`*` is the current one). For a new network it asks for the
password (hidden while typing) and saves it in
`/etc/wpa_supplicant/wpa_supplicant.conf` only if the connection works.
dhcpcd handles the cable on its own.
- Left click on the date in the bar: this month's calendar in a notification
(`calendario`), with today in green.
- bash: 10 000-entry history, without duplicates and shared between
@ -145,7 +194,7 @@ shown in a notification.
them in `/mnt/LABEL`, or `/mnt/sdXY` if they have no label, and unmounts
them when removed, with a notification. FAT, exFAT and NTFS are owned by
the user; internal disks are never touched. Before pulling a stick you
wrote to, run `sync` (or `sudo umount /mnt/...`).
wrote to, run `sync` (or `doas umount /mnt/...`).
- User folders in English and without accents (`user-dirs.dirs`):
Documents, Downloads and Images.
@ -163,6 +212,7 @@ shown in a notification.
the combination with ligatures come from the `graphics-with-patches`
branch of [st-graphics](https://github.com/sergei-grechanik/st-graphics),
without boxdraw.
- In st, Ctrl+Shift+right click on an image opens it in `nsxiv`.
- st shows images with the kitty graphics protocol; yazi detects it on its
own and shows previews without ueberzugpp.
- slock is modified by hand (not a patch): clock, date, battery and a bottom

View file

@ -12,55 +12,86 @@ Tema Everforest y fuente Fira Code en todos.
|---|---|
| `suckless/` | Los programas, cada uno con su `config.h` y sus parches |
| `home/` | Archivos que van en `~`, con la misma ruta (se enlazan) |
| `sistema/` | Archivos que van en `/` (acpid, zzz, elogind, udev, sudoers, runit) |
| `sistema/` | Archivos que van en `/` (acpid, zzz, turnstile, udev, doas, xbps, runit) |
| `install.sh` | Lo instala todo en un Void recién instalado |
## Instalar
En un Void recién instalado, como tu usuario (pide sudo cuando hace falta):
En un Void recién instalado, como tu usuario (pide la contraseña de root
cuando hace falta: con sudo hasta que doas está listo, luego con doas):
git clone ssh://forgejo@ssh.alejandrogs.es/alejandrogs73/suckless.git ~/suckless
cd ~/suckless && ./install.sh
Hace seis pasos, que también se pueden lanzar por separado
Hace siete pasos, que también se pueden lanzar por separado
(`./install.sh enlaces`, por ejemplo) y repetir sin problema:
1. `paquetes`: instala con xbps todo lo que usa la configuración.
2. `suckless`: compila e instala los programas en `/usr/local`.
3. `enlaces`: enlaza cada archivo de `home/` en `~`. Si ya existía un archivo
distinto, lo guarda como `.bak`. Como son enlaces, editar `~/.bashrc` es
editar el repo. También crea las carpetas del usuario y deja `~/.ssh` en
editar el repo. Los enlaces a archivos que se han borrado del repo se
quitan. También crea las carpetas del usuario y deja `~/.ssh` en
700.
4. `gtk`: compila el tema [Everforest GTK](https://github.com/Fausto-Korpsvart/Everforest-GTK-Theme)
(verde, oscuro, paleta medium) en `~/.themes`, en una versión fija, y lo
enlaza para las apps de GTK 4. Corrige los colores de la parte de GTK 2
(el tema trae los de Gruvbox) y pone verdes las carpetas de Papirus. Los
enlaza para las apps de GTK 4, y pone verdes las carpetas de Papirus. Los
iconos son Papirus-Dark en todo. Las apps Qt 5 y Qt 6 usan qt5ct/qt6ct
(`QT_QPA_PLATFORMTHEME` en `.xinitrc`) con el estilo Fusion y una paleta
Everforest (`home/.config/qt*ct/`). Si una actualización de
`papirus-icon-theme` devuelve las carpetas a azul, basta con repetir este
paso.
5. `gnupg`: para después de copiar `~/.gnupg` a mano (de un USB, por
ejemplo). Arregla los permisos, pone `pinentry-gtk` (en una tty cae a
curses solo), activa el agente SSH de gpg, añade a `sshcontrol` las
ejemplo). Arregla los permisos, pone `pinentry-dmenu` con los colores de
dmenu (en una tty, `pinentry-curses`: lo decide
`home/.local/bin/pinentry-menu`), activa el agente SSH de gpg, añade a `sshcontrol` las
subclaves de autenticación y hace que recuerde la contraseña una hora.
`.bashrc` ya apunta `SSH_AUTH_SOCK` al agente. Si `~/.gnupg` no existe
todavía, no hace nada.
6. `sistema`: copia `sistema/` en `/`, activa los servicios de runit (dbus,
elogind, polkitd, NetworkManager, bluetoothd, acpid, chronyd, tlp,
automontaje, cupsd), quita dhcpcd y wpa_supplicant (NetworkManager ya
gestiona la red) y añade el usuario a los grupos audio, video, input,
network, bluetooth y lpadmin (para gestionar impresoras). Los archivos de
`sudoers.d` se validan con `visudo` y se instalan con modo 440.
6. `sistema`: copia `sistema/` en `/`, prepara `wpa_supplicant.conf` para que
los de wheel usen `wpa_cli` sin root y guarden redes, activa los servicios
de runit (dbus, turnstiled, wpa_supplicant, dhcpcd, bluetoothd, acpid,
chronyd, tlp, automontaje, cupsd), quita NetworkManager, elogind y polkitd
(si algo pide polkit, como udisks2 o libvirt, D-Bus lo arranca solo) y
añade el usuario a los grupos audio, video, input, network, bluetooth,
lpadmin (para gestionar impresoras) y `_pipewire` (prioridad de tiempo real
para el audio sin rtkit). `doas.conf` se valida con `doas -C` antes de
instalarlo con modo 400.
7. `quitar`: desinstala lo que el repo ya no usa porque lo sustituye otra
cosa: sudo (doas), feh (xwallpaper y nsxiv), gammastep (sct), autorandr
(`pantallas`), blueman y pavucontrol (scripts `bluetooth` y `volumen`),
pinentry-gtk (pinentry-dmenu), vlc (mpv), btop, NetworkManager y tlp-rdw
(wpa_supplicant, dhcpcd y el script `wifi`), rtkit y elogind (turnstile).
sudo se puede quitar gracias a `sistema/etc/xbps.d/sin-sudo.conf`
(base-system depende de él), y solo se quita si `/etc/doas.conf` ya está
instalado.
Después hay que cerrar sesión y volver a entrar (por los grupos) y lanzar
`startx`.
Nix no se instala: lo poco que viene de ahí (webcord) se instala a mano.
## Sin elogind
elogind es el logind de systemd por separado, y aquí sobra:
- `XDG_RUNTIME_DIR` (`/run/user/UID`) lo crea turnstile al entrar
(`sistema/etc/turnstile/turnstiled.conf`: solo eso, sin servicios de
usuario).
- Xorg arranca como root con `Xorg.wrap` (`needs_root_rights = yes` en
`/etc/X11/Xwrapper.config`, lo trae Void).
- La tapa y los botones de encendido y suspender los lleva acpid, que llama a
`zzz`. Apagar y reiniciar son los de runit.
- Los dispositivos (sonido, vídeo, entrada, bluetooth) van por los grupos del
usuario, no por las ACL que ponía elogind a la sesión activa.
Lo que deja de ir: montar discos desde un gestor de archivos (udisks2 pide a
polkit una sesión activa, que ya no hay). Las memorias USB las monta
`automontaje`.
## Recompilar tras cambiar la configuración
cd suckless/dwm && make && sudo make install
cd suckless/dwm && make && doas make install
## Actualizar desde el proyecto original
@ -108,6 +139,18 @@ Las teclas de audio (y los clics en VOL de la barra) usan el script `volumen`
(`home/.local/bin/volumen`): cambia el volumen con `wpctl`, refresca slstatus
y muestra una notificación con el nivel.
Los menús de los scripts (`apagado`, `bluetooth`, `volumen salida`...) usan
`menu`, que es dmenu con la fuente y los colores de dwm.
### Clics en la barra
| Zona | Izquierdo | Central | Derecho | Rueda |
|---|---|---|---|---|
| Red | Conectarse a una red (`wifi`) | | `wpa_cli` | |
| VOL | Elegir la salida de audio (`volumen salida`) | Silenciar | Silenciar el micro | Volumen ± |
| BT | Menú de bluetooth (`bluetooth`): conectar, desconectar, buscar y emparejar, apagar | | Encender o apagar | |
| Fecha | Calendario del mes | | | |
Las capturas se guardan en `~/Images/Screenshots`, se copian al portapapeles
y muestran una notificación.
@ -115,13 +158,18 @@ y muestran una notificación.
- Al entrar en tty1 se lanza `startx` solo (`.bash_profile`); en las demás
tty no.
- `.xinitrc` arranca también `gammastep` (luz cálida de 20:00 a 8:00, con
transición de una hora) y `bateria` (avisa al 15 % y, en rojo, al 5 %; al
3 % suspende con `sudo -n zzz`). Suspender, apagar y reiniciar no piden
contraseña (`sistema/etc/sudoers.d/energia`).
- Pantallas: `autorandr` las pone en fila (la del portátil a la izquierda y
como principal) al arrancar y cada vez que se conecta o desconecta una
(regla de udev en `sistema/`), y vuelve a pintar el fondo.
- `.xinitrc` arranca también `luz` (luz cálida con `sct` de 20:00 a 8:00,
con transición de una hora) y `bateria` (avisa al 15 % y, en rojo, al 5 %;
al 3 % suspende con `doas -n zzz`). Suspender, apagar y reiniciar no piden
contraseña (`sistema/etc/doas.conf`).
- Pantallas: `pantallas` (`sistema/usr/local/bin`) las pone en fila con
`xrandr` (la del portátil a la izquierda y como principal) al arrancar y
cada vez que se conecta o desconecta una (regla de udev en `sistema/`), y
vuelve a pintar el fondo con `xwallpaper`.
- WiFi: `wifi` busca redes con `wpa_cli` y las enseña en dmenu por señal
(`*` la actual). Si la red es nueva pide la contraseña (no se ve al
escribirla) y la guarda en `/etc/wpa_supplicant/wpa_supplicant.conf` solo
si la conexión va bien. El cable lo coge dhcpcd solo.
- Clic izquierdo en la fecha de la barra: calendario del mes en una
notificación (`calendario`), con el día de hoy en verde.
- bash: historial de 10 000 órdenes, sin duplicados y compartido entre
@ -143,7 +191,7 @@ y muestran una notificación.
las monta en `/mnt/ETIQUETA`, o en `/mnt/sdXY` si no tienen etiqueta, y
las desmonta al sacarlas, con una notificación. FAT, exFAT y NTFS quedan a
nombre del usuario; los discos internos no se tocan. Antes de sacar una
memoria en la que se ha escrito, `sync` (o `sudo umount /mnt/...`).
memoria en la que se ha escrito, `sync` (o `doas umount /mnt/...`).
- Carpetas del usuario en inglés y sin tildes (`user-dirs.dirs`):
Documents, Downloads e Images.
@ -160,6 +208,7 @@ y muestran una notificación.
con ligatures vienen de la rama `graphics-with-patches` de
[st-graphics](https://github.com/sergei-grechanik/st-graphics), sin
boxdraw.
- En st, Ctrl+Shift+clic derecho sobre una imagen la abre en `nsxiv`.
- st muestra imágenes con el protocolo de gráficos de kitty; yazi lo detecta
solo y enseña las vistas previas sin ueberzugpp.
- slock está modificado a mano (no es un parche): reloj, fecha, batería y

View file

@ -61,13 +61,13 @@ alias mv='mv -i'
# --- 4. Aliases para Void Linux (xbps) ---
# Te ahorrarán teclear 'xbps-lo-que-sea' 40 veces al día
alias xi='sudo xbps-install' # Instalar paquete
alias xu='sudo xbps-install -Su' # Actualizar todo el sistema
alias xi='doas xbps-install' # Instalar paquete
alias xu='doas xbps-install -Su' # Actualizar todo el sistema
alias xq='xbps-query -Rs' # Buscar paquete en el repositorio
alias xl='xbps-query -l' # Listar paquetes instalados
alias xr='sudo xbps-remove -R' # Eliminar paquete y sus huérfanos
alias xr='doas xbps-remove -R' # Eliminar paquete y sus huérfanos
alias esp32='sudo chmod a+rw /dev/ttyUSB0'
alias esp32='doas chmod a+rw /dev/ttyUSB0'
# --- 5. Funciones Útiles ---

View file

@ -1,6 +0,0 @@
#!/bin/sh
# Tras cambiar de pantallas: la interna del portátil (eDP*/LVDS*) como
# principal y el fondo pintado de nuevo con la geometría nueva.
interna=$(xrandr | awk '/^(eDP|LVDS)[^ ]* connected/ { print $1; exit }')
[ -n "$interna" ] && xrandr --output "$interna" --primary
feh --no-fehbg --bg-fill "$HOME/.local/share/wallpaper.jpg"

View file

@ -1,286 +0,0 @@
#? Config file for btop v.1.4.7
#* Name of a btop++/bpytop/bashtop formatted ".theme" file, "Default" and "TTY" for builtin themes.
#* Themes should be placed in "../share/btop/themes" relative to binary or "$HOME/.config/btop/themes"
color_theme = "everforest-dark-medium"
#* If the theme set background should be shown, set to False if you want terminal background transparency.
theme_background = false
#* Sets if 24-bit truecolor should be used, will convert 24-bit colors to 256 color (6x6x6 color cube) if false.
truecolor = true
#* Set to true to force tty mode regardless if a real tty has been detected or not.
#* Will force 16-color mode and TTY theme, set all graph symbols to "tty" and swap out other non tty friendly symbols.
force_tty = false
#* Option to disable presets. Either the default preset, custom presets, or all presets.
#* "Off" All presets are enabled.
#* "Default" preset is disabled.#* "Custom" presets are disabled.#* "All" presets are disabled.
disable_presets = "Off"
#* Define presets for the layout of the boxes. Preset 0 is always all boxes shown with default settings. Max 9 presets.
#* Format: "box_name:P:G,box_name:P:G" P=(0 or 1) for alternate positions, G=graph symbol to use for box.
#* Use whitespace " " as separator between different presets.
#* Example: "cpu:0:default,mem:0:tty,proc:1:default cpu:0:braille,proc:0:tty"
presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty"
#* Set to True to enable "h,j,k,l,g,G" keys for directional control in lists.
#* Conflicting keys for h:"help" and k:"kill" is accessible while holding shift.
vim_keys = false
#* Disable all mouse events.
disable_mouse = false
#* Rounded corners on boxes, is ignored if TTY mode is ON.
rounded_corners = true
#* Use terminal synchronized output sequences to reduce flickering on supported terminals.
terminal_sync = true
#* Default symbols to use for graph creation, "braille", "block" or "tty".
#* "braille" offers the highest resolution but might not be included in all fonts.
#* "block" has half the resolution of braille but uses more common characters.
#* "tty" uses only 3 different symbols but will work with most fonts and should work in a real TTY.
#* Note that "tty" only has half the horizontal resolution of the other two, so will show a shorter historical view.
graph_symbol = "braille"
# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
graph_symbol_cpu = "default"
# Graph symbol to use for graphs in gpu box, "default", "braille", "block" or "tty".
graph_symbol_gpu = "default"
# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
graph_symbol_mem = "default"
# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
graph_symbol_net = "default"
# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
graph_symbol_proc = "default"
#* Manually set which boxes to show. Available values are "cpu mem net proc" and "gpu0" through "gpu5", separate values with whitespace.
shown_boxes = "cpu mem net proc"
#* Update time in milliseconds, recommended 2000 ms or above for better sample times for graphs.
update_ms = 2000
#* Processes sorting, "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu direct",
#* "cpu lazy" sorts top process over time (easier to follow), "cpu direct" updates top process directly.
proc_sorting = "cpu lazy"
#* Reverse sorting order, True or False.
proc_reversed = false
#* Show processes as a tree.
proc_tree = false
#* Use the cpu graph colors in the process list.
proc_colors = true
#* Use a darkening gradient in the process list.
proc_gradient = true
#* If process cpu usage should be of the core it's running on or usage of the total available cpu power.
proc_per_core = false
#* Show process memory as bytes instead of percent.
proc_mem_bytes = true
#* Show cpu graph for each process.
proc_cpu_graphs = true
#* Use /proc/[pid]/smaps for memory information in the process info box (very slow but more accurate)
proc_info_smaps = false
#* Show proc box on left side of screen instead of right.
proc_left = false
#* (Linux) Filter processes tied to the Linux kernel(similar behavior to htop).
proc_filter_kernel = false
#* Should the process list follow the selected process when detailed view is open.
proc_follow_detailed = true
#* In tree-view, always accumulate child process resources in the parent process.
proc_aggregate = false
#* Should cpu and memory usage display be preserved for dead processes when paused.
keep_dead_proc_usage = false
#* Sets the CPU stat shown in upper half of the CPU graph, "total" is always available.
#* Select from a list of detected attributes from the options menu.
cpu_graph_upper = "Auto"
#* Sets the CPU stat shown in lower half of the CPU graph, "total" is always available.
#* Select from a list of detected attributes from the options menu.
cpu_graph_lower = "Auto"
#* If gpu info should be shown in the cpu box. Available values = "Auto", "On" and "Off".
show_gpu_info = "Auto"
#* Toggles if the lower CPU graph should be inverted.
cpu_invert_lower = true
#* Set to True to completely disable the lower CPU graph.
cpu_single_graph = false
#* Show cpu box at bottom of screen instead of top.
cpu_bottom = false
#* Shows the system uptime in the CPU box.
show_uptime = true
#* Shows the CPU package current power consumption in watts. Requires running `make setcap` or `make setuid` or running with sudo.
show_cpu_watts = true
#* Show cpu temperature.
check_temp = true
#* Which sensor to use for cpu temperature, use options menu to select from list of available sensors.
cpu_sensor = "Auto"
#* Show temperatures for cpu cores also if check_temp is True and sensors has been found.
show_coretemp = true
#* Set a custom mapping between core and coretemp, can be needed on certain cpus to get correct temperature for correct core.
#* Use lm-sensors or similar to see which cores are reporting temperatures on your machine.
#* Format "x:y" x=core with wrong temp, y=core with correct temp, use space as separator between multiple entries.
#* Example: "4:0 5:1 6:3"
cpu_core_map = ""
#* Which temperature scale to use, available values: "celsius", "fahrenheit", "kelvin" and "rankine".
temp_scale = "celsius"
#* Use base 10 for bits/bytes sizes, KB = 1000 instead of KiB = 1024.
base_10_sizes = false
#* Show CPU frequency.
show_cpu_freq = true
#* How to calculate CPU frequency, available values: "first", "range", "lowest", "highest" and "average".
freq_mode = "first"
#* Draw a clock at top of screen, formatting according to strftime, empty string to disable.
#* Special formatting: /host = hostname | /user = username | /uptime = system uptime
clock_format = "%X"
#* Update main ui in background when menus are showing, set this to false if the menus is flickering too much for comfort.
background_update = true
#* Custom cpu model name, empty string to disable.
custom_cpu_name = ""
#* Optional filter for shown disks, should be full path of a mountpoint, separate multiple values with whitespace " ".
#* Only disks matching the filter will be shown. Prepend exclude= to only show disks not matching the filter. Examples: disk_filter="/boot /home/user", disks_filter="exclude=/boot /home/user"
disks_filter = ""
#* Show graphs instead of meters for memory values.
mem_graphs = true
#* Show mem box below net box instead of above.
mem_below_net = false
#* Count ZFS ARC in cached and available memory.
zfs_arc_cached = true
#* If swap memory should be shown in memory box.
show_swap = true
#* Show swap as a disk, ignores show_swap value above, inserts itself after first disk.
swap_disk = true
#* If mem box should be split to also show disks info.
show_disks = true
#* Filter out non physical disks. Set this to False to include network disks, RAM disks and similar.
only_physical = true
#* Read disks list from /etc/fstab. This also disables only_physical.
use_fstab = true
#* Setting this to True will hide all datasets, and only show ZFS pools. (IO stats will be calculated per-pool)
zfs_hide_datasets = false
#* Set to true to show available disk space for privileged users.
disk_free_priv = false
#* Toggles if io activity % (disk busy time) should be shown in regular disk usage view.
show_io_stat = true
#* Toggles io mode for disks, showing big graphs for disk read/write speeds.
io_mode = false
#* Set to True to show combined read/write io graphs in io mode.
io_graph_combined = false
#* Set the top speed for the io graphs in MiB/s (100 by default), use format "mountpoint:speed" separate disks with whitespace " ".
#* Example: "/mnt/media:100 /:20 /boot:1".
io_graph_speeds = ""
#* Swap the positions of the upload and download speed graphs. When true, upload will be on top.
swap_upload_download = false
#* Set fixed values for network graphs in Mebibits. Is only used if net_auto is also set to False.
net_download = 100
net_upload = 100
#* Use network graphs auto rescaling mode, ignores any values set above and rescales down to 10 Kibibytes at the lowest.
net_auto = true
#* Sync the auto scaling for download and upload to whichever currently has the highest scale.
net_sync = true
#* Starts with the Network Interface specified here.
net_iface = ""
#* "True" shows bitrates in base 10 (Kbps, Mbps). "False" shows bitrates in binary sizes (Kibps, Mibps, etc.). "Auto" uses base_10_sizes.
base_10_bitrate = "Auto"
#* Show battery stats in top right if battery is present.
show_battery = true
#* Which battery to use if multiple are present. "Auto" for auto detection.
selected_battery = "Auto"
#* Show power stats of battery next to charge indicator.
show_battery_watts = true
#* Set loglevel for "~/.local/state/btop.log" levels are: "ERROR" "WARNING" "INFO" "DEBUG".
#* The level set includes all lower levels, i.e. "DEBUG" will show all logging info.
log_level = "WARNING"
#* Automatically save current settings to config file on exit.
save_config_on_exit = true
#* Measure PCIe throughput on NVIDIA cards, may impact performance on certain cards.
nvml_measure_pcie_speeds = true
#* Measure PCIe throughput on AMD cards, may impact performance on certain cards.
rsmi_measure_pcie_speeds = true
#* Horizontally mirror the GPU graph.
gpu_mirror_graph = true
#* Set which GPU vendors to show. Available values are "nvidia amd intel apple"
shown_gpus = "nvidia amd intel apple"
#* Custom gpu0 model name, empty string to disable.
custom_gpu_name0 = ""
#* Custom gpu1 model name, empty string to disable.
custom_gpu_name1 = ""
#* Custom gpu2 model name, empty string to disable.
custom_gpu_name2 = ""
#* Custom gpu3 model name, empty string to disable.
custom_gpu_name3 = ""
#* Custom gpu4 model name, empty string to disable.
custom_gpu_name4 = ""
#* Custom gpu5 model name, empty string to disable.
custom_gpu_name5 = ""

View file

@ -1,9 +0,0 @@
; Luz nocturna. Con horas fijas en vez de ubicación: de 20:00 a 21:00 pasa
; poco a poco a luz cálida y de 7:00 a 8:00 vuelve a la normal.
[general]
temp-day=6500
temp-night=4000
fade=1
dusk-time=20:00-21:00
dawn-time=07:00-08:00
adjustment-method=randr

View file

@ -1,3 +0,0 @@
# GTK 2 (pinentry-gtk, entre otros). El tema lo instala install.sh (paso gtk).
gtk-theme-name="Everforest-Green-Dark-Medium"
gtk-icon-theme-name="Papirus-Dark"

View file

@ -1,15 +1,10 @@
#!/bin/sh
# Menú de apagado con dmenu (Mod+Shift+Escape en dwm). Apagar, reiniciar y
# salir de dwm piden confirmación. Suspender, apagar y reiniciar usan sudo
# sin contraseña (sistema/etc/sudoers.d/energia).
menu() {
dmenu -i -p "$1" -fn "Fira Code:size=11" \
-nb "#2d353b" -nf "#d3c6aa" -sb "#a7c080" -sf "#2d353b"
}
# salir de dwm piden confirmación. Suspender, apagar y reiniciar usan doas
# sin contraseña (sistema/etc/doas.conf).
confirmar() {
[ "$(printf 'No\nSí\n' | menu "¿$1?")" = "Sí" ]
[ "$(printf 'No\nSí\n' | menu -p "¿$1?")" = "Sí" ]
}
opcion=$(printf '%s\n' \
@ -17,12 +12,12 @@ opcion=$(printf '%s\n' \
"󰤄 Suspender" \
"󰍃 Salir de dwm" \
"󰜉 Reiniciar" \
"󰐥 Apagar" | menu "Sesión:")
"󰐥 Apagar" | menu -p "Sesión:")
case $opcion in
*Bloquear) slock ;;
*Suspender) sudo -n zzz ;;
*Suspender) doas -n zzz ;;
*Salir*) confirmar "Salir de dwm" && pkill -TERM -x dwm ;;
*Reiniciar) confirmar "Reiniciar" && sudo -n reboot ;;
*Apagar) confirmar "Apagar" && sudo -n poweroff ;;
*Reiniciar) confirmar "Reiniciar" && doas -n reboot ;;
*Apagar) confirmar "Apagar" && doas -n poweroff ;;
esac

View file

@ -3,7 +3,7 @@
# mientras se descarga, y al 3 % suspende (con slock, como al cerrar la
# tapa) en vez de dejar que se apague de golpe. Cada umbral actúa una vez;
# al enchufar el cargador se reinicia. Se lanza desde .xinitrc y comprueba
# cada minuto. Suspender usa "sudo -n zzz" (regla en sistema/etc/sudoers.d).
# cada minuto. Suspender usa "doas -n zzz" (regla en sistema/etc/doas.conf).
BAJA=15
CRITICA=5
@ -26,7 +26,7 @@ while :; do
-i battery-empty "Batería agotada" "Queda un $nivel %: suspendiendo en 10 s"
avisado=$SUSPENDER
sleep 10
[ "$(cat "$bat/status")" = Discharging ] && sudo -n zzz
[ "$(cat "$bat/status")" = Discharging ] && doas -n zzz
elif [ "$nivel" -le "$CRITICA" ] && [ "$avisado" -gt "$CRITICA" ]; then
notify-send -u critical -h string:x-dunst-stack-tag:bateria \
-i battery-empty "Batería crítica" "Queda un $nivel %: enchufa el cargador ya"

70
home/.local/bin/bluetooth Executable file
View file

@ -0,0 +1,70 @@
#!/bin/sh
# Menú de bluetooth con dmenu (clic izquierdo en BT de la barra): conectar o
# desconectar los dispositivos emparejados (󰂱 = conectado), buscar y
# emparejar uno nuevo y apagar el adaptador. Si está apagado, ofrece
# encenderlo.
avisar() {
notify-send -h string:x-dunst-stack-tag:bluetooth -i bluetooth "Bluetooth" "$1"
}
# "Device AA:BB:CC:DD:EE:FF Nombre" -> "Nombre (AA:BB:CC:DD:EE:FF)"
lista() { sed -n 's/^Device \([^ ]*\) \(.*\)/\2 (\1)/p'; }
mac() { printf '%s\n' "$1" | sed 's/.*(\([^)]*\))$/\1/'; }
if ! bluetoothctl show | grep -q 'Powered: yes'; then
[ "$(echo Encender | menu -p Bluetooth:)" = Encender ] || exit 0
bluetoothctl power on >/dev/null
pkill -USR1 -x slstatus
fi
conectados=$(bluetoothctl devices Connected | lista)
emparejados=$(bluetoothctl devices Paired | lista)
opcion=$(
printf '%s\n' "$emparejados" | while IFS= read -r d; do
[ -n "$d" ] || continue
if printf '%s\n' "$conectados" | grep -qxF "$d"; then
echo "󰂱 $d"
else
echo " $d"
fi
done
echo "󰍉 Buscar dispositivos"
echo "󰂲 Apagar"
)
opcion=$(printf '%s\n' "$opcion" | menu -p Bluetooth:)
case $opcion in
'') exit 0 ;;
*" Apagar")
bluetoothctl power off >/dev/null
;;
*" Buscar dispositivos")
avisar "Buscando dispositivos durante 10 s..."
bluetoothctl --timeout 10 scan on >/dev/null
nuevo=$(bluetoothctl devices | lista | awk -v e="$emparejados" '
BEGIN { n = split(e, a, "\n"); for (i = 1; i <= n; i++) visto[a[i]] }
!($0 in visto)' | menu -p Emparejar:)
[ -n "$nuevo" ] || exit 0
m=$(mac "$nuevo")
if bluetoothctl pair "$m" >/dev/null && bluetoothctl trust "$m" >/dev/null &&
bluetoothctl connect "$m" >/dev/null; then
avisar "Conectado: $nuevo"
else
avisar "No se pudo emparejar: $nuevo"
fi
;;
"󰂱 "*)
bluetoothctl disconnect "$(mac "$opcion")" >/dev/null &&
avisar "Desconectado: ${opcion#"󰂱 "}"
;;
*)
if bluetoothctl connect "$(mac "$opcion")" >/dev/null; then
avisar "Conectado: ${opcion#" "}"
else
avisar "No se pudo conectar: ${opcion#" "}"
fi
;;
esac
pkill -USR1 -x slstatus

22
home/.local/bin/luz Executable file
View file

@ -0,0 +1,22 @@
#!/bin/sh
# Luz nocturna con sct: de 20:00 a 21:00 pasa poco a poco a luz cálida y de
# 7:00 a 8:00 vuelve a la normal. Se lanza desde .xinitrc y la ajusta cada
# minuto, así que también vuelve sola si xrandr la reinicia.
DIA=6500
NOCHE=4000
while :; do
m=$(($(date +%-H) * 60 + $(date +%-M)))
if [ "$m" -lt 420 ] || [ "$m" -ge 1260 ]; then
t=$NOCHE
elif [ "$m" -lt 480 ]; then
t=$((NOCHE + (DIA - NOCHE) * (m - 420) / 60))
elif [ "$m" -lt 1200 ]; then
t=$DIA
else
t=$((DIA - (DIA - NOCHE) * (m - 1200) / 60))
fi
sct "$t"
sleep 60
done

5
home/.local/bin/menu Executable file
View file

@ -0,0 +1,5 @@
#!/bin/sh
# dmenu con la fuente y los colores de dwm, para los scripts de ~/.local/bin.
# Uso: menu [opciones de dmenu] (las que se pasen mandan sobre estas)
exec dmenu -i -fn "Fira Code:size=11" \
-nb "#2d353b" -nf "#d3c6aa" -sb "#a7c080" -sf "#2d353b" "$@"

8
home/.local/bin/pinentry-menu Executable file
View file

@ -0,0 +1,8 @@
#!/bin/sh
# pinentry de gpg-agent: pinentry-dmenu en X y pinentry-curses en una tty.
# Los colores de pinentry-dmenu están en ~/.gnupg/pinentry-dmenu.conf
# (lo escribe install.sh, paso gnupg).
if [ -n "$DISPLAY" ]; then
exec pinentry-dmenu "$@"
fi
exec pinentry-curses "$@"

View file

@ -1,14 +1,31 @@
#!/bin/sh
# Cambia el volumen o silencia la salida o el micro (PipeWire), refresca
# slstatus y lo muestra en una notificación que se sustituye a sí misma.
# Uso: volumen subir|bajar|silenciar|micro
# "salida" elige con dmenu por dónde suena (altavoces, cascos...).
# Uso: volumen subir|bajar|silenciar|micro|salida
case $1 in
subir) wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ 5%+ ;;
bajar) wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%- ;;
silenciar) wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle ;;
micro) wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle ;;
*) echo "uso: volumen subir|bajar|silenciar|micro" >&2; exit 1 ;;
salida)
# Las salidas de "wpctl status" (sección Sinks de Audio), con * la actual:
# " │ * 86. Nombre [vol: 0.50]" -> "* 86. Nombre"
s=$(wpctl status | awk '
/Sinks:/ { dentro = 1; next }
dentro && !/[0-9]\./ { exit }
dentro {
sub(/^[^*0-9]*/, ""); actual = sub(/^\* */, "")
sub(/ *\[vol:.*/, ""); print (actual ? "* " : " ") $0
}' | menu -p Salida:)
[ -n "$s" ] || exit 0
s=${s#??}
wpctl set-default "${s%%.*}"
exec notify-send -t 2000 -h string:x-dunst-stack-tag:volumen \
-i audio-speakers "Salida de audio" "${s#*. }"
;;
*) echo "uso: volumen subir|bajar|silenciar|micro|salida" >&2; exit 1 ;;
esac
pkill -USR1 -x slstatus

73
home/.local/bin/wifi Executable file
View file

@ -0,0 +1,73 @@
#!/bin/sh
# Menú de WiFi con dmenu y wpa_cli (clic izquierdo en la red de la barra).
# Busca redes y las ordena por señal; * marca la actual. Si la elegida ya está
# guardada se conecta; si no, pide la contraseña (no se ve al escribirla) y la
# guarda en /etc/wpa_supplicant/wpa_supplicant.conf cuando la conexión va bien.
# wpa_cli funciona sin root para los de wheel (ctrl_interface_group, lo pone
# install.sh en el paso sistema).
avisar() {
notify-send -h string:x-dunst-stack-tag:wifi -i network-wireless "WiFi" "$1"
}
IF=
for w in /sys/class/net/*/wireless; do
[ -e "$w" ] && IF=${w%/wireless} && IF=${IF##*/} && break
done
[ -n "$IF" ] || { avisar "No hay tarjeta WiFi"; exit 1; }
wpa() { wpa_cli -i "$IF" "$@"; }
wpa scan >/dev/null || { avisar "wpa_supplicant no responde"; exit 1; }
sleep 3
actual=$(wpa status | sed -n 's/^ssid=//p')
# scan_results: bssid, frecuencia, señal, flags y ssid, separados por tabuladores
resultados=$(wpa scan_results | tail -n +2)
ssid=$(printf '%s\n' "$resultados" | sort -t "$(printf '\t')" -k3,3nr |
awk -F '\t' -v a="$actual" '$5 != "" && !visto[$5]++ {
print ($5 == a ? "* " : " ") $5
}' | menu -l 15 -p WiFi:)
[ -n "$ssid" ] || exit 0
ssid=${ssid#??}
id=$(wpa list_networks | awk -F '\t' -v s="$ssid" 'NR > 1 && $2 == s { print $1; exit }')
nueva=
if [ -z "$id" ]; then
nueva=1
id=$(wpa add_network | tail -1)
wpa set_network "$id" ssid "\"$ssid\"" >/dev/null
flags=$(printf '%s\n' "$resultados" | awk -F '\t' -v s="$ssid" '$5 == s { print $4; exit }')
case $flags in
*WPA* | *RSN* | *SAE*)
clave=$(menu -p "Contraseña de $ssid:" -nf "#2d353b" </dev/null)
if [ -z "$clave" ]; then
wpa remove_network "$id" >/dev/null
exit 0
fi
wpa set_network "$id" psk "\"$clave\"" >/dev/null
;;
*) wpa set_network "$id" key_mgmt NONE >/dev/null ;;
esac
fi
avisar "Conectando a $ssid..."
wpa select_network "$id" >/dev/null
i=0
while [ "$i" -lt 20 ] && ! wpa status | grep -qx wpa_state=COMPLETED; do
sleep 1
i=$((i + 1))
done
# select_network deshabilita las demás redes: se vuelven a habilitar para que
# siga cambiando sola a la que haya.
if wpa status | grep -qx wpa_state=COMPLETED; then
wpa enable_network all >/dev/null
wpa save_config >/dev/null
avisar "Conectado a $ssid"
else
[ -n "$nueva" ] && wpa remove_network "$id" >/dev/null
wpa enable_network all >/dev/null
avisar "No se pudo conectar a $ssid"
fi
pkill -USR1 -x slstatus

View file

@ -1,6 +1,6 @@
#!/bin/sh
# elogind ya crea XDG_RUNTIME_DIR (/run/user/UID); esto es solo por si falta.
# turnstile ya crea XDG_RUNTIME_DIR (/run/user/UID); esto es solo por si falta.
if [ -z "$XDG_RUNTIME_DIR" ]; then
export XDG_RUNTIME_DIR=/tmp/$(id -u)-runtime-dir
mkdir -p "$XDG_RUNTIME_DIR"
@ -8,7 +8,7 @@ if [ -z "$XDG_RUNTIME_DIR" ]; then
fi
# Abrir el bus de sesión D-Bus antes de lanzar nada, para que pipewire,
# wireplumber, dunst, blueman... y dwm compartan el mismo bus.
# wireplumber, dunst... y dwm compartan el mismo bus.
if [ -z "$DBUS_SESSION_BUS_ADDRESS" ]; then
exec dbus-run-session -- sh "$HOME/.xinitrc"
fi
@ -17,13 +17,11 @@ fi
# qt6ct también responde a "qt5ct", así que vale para Qt 5 y Qt 6.
export QT_QPA_PLATFORMTHEME=qt5ct
# Teclado y monitores primero; el fondo se pinta después con la geometría final.
# autorandr pone las pantallas conectadas en fila (la del portátil a la
# izquierda); al conectar o desconectar una, lo repite solo (regla de udev en
# sistema/) y vuelve a pintar el fondo (~/.config/autorandr/postswitch).
# Teclado y pantallas primero. pantallas (sistema/usr/local/bin) las pone en
# fila, con la del portátil a la izquierda, y pinta el fondo; al conectar o
# desconectar una, lo repite solo (regla de udev en sistema/).
setxkbmap es
autorandr --change --default horizontal
feh --no-fehbg --bg-fill "$HOME/.local/share/wallpaper.jpg" &
pantallas
pipewire &
wireplumber &
@ -31,10 +29,9 @@ pipewire-pulse &
dunst &
picom &
blueman-applet &
slstatus &
clipmenud &
gammastep &
luz &
bateria &
marcadores &

View file

@ -2,9 +2,10 @@
# Deja un Void Linux recién instalado con este escritorio: paquetes, programas
# de suckless, enlaces de la configuración en ~ y archivos de sistema.
#
# Uso: ./install.sh [paquetes] [suckless] [enlaces] [gtk] [gnupg] [sistema]
# Sin argumentos hace los seis pasos, en ese orden. Se ejecuta como el
# usuario normal; pide sudo cuando hace falta. Se puede repetir sin problema.
# Uso: ./install.sh [paquetes] [suckless] [enlaces] [gtk] [gnupg] [sistema] [quitar]
# Sin argumentos hace los siete pasos, en ese orden. Se ejecuta como el
# usuario normal; pide la contraseña de root (doas, o sudo en un Void recién
# instalado) cuando hace falta. Se puede repetir sin problema.
set -eu
@ -16,16 +17,16 @@ PAQUETES="
libXfixes-devel libxcb-devel freetype-devel fontconfig-devel harfbuzz-devel
libXrender-devel xorgproto imlib2-devel zlib-devel libxcrypt-devel
xorg xinit setxkbmap xrandr dbus elogind polkit
picom dunst libnotify feh maim xclip gammastep xss-lock autorandr
pipewire wireplumber libspa-bluetooth alsa-pipewire rtkit pavucontrol
NetworkManager bluez blueman acpid chrony tlp tlp-rdw
xorg xinit setxkbmap xrandr dbus turnstile
picom dunst libnotify xwallpaper nsxiv maim xclip sct xss-lock
pipewire wireplumber libspa-bluetooth alsa-pipewire
wpa_supplicant dhcpcd bluez acpid chrony tlp
cups cups-filters hplip
font-firacode nerd-fonts-symbols-ttf papirus-icon-theme papirus-folders
sassc gtk-engine-murrine gnome-themes-extra qt5ct qt6ct
sassc gnome-themes-extra qt5ct qt6ct
gnupg pinentry-gtk
firefox thunderbird neovim git fuse-sshfs unzip
opendoas gnupg pinentry-dmenu
firefox thunderbird mpv neovim git fuse-sshfs unzip
yazi file ffmpeg 7zip jq poppler fd ripgrep fzf zoxide resvg ImageMagick
"
@ -33,19 +34,43 @@ SUCKLESS="dwm st dmenu slstatus slock scroll clipmenu"
# Tema GTK Everforest, en una versión fija para que siempre salga igual
GTK_TEMA_REPO=https://github.com/Fausto-Korpsvart/Everforest-GTK-Theme
GTK_TEMA_COMMIT=9b8be4d6648ae9eaae3dd550105081f8c9054825
SERVICIOS="dbus elogind polkitd NetworkManager bluetoothd acpid chronyd tlp automontaje cupsd"
# NetworkManager gestiona la red él solo; estos servicios se pelean con él.
SERVICIOS_FUERA="dhcpcd wpa_supplicant"
GRUPOS="audio video input network bluetooth lpadmin"
SERVICIOS="dbus turnstiled wpa_supplicant dhcpcd bluetoothd acpid chronyd tlp automontaje cupsd"
# La red la llevan wpa_supplicant y dhcpcd. polkitd no hace falta como
# servicio: si algo lo pide (udisks2, libvirt), D-Bus lo arranca. turnstiled
# sustituye a elogind.
SERVICIOS_FUERA="NetworkManager polkitd elogind"
# _pipewire da prioridad de tiempo real al audio sin rtkit
# (/etc/security/limits.d/25-pw-rlimits.conf, de pipewire).
GRUPOS="audio video input network bluetooth lpadmin _pipewire"
# Lo que sustituyen otras cosas del repo: sudo (doas), feh (xwallpaper y
# nsxiv), gammastep (sct), autorandr (pantallas), blueman y pavucontrol
# (scripts bluetooth y volumen), pinentry-gtk (pinentry-dmenu), vlc (mpv),
# NetworkManager (wpa_supplicant, dhcpcd y el script wifi), rtkit (el grupo
# _pipewire) y elogind (turnstile; Xorg arranca como root con Xorg.wrap y la
# tapa y los botones ya los lleva acpid).
QUITAR="
sudo feh gammastep autorandr blueman pavucontrol pinentry-gtk
gtk-engine-murrine vlc btop NetworkManager tlp-rdw rtkit elogind
"
msg() { printf '\033[1;32m==>\033[0m %s\n' "$*"; }
die() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; }
# Como root: con doas cuando ya está configurado; antes (Void recién
# instalado) con sudo.
root() {
if command -v doas >/dev/null && [ -f /etc/doas.conf ]; then
doas "$@"
else
sudo "$@"
fi
}
paquetes() {
msg "Instalando paquetes"
sudo xbps-install -Syu xbps
root xbps-install -Syu xbps
# shellcheck disable=SC2086
sudo xbps-install -Syu $PAQUETES
root xbps-install -Syu $PAQUETES
}
suckless() {
@ -53,7 +78,7 @@ suckless() {
msg "Compilando $p"
make -C "$DIR/suckless/$p" clean >/dev/null
make -C "$DIR/suckless/$p"
sudo make -C "$DIR/suckless/$p" install
root make -C "$DIR/suckless/$p" install
done
}
@ -79,6 +104,14 @@ enlaces() {
done
cd "$DIR"
# Los enlaces a archivos que ya no están en home/ (borrados del repo)
find "$HOME" -xdev -type l -lname "$DIR/home/*" ! -exec test -e {} \; -print |
while read -r l; do
rm "$l"
rmdir "$(dirname "$l")" 2>/dev/null || true
echo " ${l#"$HOME"/} (ya no está en el repo: quitado)"
done
# Las carpetas de home/.config/user-dirs.dirs (y la de las capturas)
mkdir -p "$HOME/Documents" "$HOME/Downloads" "$HOME/Images/Screenshots"
# ssh no quiere ~/.ssh accesible para otros
@ -86,10 +119,10 @@ enlaces() {
}
# Compila el tema GTK Everforest (verde, oscuro, paleta medium) en ~/.themes
# y lo enlaza para las apps de GTK 4. Qué tema e iconos se usan lo dicen
# home/.gtkrc-2.0 y home/.config/gtk-*/settings.ini. Las carpetas de Papirus
# se ponen verdes; una actualización de papirus-icon-theme las devuelve a
# azul, y basta con repetir este paso.
# y lo enlaza para las apps de GTK 4. Qué tema e iconos se usan lo dice
# home/.config/gtk-*/settings.ini. Las carpetas de Papirus se ponen verdes;
# una actualización de papirus-icon-theme las devuelve a azul, y basta con
# repetir este paso.
gtk() {
msg "Compilando el tema GTK Everforest"
tmp=$(mktemp -d)
@ -98,25 +131,14 @@ gtk() {
"$tmp/themes/install.sh" -t green -c dark --tweaks medium -l >/dev/null
rm -rf "$tmp"
# La plantilla de GTK 2 del tema trae los colores de Gruvbox (fallo del
# tema original): se cambian por Everforest medium. pinentry-gtk es GTK 2.
sed -i \
-e 's|^gtk-color-scheme = "text_color:.*|gtk-color-scheme = "text_color:#d3c6aa\\nbase_color:#2d353b"|' \
-e 's|^gtk-color-scheme = "fg_color:.*|gtk-color-scheme = "fg_color:#d3c6aa\\nbg_color:#2d353b"|' \
-e 's|^gtk-color-scheme = "selected_fg_color:.*|gtk-color-scheme = "selected_fg_color:#2d353b\\nselected_bg_color:#a7c080"|' \
-e 's|^gtk-color-scheme = "titlebar_fg_color:.*|gtk-color-scheme = "titlebar_fg_color:#d3c6aa\\ntitlebar_bg_color:#2d353b"|' \
-e 's|^gtk-color-scheme = "menu_color:.*|gtk-color-scheme = "menu_color:#343f44"|' \
-e 's|^gtk-color-scheme = "tooltip_fg_color:.*|gtk-color-scheme = "tooltip_fg_color:#d3c6aa\\ntooltip_bg_color:#3d484d"|' \
-e 's|^gtk-color-scheme = "link_color:.*|gtk-color-scheme = "link_color:#7fbbb3\\nvisited_link_color:#d699b6"|' \
"$HOME/.themes/Everforest-Green-Dark-Medium/gtk-2.0/gtkrc"
msg "Carpetas de Papirus en verde"
sudo papirus-folders -C green --theme Papirus-Dark >/dev/null
root papirus-folders -C green --theme Papirus-Dark >/dev/null
}
# ~/.gnupg se copia a mano (de un USB, por ejemplo). Deja los permisos como
# los quiere gpg, usa un pinentry gráfico (en una tty cae a curses solo) y
# activa el agente SSH con las claves de autenticación.
# los quiere gpg, usa pinentry-dmenu (en una tty, pinentry-curses; lo decide
# home/.local/bin/pinentry-menu) y activa el agente SSH con las claves de
# autenticación.
gnupg() {
g="$HOME/.gnupg"
if [ ! -d "$g" ]; then
@ -125,21 +147,37 @@ gnupg() {
fi
msg "Arreglando permisos de $g"
sudo chown -R "$(id -u):$(id -g)" "$g"
root chown -R "$(id -u):$(id -g)" "$g"
find "$g" -type d -exec chmod 700 {} +
find "$g" -type f -exec chmod 600 {} +
msg "Configurando gpg-agent (pinentry gráfico y SSH)"
msg "Configurando gpg-agent (pinentry-dmenu y SSH)"
conf="$g/gpg-agent.conf"
touch "$conf"
chmod 600 "$conf"
sed -i '/^pinentry-program/d; /^default-cache-ttl/d' "$conf"
echo "pinentry-program /usr/bin/pinentry-gtk-2" >>"$conf"
echo "pinentry-program $HOME/.local/bin/pinentry-menu" >>"$conf"
grep -qx enable-ssh-support "$conf" || echo enable-ssh-support >>"$conf"
# Recordar la contraseña una hora desde el último uso (por defecto, 10 min)
echo "default-cache-ttl 3600" >>"$conf"
echo "default-cache-ttl-ssh 3600" >>"$conf"
# pinentry-dmenu con la fuente y los colores de dmenu
cat >"$g/pinentry-dmenu.conf" <<-EOF
asterisk = "*";
prompt = "Contraseña:";
font = "Fira Code:size=11";
prompt_bg = "#a7c080";
prompt_fg = "#2d353b";
normal_bg = "#2d353b";
normal_fg = "#d3c6aa";
select_bg = "#a7c080";
select_fg = "#2d353b";
desc_bg = "#2d353b";
desc_fg = "#d3c6aa";
EOF
chmod 600 "$g/pinentry-dmenu.conf"
# sshcontrol dice qué claves usa el agente para SSH: se añaden las
# subclaves de autenticación [A] que falten.
touch "$g/sshcontrol"
@ -163,47 +201,79 @@ sistema() {
find . -type f | while read -r f; do
f=${f#.}
case $f in
/etc/sudoers.d/*)
# git no guarda el modo 440 que exige sudo; y un sudoers
# roto deja sin sudo, así que se valida antes de copiarlo.
visudo -cf ".$f" >/dev/null || die "sudoers inválido: $f"
sudo install -D -m 440 ".$f" "$f"
/etc/doas.conf)
# Un doas.conf roto deja sin root: se valida antes de copiarlo.
doas -C ".$f" || die "doas.conf inválido"
root install -D -m 400 ".$f" "$f"
;;
*) sudo install -D -m "$(stat -c %a ".$f")" ".$f" "$f" ;;
*) root install -D -m "$(stat -c %a ".$f")" ".$f" "$f" ;;
esac
echo " $f"
done
cd "$DIR"
# wpa_cli sin root para los de wheel (script wifi) y guardar las redes
# nuevas. El archivo tiene las contraseñas: se edita en su sitio.
msg "Configurando wpa_supplicant"
w=/etc/wpa_supplicant/wpa_supplicant.conf
cabecera="ctrl_interface=/run/wpa_supplicant
ctrl_interface_group=wheel
update_config=1"
# shellcheck disable=SC2016
root sh -c 'umask 077; touch "$1"
{ printf "%s\n" "$2"; grep -v -e "^ctrl_interface" -e "^update_config" "$1"; } >"$1.nuevo"
mv "$1.nuevo" "$1"' sh "$w" "$cabecera"
msg "Activando servicios"
for s in $SERVICIOS; do
[ -d "/etc/sv/$s" ] || die "no existe el servicio $s (¿faltan paquetes?)"
if [ ! -e "/var/service/$s" ]; then
sudo ln -s "/etc/sv/$s" /var/service/
root ln -s "/etc/sv/$s" /var/service/
fi
done
for s in $SERVICIOS_FUERA; do
if [ -e "/var/service/$s" ]; then
sudo rm "/var/service/$s"
root rm "/var/service/$s"
fi
done
msg "Añadiendo $USER a los grupos: $GRUPOS"
for g in $GRUPOS; do
if getent group "$g" >/dev/null; then
sudo usermod -aG "$g" "$USER"
root usermod -aG "$g" "$USER"
fi
done
}
# Desinstala lo que el repo ya no usa (QUITAR), si está instalado. sudo solo
# se quita cuando doas ya funciona (paso sistema).
quitar() {
[ -f /etc/doas.conf ] || die "falta /etc/doas.conf: ejecuta antes el paso sistema"
fuera=
for p in $QUITAR; do
xbps-query "$p" >/dev/null 2>&1 && fuera="$fuera $p"
done
if [ -z "$fuera" ]; then
return 0
fi
msg "Quitando:$fuera"
# shellcheck disable=SC2086
root xbps-remove -Ry $fuera
# Lo que puso aquí una versión anterior de sistema/ para elogind
if [ -e /etc/elogind/logind.conf.d/10-acpid.conf ]; then
root rm /etc/elogind/logind.conf.d/10-acpid.conf
fi
}
[ -f /etc/void-release ] || command -v xbps-install >/dev/null ||
die "esto es solo para Void Linux"
[ "$(id -u)" -ne 0 ] || die "ejecútalo como tu usuario, no como root"
[ $# -gt 0 ] || set -- paquetes suckless enlaces gtk gnupg sistema
[ $# -gt 0 ] || set -- paquetes suckless enlaces gtk gnupg sistema quitar
for paso; do
case $paso in
paquetes|suckless|enlaces|gtk|gnupg|sistema) "$paso" ;;
paquetes|suckless|enlaces|gtk|gnupg|sistema|quitar) "$paso" ;;
*) die "paso desconocido: $paso" ;;
esac
done

8
sistema/etc/doas.conf Normal file
View file

@ -0,0 +1,8 @@
# doas en vez de sudo. Los de wheel pueden hacer de root con su contraseña,
# que se recuerda unos minutos. Suspender, apagar y reiniciar (sin
# argumentos) no la piden: los usan bateria y apagado (home/.local/bin).
# Vale la última regla que coincide.
permit persist :wheel
permit nopass :wheel as root cmd zzz args
permit nopass :wheel as root cmd poweroff args
permit nopass :wheel as root cmd reboot args

View file

@ -1,11 +0,0 @@
# acpid ya se encarga de la tapa y del botón de suspender (llama a zzz) y del
# botón de encendido. Si elogind también reacciona, el portátil se suspende
# dos veces: al abrir la tapa se enciende, se vuelve a suspender y luego
# arranca. Así solo lo gestiona acpid.
[Login]
HandlePowerKey=ignore
HandleSuspendKey=ignore
HandleHibernateKey=ignore
HandleLidSwitch=ignore
HandleLidSwitchExternalPower=ignore
HandleLidSwitchDocked=ignore

View file

@ -1,4 +0,0 @@
# Suspender, apagar y reiniciar sin contraseña para los de wheel (solo esos
# comandos y sin argumentos). Los usan el script bateria (suspender al
# agotarse) y el menú de apagado (home/.local/bin/apagado).
%wheel ALL=(root) NOPASSWD: /usr/bin/zzz "", /usr/bin/poweroff "", /usr/bin/reboot ""

View file

@ -0,0 +1,7 @@
# turnstile en vez de elogind, solo para crear /run/user/UID
# (XDG_RUNTIME_DIR) al entrar. Sin gestor de servicios de usuario: lo de la
# sesión lo arranca .xinitrc. Tampoco exporta DBUS_SESSION_BUS_ADDRESS,
# porque el bus lo abre .xinitrc con dbus-run-session.
backend = none
manage_rundir = yes
export_dbus_address = no

View file

@ -1,4 +1,3 @@
# Sustituye a la regla de autorandr (/usr/lib/udev/rules.d): al conectar o
# desconectar una pantalla, colocarlas todas en fila ("horizontal") en vez
# de buscar un perfil guardado llamado "default".
ACTION=="change", SUBSYSTEM=="drm", RUN+="/usr/bin/autorandr --batch --change --default horizontal"
# Al conectar o desconectar una pantalla, colocarlas todas en fila y repintar
# el fondo (sistema/usr/local/bin/pantallas).
ACTION=="change", SUBSYSTEM=="drm", RUN+="/usr/local/bin/pantallas"

View file

@ -0,0 +1,2 @@
# base-system depende de sudo; así se puede quitar (se usa doas).
ignorepkg=sudo

39
sistema/usr/local/bin/pantallas Executable file
View file

@ -0,0 +1,39 @@
#!/bin/sh
# Pone en fila todas las pantallas conectadas, con la del portátil
# (eDP*/LVDS*) a la izquierda y como principal, apaga las desconectadas y
# vuelve a pintar el fondo. Lo lanzan .xinitrc al arrancar y la regla de udev
# (sistema/etc/udev/rules.d) al conectar o desconectar una pantalla.
#
# udev lo ejecuta como root: entonces se relanza como el usuario de la sesión
# de dwm, con su DISPLAY.
if [ "$(id -u)" -eq 0 ]; then
pid=$(pgrep -xo dwm) || exit 0
usuario=$(stat -c %U "/proc/$pid")
casa=$(getent passwd "$usuario" | cut -d: -f6)
entorno=$(tr '\0' '\n' <"/proc/$pid/environ" | grep -E '^(DISPLAY|XAUTHORITY)=')
# shellcheck disable=SC2086
exec env $entorno HOME="$casa" chpst -u "$usuario" "$0"
fi
estado=$(xrandr) || exit 1
interna=$(echo "$estado" | awk '/^(eDP|LVDS)[^ ]* connected/ { print $1 }')
otras=$(echo "$estado" | awk '/ connected/ && $1 !~ /^(eDP|LVDS)/ { print $1 }')
fuera=$(echo "$estado" | awk '/ disconnected/ { print $1 }')
set --
ant=
for o in $interna $otras; do
if [ -z "$ant" ]; then
set -- "$@" --output "$o" --auto --primary --pos 0x0
else
set -- "$@" --output "$o" --auto --right-of "$ant"
fi
ant=$o
done
for o in $fuera; do
set -- "$@" --output "$o" --off
done
[ $# -gt 0 ] && xrandr "$@"
xwallpaper --zoom "$HOME/.local/share/wallpaper.jpg"

View file

@ -38,11 +38,8 @@ static const Rule rules[] = {
* hasta que se cierra; noswallow = 1 lo evita para esa ventana. */
/* class instance title tags mask isfloating isterminal noswallow monitor */
{ "st-256color", NULL, NULL, 0, 0, 1, 0, -1 },
{ "st-float", NULL, NULL, 0, 1, 0, 1, -1 }, /* st -c st-float (p. ej. nmtui) */
{ "st-float", NULL, NULL, 0, 1, 0, 1, -1 }, /* st -c st-float (p. ej. wpa_cli) */
{ "Gimp", NULL, NULL, 0, 1, 0, 0, -1 },
{ NULL, "pavucontrol", NULL, 0, 1, 0, 0, -1 },
{ NULL, "blueman-manager", NULL, 0, 1, 0, 0, -1 },
{ "Pinentry-gtk-2", NULL, NULL, 0, 1, 0, 1, -1 }, /* contraseña de gpg/ssh */
{ "Firefox", "Places", NULL, 0, 1, 0, 0, -1 }, /* biblioteca/descargas */
{ "Firefox", "Toolkit", NULL, 0, 1, 0, 0, -1 }, /* picture-in-picture */
{ NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */
@ -99,22 +96,22 @@ static const char *lockcmd[] = { "slock", NULL };
* (1 izquierdo, 2 central, 3 derecho, 4/5 rueda arriba/abajo).
*/
static const StatusCmd statuscmds[] = {
/* red: izquierdo conectarse a una red, derecho el menú completo de nmtui */
/* red: izquierdo conectarse a una red (script wifi), derecho wpa_cli */
{ "case $BUTTON in "
"1) st -c st-float -g 90x30 -e nmtui connect ;; "
"3) st -c st-float -g 90x30 -e nmtui ;; "
"1) wifi ;; "
"3) st -c st-float -g 90x30 -e wpa_cli ;; "
"esac", 1 },
/* volumen: izquierdo pavucontrol, central silenciar, derecho micro, rueda subir/bajar */
/* volumen: izquierdo elegir la salida, central silenciar, derecho micro, rueda subir/bajar */
{ "case $BUTTON in "
"1) pavucontrol ;; "
"1) volumen salida ;; "
"2) " VOLMUTECMD " ;; "
"3) " MICMUTECMD " ;; "
"4) " VOLUPCMD " ;; "
"5) " VOLDOWNCMD " ;; "
"esac", 2 },
/* bluetooth: izquierdo blueman, derecho encender/apagar el adaptador */
/* bluetooth: izquierdo el menú (script bluetooth), derecho encender/apagar el adaptador */
{ "case $BUTTON in "
"1) blueman-manager ;; "
"1) bluetooth ;; "
"3) if bluetoothctl show | grep -q 'Powered: yes'; "
"then bluetoothctl power off; else bluetoothctl power on; fi >/dev/null" STATUSREFRESH " ;; "
"esac", 3 },

View file

@ -214,7 +214,7 @@ static uint forcemousemod = ShiftMask;
*/
static MouseShortcut mshortcuts[] = {
/* mask button function argument release */
{ TERMMOD, Button3, previewimage, {.s = "feh"} },
{ TERMMOD, Button3, previewimage, {.s = "nsxiv"} },
{ TERMMOD, Button2, showimageinfo, {}, 1 },
{ XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 },
{ ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} },