stumpwmrc @ c27fb01fc92f

au
author Steve Losh <steve@stevelosh.com>
date Sat, 07 Jul 2018 20:27:24 +0000
parents b3887bda7531
children 196885c6b61b 74e54dee9e41
(in-package :stumpwm-user)

(ql:quickload '(:losh :split-sequence :alexandria) :silent t)
(use-package :losh)

;;;; Config -------------------------------------------------------------------
(set-prefix-key (kbd "C-space"))

;; (redirect-all-output (data-dir-file "debug" "text"))

(setf *mouse-focus-policy* :click
      *message-window-gravity* :center
      *input-window-gravity* :center
      *debug-level* 0
      *shell-program* "/bin/bash")


;;;; Utils --------------------------------------------------------------------
(defun ensure-mode-line ()
  (when (not (stumpwm::head-mode-line (current-head)))
    (toggle-mode-line (current-screen) (current-head))))


(defun string-contains (needle string)
  (and (search needle string :test #'char=) t))

(defun string-grep (needle text &key first-only)
  (-<> text
    (split-sequence:split-sequence #\newline <>)
    (if first-only
      (find needle <> :test #'string-contains)
      (remove-if-not (alexandria:curry #'string-contains needle) <>))))

(defun string-split (delimiters string)
  (split-sequence:split-sequence delimiters string
                                 :test (lambda (bag ch)
                                         (find ch bag :test #'char=))))


(defun volume ()
  (-<> (run-shell-command "amixer sget Master" t)
    (string-grep "Front Left:" <> :first-only t)
    (string-split "[]" <>)
    second
    (string-trim "%" <>)
    parse-integer))

(defun battery ()
  (run-shell-command
    "acpi -b | awk -F '[ ,]' '{printf \"%s%s\", $3, $5}' | sed s/Discharging// | sed s/Unknown// | sed s/Full// | sed s/Charging/+/"
    t))


(defun current-frame ()
  (stumpwm::tile-group-current-frame (current-group)))


(defun debug-log (&rest args)
  (with-open-file (s "/home/sjl/stumpwm.debug.log"
                     :direction :output
                     :if-exists :append
                     :if-does-not-exist :create)
    (apply #'format s args)))


(defun keywordize (string)
  (-<> string
    (string-trim (string #\newline) <>)
    string-upcase
    (intern <> (find-package :keyword))))

(defparameter *host* (keywordize (run-shell-command "hostname" t)))

(defmacro ehostcase (&body clauses)
  `(ecase *host* ,@clauses))

(defmacro hostcase (&body clauses)
  `(case *host* ,@clauses))


;;;; Regroup -------------------------------------------------------------------
(defparameter *class-groups*
  '(("zoom" . "zoom")
    ("jetbrains-idea-ce" . "ij"))
  "An alist of window classes to be regrouped and their targets")

(defun regroup (win)
  "Regroup window by class."
  (let* ((class (window-class win))
         (target (cdr (assoc class *class-groups* :test #'string=))))
    (when target
      (let ((group (stumpwm::find-group (current-screen) target)))
        (when group
          (debug-log "Regrouping ~A window to ~A group.~%" class group)
          (move-window-to-group win group)
          (stumpwm::update-all-mode-lines))))))

(add-hook *new-window-hook* 'regroup)


;;;; Load ---------------------------------------------------------------------
(load-module "pass")

;;;; Commands -----------------------------------------------------------------
(defcommand sane-hsplit () ()
  (hsplit)
  (move-focus :right))

(defcommand sane-vsplit () ()
  (vsplit)
  (move-focus :down))

(defcommand sane-move-window (direction)
    ((:direction "Enter a direction: "))
  (banish)
  (move-window direction))

(defcommand move-focus* (direction)
    ((:direction "Enter a direction: "))
  (labels ((in-float-p ()
             (typep (current-group) 'stumpwm::float-group))
           (focus-first-frame ()
             (unless (in-float-p)
               (dotimes (i 10)
                 (move-focus (ecase direction
                               (:left :right)
                               (:right :left))))))
           (next-group ()
             (ecase direction
               (:right (gnext))
               (:left (gprev)))
             (focus-first-frame)))
    (unless (in-float-p)
      (banish))
    (if (in-float-p)
      (next-group)
      (let ((frame (current-frame)))
        (move-focus direction)
        (when (eql frame (current-frame))
          (next-group))))))

(defcommand screen-single () ()
  (loop with laptop = "eDP1"
        with extern = "HDMI2"
        for (output commands) in `((,extern ("--off"))
                                   ;; (,rhs-name ("--auto"))
                                   ;; (,rhs-name ("--primary"))
                                   (,laptop ("--off"))
                                   (,laptop ("--auto"))
                                   ;; (,laptop ("--left-of" ,rhs-name))
                                   ;; (,laptop ("--rotate" "left"))
                                   )
        do (uiop:run-program `("xrandr" "--output" ,output ,@commands))))

(defcommand screen-multi () ()
  (loop with laptop = "eDP1"
        with extern = "DP1"
        for (output commands) in `((,laptop ("--off"))
                                   (,extern ("--off"))
                                   (,laptop ("--auto"))
                                   (,laptop ("--primary"))
                                   (,extern ("--mode" "3440x1440"))
                                   (,extern ("--left-of" ,laptop)))
        do (uiop:run-program `("xrandr" "--output" ,output ,@commands))))

(defcommand vlime () ()
  (load "~/src/dotfiles/vim/bundle/vlime/lisp/start-vlime.lisp")
  (message "Started VLIME"))

(defcommand toggle-current-mode-line () ()
  (toggle-mode-line (current-screen) (current-head)))

(defcommand pass-personal () ()
  (let ((pass:*password-store* "/home/sjl/Dropbox/password-store/"))
    (pass:pass-copy)))

;; (defcommand pass-work () ()
;;   (let ((pass:*password-store* "/home/sjl/.password-store-work/")
;;         (pass:*pass* "/home/sjl/src/dotfiles/bin/pass-work"))
;;     (pass:pass-copy)))


;;;; Applications -------------------------------------------------------------
(defcommand spotify () ()
  (run-or-raise "spotify" '(:class "Spotify")))

(defcommand intellij () ()
  (run-or-raise "~/intellij/bin/idea.sh" '(:class "jetbrains-idea-ce")))

(defcommand browser () ()
  (run-shell-command
    (hostcase
      (:bitdumpster "google-chrome")
      (t "firefox"))))


;;;; Key Mapping --------------------------------------------------------------
(defmacro define-top-keys (&body keyforms)
  `(progn ,@(loop :for form :in keyforms
                  :collect `(define-key *top-map*
                              (kbd ,(first form))
                              ,(second form)))))


(define-top-keys ;; application shortcuts
  ("H-m" "exec st")
  ("H-\\" "pass-personal")
  ;; ("H-|" "pass-work")
  ("H-b" "browser")
  ("H-o" "spotify")
  ("H-I" "intellij")
  ("H-q" "exec slock")
  ("H-y" "exec scrot 'screenshot_%Y-%m-%d_%H-%M-%S.png' -s -e 'mv $f ~/screenshots && echo -n ~/screenshots/$f' | xclip -sel clip")
  ("H-Y" "exec scrot 'screenshot_%Y-%m-%d_%H-%M-%S.png' -m    'mv $f ~/screenshots && echo -n ~/screenshots/$f' | xclip -sel clip")
  ("H-r" "loadrc")
  ("H-V" "vlime"))

(define-top-keys ;; movement
  ("H-h" "move-focus* left")
  ("H-j" "move-focus down")
  ("H-k" "move-focus up")
  ("H-l" "move-focus* right")

  ("H-H" "sane-move-window left")
  ("H-J" "sane-move-window down")
  ("H-K" "sane-move-window up")
  ("H-L" "sane-move-window right")

  ("H-n" "next-in-frame")
  ("H-p" "prev-in-frame")
  ("H-N" "pull-hidden-next"))

(define-top-keys ;; splitting
  ("H-s" "sane-vsplit")
  ("H-v" "sane-hsplit"))

(define-top-keys ;; killing
  ("H-w" "delete")
  ("H-W" "kill")
  ("H-BackSpace" "remove"))

(define-top-keys ;; screen
  ("H-F5" "exec xbacklight -dec 10")
  ("H-F6" "exec xbacklight -inc 10")
  ("H-F7" "screen-single")
  ("H-F8" "screen-multi"))

(define-top-keys ;; sound
  ("H-F2" "exec amixer -q sset Master 5%-")
  ("H-F3" "exec amixer -q sset Master 5%+"))

(define-top-keys ;; stump
  ("H-F9" "exec systemctl suspend")
  ("H-F10" "exec keysettings")
  ("Pause" "exec st") ; jesus christ
  ("H-F11" "toggle-current-mode-line")
  ("H-F12" "restart-hard"))


(stumpwm::unbind-remapped-keys)
(define-remapped-keys
  '(("st-256color"
     ("s-c" . "C-C")
     ("s-v" . "C-V"))
    ("Firefox"
     ("s-1" . "C-S-Tab")
     ("s-2" . "C-Tab")
     ("s-z" . "C-z")
     ("s-x" . "C-x")
     ("s-c" . "C-c")
     ("s-v" . "C-v"))
    (""
     ("s-z" . "C-z")
     ("s-x" . "C-x")
     ("s-c" . "C-c")
     ("s-v" . "C-v"))))


;;;; Modeline -----------------------------------------------------------------
(defun configure-modeline ()
  (setf
    *time-modeline-string*
    "%a %b %e %H:%M"

    *screen-mode-line-format*
    (append (list
              "[^B%n^b] %W^>"
              ;; "(V "
              ;; ;; '(:eval (volume))
              ;; ")"
              " ")
            (hostcase
              (:bitdumpster '("(B "
                              (:eval (battery))
                              ")")))
            (list
              " %d %T")))

  (setf *mode-line-timeout* 10)
  (setf *mode-line-background-color* "#111111")

  (ensure-mode-line))

(configure-modeline)


;;;; System Tray --------------------------------------------------------------
(load-module "stumptray")
(run-commands "stumptray")

(run-shell-command "nm-applet --sm-disable")
(run-shell-command "~/.dropbox-dist/dropboxd")
(run-shell-command "/usr/bin/dunst -conf ~/.dunstrc")