Merge branch 'master' into acpi-backlight

This commit is contained in:
David 2022-06-13 21:06:24 -04:00 committed by GitHub
commit 9de5049e78
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 445 additions and 19 deletions

View file

@ -71,6 +71,7 @@ Advertise your module here, open a PR and include a org-mode link!
- [[https://gitlab.com/sasanidas/stumpwm-dmenu][stumpwm-dmenu]] :: StumpWM [[https://tools.suckless.org/dmenu/][dmenu]] integration
- [[https://github.com/Junker/stumpwm-pamixer][stumpwm-pamixer]] :: Pulseaudio volume and microphone control module
- [[https://github.com/Junker/stumpwm-acpi-backlight][stumpwm-acpi-backlight]] :: ACPI backlight control module for StumpWM
* Current Modules
(click for its respective README/docs)
@ -125,6 +126,7 @@ Advertise your module here, open a PR and include a org-mode link!
- [[./util/screenshot/README.org][screenshot]] :: Takes screenshots and stores them as png files
- [[./util/searchengines/README.org][searchengines]] :: Allows searching text using prompt or clipboard contents with various search engines
- [[./util/shell-command-history/README.org][shell-command-history]] :: Save and load the stumpwm::*input-shell-history* to a file
- [[./util/spatial-groups/README][spatial-groups]] :: Spatial Groups navigation for StumpWM
- [[./util/stump-backlight/README.org][stump-backlight]] :: Native backlight control from StumpWM
- [[./util/stump-lock/README.org][stump-lock]] :: Screen locker in StumpWM
- [[./util/stump-nm/README.org][stump-nm]] :: StumpWM integration with NetworkManager

View file

@ -3,6 +3,6 @@
:description "Alert me that an event is coming"
:author "Florian Margaine <florian@margaine.com>"
:license "GPLv3"
:depends-on (:bordeaux-threads :stumpwm)
:depends-on (:uiop :bordeaux-threads :stumpwm :notifications)
:components ((:file "package")
(:file "alert-me")))

View file

@ -1,35 +1,75 @@
(in-package #:alert-me)
(stumpwm:defcommand alert-me-at (alert-hour alert-minute message) ((:number "hour: ") (:number "minute: ") (:string "message: "))
(defvar *alert-sound-file* #p"~/Music/bell.wav"
"When set to a sound file pathname, plays on alert.")
(defvar *sound-play-command* "aplay"
"System command to play sounds.")
(defvar notifications-loaded
(when (member "notifications" (asdf:already-loaded-systems)
:test #'string-equal) t)
"True when StumpWM-Contrib `Notifications` module is loaded.")
(defun ring-alert ()
"Play the *ALERT-SOUND-FILE* if exists."
(when (probe-file *alert-sound-file*)
(uiop:run-program
(format nil "~a ~a" *sound-play-command* (namestring *alert-sound-file*)))))
(defun alert-message (alert-hour alert-minute message)
(format nil "^[^3 ~2,'0d:~2,'0d ^2~a ^]"
alert-hour alert-minute message))
(stumpwm:defcommand alert-me-at (alert-hour alert-minute message)
((:number "hour: ") (:number "minute: ") (:string "message: "))
"Alert me at some point in time."
(unless (validate-alert alert-hour alert-minute message)
(error "One of the parameters is either empty or wrong."))
(bordeaux-threads:make-thread
#'(lambda ()
(stumpwm:message "Alert is set: ~a"
(alert-message alert-hour alert-minute message))
(loop
do (sleep 5)
when (multiple-value-bind (seconds minute hour)
(get-decoded-time)
(declare (ignore seconds))
(and (= alert-hour hour) (= alert-minute minute)))
do (repeat-with-delay 10 3
#'(lambda (count)
(stumpwm:message "The time for ~A is now! (~D/3 remainder)"
message (1+ count))))))
do (sleep 5)
when (multiple-value-bind (seconds minute hour)
(get-decoded-time)
(declare (ignore seconds))
(and (= alert-hour hour) (= alert-minute minute)))
do (progn
(when notifications-loaded
(notifications:notifications-add
(alert-message alert-hour alert-minute message)))
(repeat-with-delay
10 3
#'(lambda (count)
(stumpwm:message "~a ^[^4[^1 ~d/3 ^4] ^]"
(alert-message alert-hour alert-minute message)
(1+ count))
(ring-alert)))
(return))))
:name (format nil "Alert thread: ~A" message)))
(defun validate-alert (alert-hour alert-minute message)
(unless (or alert-hour alert-minute message)
(return-from validate-alert nil))
(multiple-value-bind (seconds minute hour)
(get-decoded-time)
(declare (ignore seconds))
(when (> hour alert-hour)
(return-from validate-alert nil))
(when (>= minute alert-minute)
(when (or (> hour alert-hour)
(and (= hour alert-hour)
(>= minute alert-minute)))
(return-from validate-alert nil)))
t)
(defun repeat-with-delay (delay times fn)
(dotimes (i times)
(apply fn `(,i))

View file

@ -35,6 +35,10 @@ at the end of each pomodoro.")
"Counter of finished pomodoros in a series.")
(defparameter *pomodoro-timer* nil
"The pomodoro timer clock object.")
(defun update-status-message ()
(when notifications-loaded
(notifications:notifications-delete status-message))
@ -53,7 +57,7 @@ at the end of each pomodoro.")
(ring-the-bell))
(defparameter *pomodoro-timer*
(setf *pomodoro-timer*
(sb-ext:make-timer #'swm-pomodoro::finish-timer
:name :pomodoro-timer))
@ -67,8 +71,8 @@ at the end of each pomodoro.")
(defun ring-the-bell ()
"Play the *BELL-SOUND-FILE* if exists."
(when (probe-file *bell-sound-file*)
(asdf:run-shell-command
"~a ~a" *sound-play-command* (namestring *bell-sound-file*))))
(uiop:run-program
(format nil "~a ~a" *sound-play-command* (namestring *bell-sound-file*)))))
(defun notify-break ()

View file

@ -6,6 +6,6 @@
:license "GPLv3"
:version "0.2.0"
:serial t
:depends-on (#:stumpwm)
:depends-on (#:uiop #:stumpwm #:notifications)
:components ((:file "package")
(:file "swm-pomodoro")))

159
util/spatial-groups/README Normal file
View file

@ -0,0 +1,159 @@
This repo contains code implementing Spatial Groups for StumpWM.
======================================================================
Installation:
Please see https://github.com/stumpwm/stumpwm/wiki/Modules for how to
install the stumpwm-contrib collection.
Otherwise, manually:
mkdir ~/.stumpwm.d/modules (if needed)
git clone https://github.com/stumpwm/stumpwm-contrib ~/.stumpwm.d/modules
In your .stumpwmrc, add the following:
(in-package :stumpwm)
(load-module "spatial-groups")
(spatial-groups:install-default-keybinds) ; optional
Restart stumpwm.
======================================================================
From the original post:
http://demosthenes.org/tmp/StumpWMSpatialGroups.mp4
Please pardon the rough edges. I'm not starting a Youtube channel,
just trying to have a conversation about how to manage windows and
groups in Stump.
Spatial grouping abuses Stump's ability to dynamically create groups
to create a sparse 3d array of groups, visualized as multiple desktops
of a 2d grid of screens. Hotkeys use arrows to navigate the grid and
swap desktops in a way which emulates a larger physical screen
surface.
Using this method allows me to group windows by project, adjacent to
each other. This allows absolute navigation to each window, as opposed
to relative navigation (ie: alt-tab).
I'm not grouping related application windows on the same screen, but
rather organizing patterns of groups to keep related application
windows cognitively near each other. I still may use splits and tile
windows within a screen, but not as often.
Concepts:
Spatial groups use a 3d coordinate system: “x,y,z”
Valid groups are “0,0,0”, “-1,2,0”, etc.
Z is used as the desktop index
Keys:
Control-Shift-{Left,Right}: Change desktop (Z axis)
Control-Arrows: Navigate virtual screens on current desktop
Control-Shift-Up: Return to 0,0 on current desktop (Z)
Shift-Arrows: Navigate splits on current screen group
======================================================================
This idea of spatial groupings I have been using since Enlightenment
in the early 2000's. E later dropped their virtual desktops with
expandable numbers of screens in a grid.
I've implemented this concept on xmonad, awesome WM, i3, and now
StumpWM (my fav).
My work style is to start a central task, and then supplemental tasks
should be organized radially from that central task. To do this, I use
a 2d plane of workspaces where I can easily layout my windows
geometrically and navigate them spatially in lieu of a desktop or tab
analogy. Multiple projects or key tasks are separated on separate
planes.
In this configuration, each workspace is a tag organized into a 3d
cube of workspaces described by a simple coordinate system. To
navigate between these workspaces, simple keybindings have been
created.
Example Workspace Plane:
The example plane below puts Emacs into the central window, surrounded
by supplimental windows that help support the central task.
At any time from the central window, any supplemental window is only
one key chord away (Control+Arrows). Habit and simple organization
gives way to always knowing where to go to find an item in relation to
the central workspace.
+-----------------------------------------------+----------------------+
| | | |
| | Supplement | |
| | | |
| | Firefox | |
| | | |
+----------------------------------------------------------------------+
| | | |
| Supplement | Central Task | Supplement |
| | | |
| SQL Window | EMACS | Documentation |
| | | |
+----------------------------------------------------------------------+
| | | |
| | Supplement | |
| | | |
| | Two shell prompts | |
| | | |
+-----------------------------------------------+----------------------+
There is no Alt-tab style confusion of trying to find the right window
in a dynamic stack. This organization also lends itself to full screen
windows, or relatively few tiles.
Second level supplementary windows can be created in the corners,
where they are at most two key chords from center. These are less
frequently used and may provide scratch space for additional windows.
The third dimension comes in when managing multiple core tasks in
parallel, where the advantage of easy radial addressing becomes a
concern for another project. The third dimension allows us to stack
workspaces, and toggle between them when it is time to change
projects.
+-----------------------------------------------+----------------------+
| 1,1,1 | | |
| | Supplement | |
| | | |
| | Firefox | |---------+
| | | | |
+----------------------------------------------------------------------+ |
| | | | |
| Supplement | Central Task | Supplement | |
| | | | |----------+
| SQL Window | EMACS | Documentation |---------+ |
| | | | | |
+----------------------------------------------------------------------+ | |
| | | | | |
| | Supplement | |on | |
| | | | |----------+
| | Two shell prompts | |---------+ |
| 1,3,1 | | | | |
+-----------------------------------------------+----------------------+ | |
| | | |ion |
| | Two shell prompts | | |
| 1,3,2 | | |----------+
+-----------------------------------------------+----------------------+ |
| | | |
| | Two shell prompts | |
| 1,3,3 | | |
+-----------------------------------------------+----------------------+
======================================================================
TODO:
- Multiple monitor support?
- Cleanup code

View file

@ -0,0 +1,50 @@
* Overview
This is just my notes file.
* Features
** DONE Complete moving to a module
CLOSED: [2022-03-08 Tue 18:03]
[2022-03-08 Tue 17:07]
nearly there, already used quickproject to create the basics
trying to port my config to use the module.
[2022-03-08 Tue 18:03]
ok, my personal stumpwmrc is now using the module!
here's a sample file:
#+BEGIN_EXAMPLE
;; -*-lisp-*-
;; Load my Spatial groups module from ~/.stumpwm/modules/ symlink to repo
(in-package :stumpwm)
(load-module "spatial-groups")
#+END_EXAMPLE
** TODO Add screenshotting feature
[2022-03-08 Tue 17:10]
i already have a function to take screenshots and create a montage of
the spatial environment in my dotfile.
** TODO Multiple monitor support
[2022-03-08 Tue 17:08]
i've only used this single screen. I imagine multiple monitors would
be like having adjacent screen cursors panning across the grid.
For example, if I had 2 screens (left and right), they would be
considered adjacent cursors. If I shifted the grid using
control-right, both screens would move over one.
This means that I may have to move one or more screens to "fake"
groups in the mean time, because one group can never be on more than
one screen.
Required further thought, and I don't have multiple screens on my laptop.
** TODO List windows in current desktop? Picker?

View file

@ -0,0 +1,7 @@
;;;; package.lisp
(defpackage #:spatial-groups
(:use #:cl #:stumpwm)
(:export *spatial-banish-on-move*
spatial-gselect
install-default-keybinds))

View file

@ -0,0 +1,11 @@
;;;; spatial-groups.asd
(asdf:defsystem #:spatial-groups
:description "Spatial Groups navigation for StumpWM"
:author "Russell Adams <rladams@adamsinfoserv.com>"
:license "GPL-v2"
:version "0.0.1"
:serial t
:depends-on (#:stumpwm)
:components ((:file "package")
(:file "spatial-groups")))

View file

@ -0,0 +1,153 @@
;; Spatial Groups for StumpWM
;;
;; Copyright (C) 2022 Russell Adams
;;
;; Maintainer: Russell Adams <rladams@adamsinfoserv.com>
;;
;; This module is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 2 of the License, or
;; (at your option) any later version.
;;
;; This module is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this software. If not, see <http://www.gnu.org/licenses/>.
;;; Usage:
;;
;; Just add the following line to your .stumpwmrc file:
;;
;; (load-module :stumpwm-spatial)
;;
(in-package :spatial-groups)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Define global vars
(defparameter *z-cursors* '()
"Association list of groups by Z coordinate for preserving last position on that plane.")
(defparameter *last-cursor* NIL
"Previous group name string for popping back.")
(defparameter *spatial-banish-on-move* t
"Banish the cursor to bottom right when switching screens? Defaults to true.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Coordinate commands
;; Control arrows between groups
(defcommand coord-left () () (coord-group-change -1 0 0))
(defcommand coord-right () () (coord-group-change 1 0 0))
(defcommand coord-up () () (coord-group-change 0 1 0))
(defcommand coord-down () () (coord-group-change 0 -1 0))
(defcommand coord-taskleft () () (coord-group-change 0 0 -1))
(defcommand coord-taskright () () (coord-group-change 0 0 1))
;; return to 0,0 on the current taskplane as a shortcut to return to the core task
(defcommand coord-taskorigin () ()
(gselect
(group-name
(spatial-find-group (current-screen)
(format nil "~{~a~^,~}" (list 0 0 (parse-integer (third (split-string (group-name (current-group)) ",")))))))))
;; pop back to last location
(defcommand coord-taskpop () () (when *last-cursor* (spatial-gselect *last-cursor*)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Key bindings for spatial group movement
(defun install-default-keybinds ()
"Install default keybinds. Use this as an example for making your own keybinds."
;; Shift arrows between adjacent frames on the current screen
(define-key *top-map* (kbd "S-Up") "move-focus up")
(define-key *top-map* (kbd "S-Down") "move-focus down")
(define-key *top-map* (kbd "S-Left") "move-focus left")
(define-key *top-map* (kbd "S-Right") "move-focus right")
;; Control arrows move between screens on the current desktop
(define-key *top-map* (kbd "C-Left") "coord-left")
(define-key *top-map* (kbd "C-Right") "coord-right")
(define-key *top-map* (kbd "C-Up") "coord-up")
(define-key *top-map* (kbd "C-Down") "coord-down")
;; Control-Shift left/right to switch desktop Z
(define-key *top-map* (kbd "C-S-Left") "coord-taskleft")
(define-key *top-map* (kbd "C-S-Right") "coord-taskright")
;; Control-Shift-Up to return to origin 0,0 on current desktop Z
(define-key *top-map* (kbd "C-S-Up") "coord-taskorigin")
;; "Pop" back to last desktop position
(define-key *top-map* (kbd "C-S-Down") "coord-taskpop") )
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Spatial groups and coordinate functions
;; Groups will manage the coordinate system
;; format: 0,0,0 with positive and negative numbers
;; create groups on the fly as needed
;; only supports one screen atm, would like multimonitor support later
(defun spatial-find-group (screen name)
"Simple function to find group by string name"
(find name (screen-groups screen) :key 'group-name :test 'string=))
(defun spatial-gselect (name)
"Wrap gselect, preserve prior location for pop, and handle when group is new"
(when *spatial-banish-on-move* (banish))
(setf *last-cursor* (group-name (current-group)))
(gselect (group-name
(or (spatial-find-group (current-screen) name)
(gnew name)))))
(defun coord-group-change (xo yo zo)
"Navigate a 3d array of groups using x,y,z coordinates by passing the offset of the change."
(let* ((current-coords
(mapcar #'parse-integer
(split-string (group-name (current-group)) ",")))
(new-coords (mapcar #'+ current-coords (list xo yo zo)))
(new-group-name (format nil "~{~a~^,~}" new-coords)) )
(if (= 0 zo)
;; Not changing desktop, so just move by coordinates
(spatial-gselect new-group-name)
;; Changing Z across desktops, RESTORE z-cursor for that plane
(let ((old-z (third current-coords))
(new-z (third new-coords)))
;; Save current location for desktop so we can return to same spot
(if (assoc old-z *z-cursors*)
(setf (cdr (assoc old-z *z-cursors*)) (current-group))
(push (cons old-z (current-group)) *z-cursors*))
;; Try to restore prior desktop location
(let ((z-cursor (cdr (or (assoc new-z *z-cursors*) '(nil . nil)))))
(if z-cursor
;; Restore saved location
(spatial-gselect (group-name z-cursor))
;; create new taskplane
(spatial-gselect new-group-name)))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Startup
(defun spatial-startup ()
"Must goto 0,0,0 on startup"
(spatial-gselect "0,0,0"))
(when *initializing* (spatial-startup))

View file

@ -1,6 +1,6 @@
** Commentary
I like surfraw (http://surfraw.alioth.debian.org). If you're
I like [[https://gitlab.com/surfraw/Surfraw][surfraw]]. If you're
reading this, you probably like surfraw. I've got surfraw-related
code in my .stumpwmrc, and (judging from some judicious googling
for RC files early on in my use of stumpwm) I know that I'm not the