=dtao-guile= is still under development, so proceed with caution!
** Features This Guix Home service will:
** Guix channel We provide =home-service-dtao-guile= in a Guix channel.
Add the channel to your =~/.config/guix/channels.scm=:
(channel (name 'home-service-dtao-guile) (url "https://github.com/engstrand-config/home-service-dtao-guile") (branch "main") (introduction (make-channel-introduction "64d0b70c547095ddc840dd07424b9a46ccc2e64e" (openpgp-fingerprint "C9BE B8A0 4458 FDDF 1268 1B39 029D 8EB7 7E18 D68C"))))
Afterwards, run =guix pull=.
** Usage
*** Home service configuration Enable =home-service-dtao-guile= by adding it to your list of home services.
;; Import the service (use-modules (dtao-guile home-service))
;; Create and add the dtao-guile home service to your home configuration. (service home-dtao-guile-service-type (home-dtao-guile-configuration ;; Optionally use a custom dtao-guile package. (package my-custom-dtao-guile) ;; Start dtao-guile on login, defaults to true. (auto-start? #t) ;; Create a custom configuration for dtao. (config (dtao-config ...))))
*** Shepherd service A Shepherd service wil be added after you have enabled the dtao-guile home service and reconfigured the system. This allows you to control the =dtao-guile= executable with the =herd= command, for example:
herd start dtao-guile herd stop dtao-guile herd restart dtao-guile
Logs are available at =$XDG_LOG_HOME/dtao-guile.log= (logs will be saved to your home directory if =$XDG_LOG_HOME= is not set).
*** Configuring =dtao-guile=
All configuration is done in the =dtao-config= record of the =config= field of the home service configuration.
(dtao-config
;; A font string in fcft format.
(font "monospace:style=bold:size=12")
;; Read root',
border' and `text' colors from dwl-guile.
(use-dwl-guile-colorscheme? #t)
(background-color "111111AA")
(border-color "333333FF")
(foreground-color "FFFFFFFF")
(padding-left 8)
(padding-right 8)
(padding-top 2)
(padding-bottom 2)
;; Request an exclusive zone for the bar to prevent overlapping.
(exclusive? #t)
;; Layer to render the bar in (LAYER-TOP, LAYER-BOTTOM, LAYER-OVERLAY, LAYER-BACKGROUND).
(layer 'LAYER-BOTTOM)
;; Render the bar at the bottom of the screen.
(bottom? #f)
;; Height of the bar in pixels. Set to #f for automatic height based on font size.
(height #f)
;; Delimiter string of arbitrary length inserted between blocks.
(delimiter #f)
;; Additional spacing on each side of the delimiter string.
(block-spacing 0)
(left-blocks '())
(center-blocks '())
(right-blocks '())
;; List of Guile module dependencies needed to run your blocks.
(modules '()))
*** Defining blocks
Status bar blocks are defined through =dtao-block= records with the following structure:
(dtao-block
(render (...)) (click
(...))
;; Signal (RTMIN to RTMAX) to trigger a re-render.
(signal #f)
;; Listen for dwl-guile events like updated title, tag layout etc. upon which to instantly re-rerender the block.
(events? #f)
;; Update interval time in seconds. The block will not update automatically if the interval <= 0.
(interval 0))
For example, a block that shows the date and time, that is updated every second:
(dtao-block (interval 1) (render `(strftime "%A, %d %b (w.%V) %T" (localtime (current-time)))))
*** =dwl= integration
=dtao-guile= has Guile bindings for capturing =dwl= state and events, such as retrieving the title of the currently selected client:
(dtao-block (events? #t) ;; Must be enabled to correctly re-render upon event/state change (render `(dtao:title)))
The following snippet defines the behavior and colors of the tag and layout indicators in =dwl=:
(define %tags-and-layout
(append
(map
(lambda (tag)
(let ((str (string-append "^p(8)" (number->string tag) "^p(8)"))
(index (- tag 1)))
(dtao-block
(interval 0)
(events? #t)
(click (match button (0 (dtao:view ,index)))) (render
(cond
((dtao:selected-tag? ,index)
,(string-append "^bg(#ffcc00)^fg(#191919)" str "^fg()^bg()"))
((dtao:urgent-tag? ,index)
,(string-append "^bg(#ff0000)^fg(#ffffff)" str "^fg()^bg()"))
((dtao:active-tag? ,index)
,(string-append "^bg(#323232)^fg(#ffffff)" str "^fg()^bg()"))
(else ,str))))))
(iota 9 1))
(list
(dtao-block
(events? #t)
(click (dtao:next-layout)) (render
(string-append "^p(4)" (dtao:get-layout)))))))
As the =(lambda (tag) ...)= and =(iota 9 1)= expressions suggest, there are 9 tags in the bar, each with an individual =dtao-block= record.
In the picture below (rendered by the above code snippet), tag 1 is the currently selected tag, so =dtao:selected-tag?= equals =#t= for its block. Tag 2 has one or more active clients assigned to it, which means that =dtao:active-tag?= equals =#t=. Tags 3 to 9 are not selected and have no windows assigned to them. The current layout --- shown as =[]== --- is the default =dwl= tiling layout.
[[./images/tags.png]]
*** C bindings All =libguile= bindings in the =dtao-guile= C source (i.e. the =dtao:...= procedures) are available [[https://github.com/engstrand-config/dtao-guile/blob/a1b2baefa8542e018787009ddb0254fdcfb9d413/dscm-bindings.h#L173-L216][here]].
** Example configuration You can find a working example in [[https://github.com/engstrand-config/guix-dotfiles/blob/main/engstrand/features/statusbar.scm][our GNU Guix configuration]], in the [[https://github.com/engstrand-config/guix-dotfiles/blob/main/engstrand/features/statusbar.scm][ =engstrand/features/statusbar.scm= ]] file.