#!/usr/bin/env bash # exwm-arch install script # arch + exwm + daviwil emacs-from-scratch dotfiles (https://github.com/daviwil/emacs-from-scratch) set -euo pipefail RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m' info() { echo -e "${GREEN}[info]${NC} $*"; } warn() { echo -e "${YELLOW}[warn]${NC} $*"; } error() { echo -e "${RED}[error]${NC} $*"; exit 1; } [[ $EUID -eq 0 ]] && error "do not run as root. run as your sudo user." command -v pacman &>/dev/null || error "this script is for arch linux only." # base tools info "installing xorg and base tools..." sudo pacman -S --noconfirm --needed \ xorg-server xorg-xinit \ emacs \ dmenu \ git \ zsh \ rxvt-unicode \ tmux \ xterm \ nano # daviwil emacs-from-scratch dotfiles if [[ -d "$HOME/.emacs.d" ]]; then warn "~/.emacs.d already exists — backing up to ~/.emacs.d-old" mv "$HOME/.emacs.d" "$HOME/.emacs.d-old" fi info "cloning daviwil emacs-from-scratch..." git clone https://github.com/daviwil/emacs-from-scratch "$HOME/.emacs.d" #.xinitrc info "writing ~/.xinitrc..." cat > "$HOME/.xinitrc" << 'EOF' exec emacs EOF # pipewire audio info "installing pipewire audio stack..." sudo pacman -S --noconfirm --needed \ pipewire \ pipewire-pulse \ wireplumber info "enabling pipewire user services..." systemctl --user enable --now pipewire pipewire-pulse wireplumber # installing applications info "installing applications and fonts..." sudo pacman -S --noconfirm --needed \ firefox \ ttf-dejavu \ noto-fonts \ xclip \ scrot \ xf86-video-qxl # proxmox/qemu display driver # .emacs config info "writing ~/.emacs..." cat > "$HOME/.emacs" << 'EOF' ;;; -*- lexical-binding: t -*- ;; package manager setup (require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) (package-initialize) ;; ensure exwm is installed (if not already) (unless (package-installed-p 'exwm) (package-refresh-contents) (package-install 'exwm)) ;; ensure doom-themes is installed (if not already) (unless (package-installed-p 'doom-themes) (package-refresh-contents) (package-install 'doom-themes)) ;; load exwm and disable clunky gui elements (require 'exwm) (menu-bar-mode -1) (tool-bar-mode -1) (scroll-bar-mode -1) (column-number-mode 1) (show-paren-mode 1) ;; theme (use-package doom-themes :ensure t :config (load-theme 'doom-moonlight t)) ;; rename buffer to match application name (defun efs/exwm-update-class () (exwm-workspace-rename-buffer exwm-class-name)) (add-hook 'exwm-update-class-hook #'efs/exwm-update-class) ;; cua: better copy/paste keybinds. C-x C-c copy, C-v to paste (cua-selection-mode t) ;; keys that must passthrough to emacs regardless of focused window (setq exwm-input-prefix-keys '(?\C-x ?\C-u ?\C-h ?\M-x ?\M-: ?\C-\ )) ;; C-q passes the next key directly to the application (define-key exwm-mode-map [?\C-q] 'exwm-input-send-next-key) ;; global keybinds ;; note: super (win) key passes through to host when running in a vm via browser. ;; use meta (alt) keybinds instead when in a vm. super binds work on bare metal. (setq exwm-input-global-keys `(;; reset window to line mode ([?\s-r] . exwm-reset) ;; move between emacs windows ([s-left] . windmove-left) ([s-right] . windmove-right) ([s-up] . windmove-up) ([s-down] . windmove-down) ;; launch application by shell command ([?\s-&] . (lambda (command) (interactive (list (read-shell-command "$ "))) (start-process-shell-command command nil command))) ;; open terminal ([s-return] . (lambda () (interactive) (start-process "" nil "urxvt"))) ;; switch workspace interactively ([?\s-w] . exwm-workspace-switch) ;; s-0 through s-9 switch workspaces ,@(mapcar (lambda (i) `(,(kbd (format "s-%d" i)) . (lambda () (interactive) (exwm-workspace-switch-create ,i)))) (number-sequence 0 9)))) ;; start exwm (exwm-wm-mode) EOF # install emacs packages via batch emacs info "installing emacs packages (exwm + doom-themes) via batch mode..." emacs --batch \ --eval "(require 'package)" \ --eval "(add-to-list 'package-archives '(\"melpa\" . \"https://melpa.org/packages/\") t)" \ --eval "(package-initialize)" \ --eval "(unless (package-installed-p 'exwm) (package-refresh-contents) (package-install 'exwm))" \ --eval "(unless (package-installed-p 'doom-themes) (package-refresh-contents) (package-install 'doom-themes))" \ 2>&1 | tail -5 echo "" info "all done! launch with: startx" echo "" echo "" echo " quick reference:" echo " s-Return open urxvt terminal" echo " s-0 .. s-9 switch/create workspace" echo " s-w interactive workspace switcher" echo " s-r reset/refresh window" echo " s-arrows move between emacs splits" echo " s-& launch app by shell command" echo " C-x C-f open/find file" echo " C-x C-c quit emacs (closes everything)" echo ""