dotfiles/mowedline/.config/mowedline/init.org

5.7 KiB

Mowedline init

Load the matchable module so I can use match-lambda.

  (use matchable dbus)

Set the default font and color to something nicer.

  (text-widget-font "Fantasque Sans Mono-13:bold")
  (text-widget-color "#ededed")

Define a convenience function to check if a formatter's argument is not some text.

  (define (not-text? text)
    (or (null? text) (and (not (pair? text)) (string-null? text))))

Define a convenience function that adds spaces around its argument if its argument is text.

  (define (text-maybe-pad-both text)
    (if (not-text? text)
        text
        (list " " text " ")))

Define a convenience function to add a Font Awesome icon to a widget.

  (define (add-fa-icon icon)
    (lambda (text)
      (if (not-text? text)
          text
          (list (list 'font "FontAwesome-10"
                      (string-append " " icon " "))
                text))))

Tag list

This formatter will parse the herbstluftwm tag status line, which looks like this:

  #1  -2  :3  :4  :5  .6  .7  .8  .9

And turn it into something more useful. The symbols before the tag names (numbers) have the following meaning:

#
This tag is currently active.
-
This tag is visible on another monitor.
:
This tag isn't displayed, but has windows on it.
.
This tag isn't displayed and is empty.
!
This tag has an urgent window on it.

First the tag line has to be split into separate parts. Each tag status/name pair is split by a tab character and each status is only one character. So I split the whole string on tabs and then make a list out of each individual part, for easy access to the status character. So we end up with something like:

  ((#\# #\1) (#\- #\2) (#\: #\3) ...)
  (define (split-tag-list str)
    (map string->list (string-split str "\t")))

Next we turn each part into something practical for display in mowedline.

  (define tag-display
    (match-lambda
     ((#\# . name-list)
      (list '(color "#ececec" font "FontAwesome-10" "")
            (string-append " " (list->string name-list) " ")))
     ((#\- . _) '((color "#bfbfbf" font "FontAwesome-10" "") " "))
     ((#\: . _) '((color "#969696" font "FontAwesome-10" "") " "))
     ((#\! . _) '((color "#a85454" font "FontAwesome-10" "") " "))
     (_ '())))

  (define (tag-list-display tag-list)
    (map tag-display tag-list))

Finally, bring it all together in a function that can be used as a mowedline text formatter.

  (define (tag-list-formatter text)
    (tag-list-display (split-tag-list text)))

Define the widget to be used in the window.

  (define taglist-widget
    (widget:text #:name "taglist" #:format tag-list-formatter))

Email

Define a widget to show email notifications in.

  (define email-widget
    (widget:text
     #:name "email"
     #:format (compose text-maybe-pad-left (add-fa-icon ""))))

Battery

I'm on a laptop and seeing the state of my battery is pretty important.

  (define (clamp x low high)
    (max low (min high x)))

  (define (source:sys)
    (list
     (/ (clamp (with-input-from-file
                   "/sys/class/power_supply/BAT0/capacity"
                 read)
               0 100)
        100.0)
     (with-input-from-file
         "/sys/class/power_supply/BAT0/status"
       read)))

  (define (widget:battery)
    (widget:text
     font: "FontAwesome-10"
     format:
     (compose
      text-maybe-pad-left
      (match-lambda
       ((capacity status)
        (list
         (list-ref
          '((color "#a85454" "")
            (color "#a88654" "")
            (color "#8d995c" "")
            (color "#65a854" "")
            (color "#5476a8" ""))
          (inexact->exact
           (round (* 4 capacity))))
         (if (eq? 'Charging status) " " "")))
       (val val)))
     init: (lambda (widget)
             (widget-update-at-interval widget 5 source:sys))))

The window

Create a mowedline window, put it at the bottom.

  (define clipboard-widget
    (widget:text #:format text-maybe-pad-left))

  (let ((ctx (make-context #:service 'org.gnome.GPaste
                           #:interface 'org.gnome.GPaste1
                           #:path "/org/gnome/GPaste")))
    (register-signal-handler ctx
                             "Update"
                             (lambda (type replace id)
                               (update clipboard-widget "Text copied!")
                               (thread-start! (make-thread (lambda ()
                                                             (thread-sleep! 3)
                                                             (update clipboard-widget "")))))))

  (window #:position 'bottom
          #:width 1843
          #:margin-bottom 15
          #:margin-left 46
          #:margin-right 15
          #:background 'transparent

          taglist-widget

          (widget:spacer #:flex 1)

          clipboard-widget
          (widget:text #:name "irc" #:format (lambda (text) (text-maybe-pad-left (with-input-from-string text read))))
          email-widget
          (widget:battery)
          (widget:clock #:format text-maybe-pad-left))