Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/russmatney/clawe

Clojure REPL-based WM hacking on linux and osx
https://github.com/russmatney/clawe

awesomewm babashka clojure yabai

Last synced: 2 months ago
JSON representation

Clojure REPL-based WM hacking on linux and osx

Awesome Lists containing this project

README

        

#+TITLE: Clawe
#+startup: overview

#+html:


#+html:

#+html:
#+html: Mastodon Badge
#+html:

#+html:
#+html: Twitch Badge
#+html:

#+html:
#+html: Patreon Badge
#+html:

#+html:
#+html: Discord
#+html:

#+html:

#+html:
#+html:


#+html: Hi there! I'm Russ!
#+html:
#+html:


#+html:

I'm putting together an overview of this whole project [[https://russmatney.com/note/clawe_overview_video.html][on my blog]].

A stream covering the motivation and showing some of the namespaces is available
[[https://www.twitch.tv/videos/1805970411?t=2h59m42s][on twitch]].

I hope to cut it to something shorter and more presentable soon!

--

#+begin_quote Toy Story
Buzz: This is an intergalactic emergency. I need to commandeer your vessel to Sector 12. Who's in charge here?

All Aliens: [pointing up] The clawwwwwwwww[e]!

Alien #1: The claw is our master.

Alien #2: The claw chooses who will go and who will stay.

Woody: This is ludicrous.
#+end_quote

For more on Clawe beyond the below readme, check out the [[https://russmatney.com/note/clawe.html][clawe garden file]] on my blog.

* Clawe is a clojure-centric window-manager, uh, -manager
It is named after the shape of your hand while trying to nail some of these key
bindings.

It started as a CLojure-AWEsomewm experiement, but now cuts off any specific WM
via a protocol, and can run on OSX (via yabai) as well.

Clawe is a clojure-based approach to managing your window manager's
configuration, and otherwise hacking scripts/automation together on your
machine.

** Clawe feature list
- Dev against your environment with a clojure repl!
- No more write-compile-restart-loop!
- Instead, debug by connecting to a running clojure repl and execing the code.
- Define your keybindings as clojure functions
- [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/clawe/defs/bindings.clj][clawe.defs.bindings namespace]]
- Configurable, toggle-able clients that can be repo-workspace aware
- [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/clawe/toggle.clj][clawe.toggle namespace]]
- [[https://github.com/davatorium/rofi][Rofi]] (or via [[https://github.com/chipsenkbeil/choose][choose]] on osx) for listing available commands
- [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/clawe/m_x.clj][clawe.mx]] and [[https://github.com/russmatney/clawe/blob/master/src/ralphie/rofi.clj][ralphie.rofi]] namespaces
- Useful Babashka-based namespaces
- [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/ralphie/browser.clj][ralphie.browser]]
- [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/ralphie/clipboard.clj][ralphie.clipboard]]
- [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/ralphie/emacs.clj][ralphie.emacs]]
- [[https://github.com/russmatney/clawe/blob/master/src/ralphie/git.clj][ralphie.git]]
- [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/ralphie/notify.clj][ralphie.notify]]
- [[https://github.com/russmatney/clawe/blob/master/src/ralphie/screenshot.clj][ralphie.screenshot]]
- [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/ralphie/tmux.clj][ralphie.tmux]]
- [[https://github.com/russmatney/clawe/tree/master/src/ralphie][all ralphie namespaces]]
- [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/ralphie/git.clj#L101][suggesting git clones based on the clipboard and current tabs]]

** ~clawe.wm~ and ~clawe.wm.protocol~
[[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/clawe/wm.clj][clawe.wm]] provides functions for working with your running clients and
workspaces:

Ex:

- ~clawe.wm/focus-client~
- ~clawe.wm/delete-workspace~

These functions are implemented via a [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/clawe/wm/protocol.clj][protocol]], which means extending the same
behavior to other window-managers is fairly reasonable. I've implemented it for
AwesomeWM and Yabai so far, but am interested in pursuing i3 and bspwm as well.

- [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/ralphie/awesome.clj][ralphie.awesome]]
- [[https://github.com/russmatney/clawe/blob/db7042b02ba8ed9f8dc35f98c901a8ff5d07953b/src/ralphie/yabai.clj][ralphie.yabai]]
** Babashka-based
Much gratitude to borkdude and the clojure community at large!

Clawe would not be possible without the boon that [[https://github.com/babashka/babashka][Babashka]] has brought to the
clojure ecosystem. Simplicity + performance!
*** [[https://github.com/babashka/process][process]]
Clawe uses process everywhere, to shell out and do everything. It's the
equivalent of ~$()~ in bash.
*** [[https://github.com/babashka/cli][cli]]
Nearly all of clawe's commands are executed almost exclusively as babashka cli commands:

#+begin_src sh
# Toggle open/closed emacs in the current workspace's directory
bb ~/russmatney/clawe/bb.edn -x clawe.toggle/toggle "emacs"
#+end_src

This is of course often better debugged in a clojure repl itself:

#+begin_src clojure
(comment (clawe.toggle/toggle "emacs"))
#+end_src
** To cover in more detail
*** ~resources/clawe.edn~
*** sxhkd/awesome config on linux
*** yabai/skhd config on osx
** Future work
*** Break up ~clawe.edn~ usage into personal configs
*** refactor/hone keybindings implementation
** Old methods
*** Clawe microscripts? uberjar?
Clawe has been through a few different iterations and experiements - at one
point I was using carve to produce 'micro'-scripts in an effort to improve
performance.

Later I had an uberjar flow, which required rebuilding after code changes were
made.

Lately I'm in favor of using the babashka/cli style - just run the scripts in
place, call the functions directly with ~-x~. This has been great and nice to
debug both in the repl and via the terminal. It's also simple, in that there are
no built artifacts to worry about. I expect this method to stick!
* Doctor, Tauri, and full-stack clojure
~doctor~ and most of the other top-level namespaces in clawe are used in a
full-on JVM or browser context. The above clawe features are all babashka-based,
but with ~doctor~, we get into support for topbars, dashboards, parsing org
files, reviewing chess games, publishing blog posts... all sorts of rabbit holes.

It may have been wise to cut clawe at the above feature set (and I did just
that before one day throwing up my hands and combining several repos together).

Instead I've been hacking deeper features right on top of it. Keeping things in
the same repo lowers the barrier for trying out new things, and at this point
the clawe repo has several runtimes.

** Multiple runtimes
In particular, the 'doctor' backend is jvm based, and not all of the
clojure dependencies are babashka compatible.

There are 4 runtimes to be aware of.
*** the 'bash' runtime (i.e. babashka)
the ~clawe~ and ~ralphie~ namespaces are intended to be consumed by babashka
commands, and should be simple, fast, and (mostly) stateless. A clawe.edn
config file is read for most of them to work, but that should be it.
*** the backend 'server' (doctor backend)
A backend server process running via the jvm - the typical clojure environment,
providing a web api and sockets for connecting to the doctor frontend.

Worth noting - this server provides an nrepl for the clawe/ralphie namespaces to
connect to, and is where most of clawe's development happens.
*** the web frontend (doctor frontend)
A shadow-cljs process runs the typical frontend clojurescript environment.
*** Tauri topbar, doctor
Tauri is used, really just for it's webview, to serve the topbar and a 'native'
doctor web app (though I often work in a [[https://www.mozilla.org/en-US/firefox/developer/][proper dev browser]] as well.)

Lately this is impled via `clove`, which wraps a Tauri app and exposes an api
for launching transparent apps at arbitrary urls.

See the [[https://github.com/russmatney/clove][clove repo]] for install instructions.
** Doctor features
With those runtime distinctions in mind...

Doctor is not quite as settled as clawe and ralphie, but it is centered around
some core features:

- Topbar
- workspaces and their clients (current workspace, etc)
- queued tasks
(todos are parsed from org files and opted into via the doctor's components)
- Dashboard
- in various views
- org items (parsed and crud-able via [[https://github.com/russmatney/org-crud][russmatney/org-crud]])
- commits from repos (parsed via ~ralphie/git~)
- recent screenshots
- recent games from [[https://lichess.org][lichess.org]]
- setting wallpapers
- Sockets via [[https://github.com/teknql/plasma][teknql/plasma]]
- Database via [[https://github.com/tonsky/datascript][tonsky/datascript]]

As more doctor features/interfaces settle down, I'll update these docs with
screenshots and usage details.
* Rough Dev Notes
** local symlinking
several local dirs are symlinked into public/assets/

#+begin_src sh
# from clawe root dir
ln -s ~/Screenshots public/assets/screenshots
ln -s ~/gifs public/assets/clips
ln -s ~/Dropbox/wallpapers public/assets/wallpapers
#+end_src

#+begin_src
l ~/russmatney/clawe/public/assets/
Name
candy-icons -> /home/russ/EliverLara/candy-icons/apps/scalable/
screenshots -> /home/russ/Screenshots/
wallpapers -> /home/russ/Dropbox/wallpapers/
#+end_src

This is a quick hack to let the web apps reference images on the machine
(avoids a local image host).

** Chessground
I manually copied the exported css and images into the project:

#+begin_src sh
cp node_modules/chessground/assets/chessground.base.css node_modules/chessground/assets/chessground.brown.css node_modules/chessground/assets/chessground.cburnett.css public/css/.
#+end_src

** tauri via ~russmatney/clove~ conf

~clove~ is a barebones tauri cli. It accepts a title and url, then launches a
tauri webview harness around that url. It sets the window to transparent by
default, so if you want a background, be sure to set one!

The goal is to support local web apps (like the doctor frontend) without
requiring a full browser to use them. I.e. don't let your dashboard get lost in
your browser tabs.

See the [[https://github.com/russmatney/clove][clove repo]] for install instructions.

* Ping me!
I feel like this is kind of a crazy hack/dev environment - to me, getting to do
wm-things in clojure and against a repl is the dream!

I've been building it up for a few years now, and am happy to give a tour and
share more context.

Feel free to create an issue/discussion in this repo, ping me ~@russmatney~ on
the clojurians slack, or pop in on [[https://www.twitch.tv/russmatney][one of my Twitch streams]] - I'd love to share
more about it and show how it all fits together.

* Dev Notes
** Running tests
*** Clawe Unit tests
#+begin_src sh
./test_runner.clj
#+end_src

Runs some babashka-based clawe unit tests.

*** JVM Unit tests
#+begin_src sh
./bin/kaocha unit
#+end_src
*** CLJS tests
Bit of a wip for the moment, but hopefully there's a one-line approach to
running these soon.

*** Clawe integration tests
These tests exercise the window manager _in place_ - i.e. this will create and
destory workspaces in your current environment.

#+begin_src sh
./bin/kaocha integration
#+end_src

These don't run in CI, but are a useful way to debug or ensure basic clawe usage
isn't borked.

*** AwesomeWM tests
Expects a running awesomewm and fennel setup, which unfortunately is not well
documented or easily created at the moment.

#+begin_src sh
./bin/kaocha awesomewm
#+end_src