[PATCH] home: services: Add 'home-sway-service-type'.

  • Done
  • quality assurance status badge
Details
4 participants
  • Arnaud Daby-Seesaram
  • Hilton Chain
  • Ludovic Courtès
  • pelzflorian (Florian Pelz)
Owner
unassigned
Submitted by
Arnaud Daby-Seesaram
Severity
normal
A
A
Arnaud Daby-Seesaram wrote on 19 Aug 17:30 +0200
(address . guix-patches@gnu.org)(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)
1e82e473639f21a2950a0827f156437ef1bc9c48.1724081442.git.ds-ac@nanein.fr
* gnu/home/services/sway.scm (home-sway-service-type): New variable.
(sway-configuration): New configuration record.
(sway-bar): New configuration record.
(sway-output): New configuration record.
(sway-input): New configuration record.
(point): New configuration record.
(sway-color): New configuration record.
(sway-border-color): New configuration record.
(flatten): New procedure.

Change-Id: Ia29a4173ce3a887d5fac3f57ba3819a52f9624d3
---
This patch provides an *experimental* home service to configure sway.

It defines a configuration record that contains fields for common
options of sway (an extra-contents field that can be used for
additional settings). The service also adds packages to the user
profile (notably sway).

Feedback is welcome !

Please note that (1) I only use Guile for Guix, so my code might be
clumsy and non-idiomatic¹ and (2) the patch is experimental, and will
need polishing before being merged. For example, I am not sure when I
should allow G-expressions in the configuration.
¹: feel free to share your opinions on
how to improve the code.

I have not written any documentation at the time (even documentation
strings in the configuration records are not well defined). I am
waiting for the code structure and configuration records to be
stable-ish to take the time to write a documentation.

gnu/home/services/sway.scm | 622 +++++++++++++++++++++++++++++++++++++
1 file changed, 622 insertions(+)
create mode 100644 gnu/home/services/sway.scm

Toggle diff (543 lines)
diff --git a/gnu/home/services/sway.scm b/gnu/home/services/sway.scm
new file mode 100644
index 0000000000..3f978d0bf0
--- /dev/null
+++ b/gnu/home/services/sway.scm
@@ -0,0 +1,622 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2024 Arnaud Daby-Seesaram <ds-ac@nanein.fr>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix 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 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix 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 GNU Guix. If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu home services sway)
+ #:use-module (guix monads)
+ #:use-module (guix modules)
+ #:use-module (guix gexp)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-26)
+ #:use-module (ice-9 popen)
+ #:use-module (ice-9 format)
+ #:use-module (ice-9 match)
+ #:use-module (guix packages)
+ #:use-module (gnu services configuration)
+ #:use-module (gnu home services)
+ #:use-module (gnu packages freedesktop)
+ #:use-module (gnu packages xdisorg)
+ #:use-module (gnu packages image)
+ #:use-module (gnu packages gnome)
+ #:use-module (gnu packages wm)
+ #:use-module (gnu packages emacs)
+ #:use-module (gnu packages linux)
+ #:use-module (gnu packages base)
+ #:use-module (gnu packages suckless)
+ #:use-module (gnu packages glib)
+ #:export (;; Accessors and predicates do not need to be exported.
+ sway-configuration
+ sway-bar
+ sway-output
+ sway-input
+ point
+ sway-color
+ sway-border-color
+ home-sway-service-type))
+
+;; Helper function.
+(define (flatten l)
+ (let loop ((lst l) (acc '()))
+ (match lst
+ (() acc)
+ ((head . tail)
+ (loop tail (append acc head))))))
+
+
+;;;
+;;; Default settings.
+;;;
+
+(define %sway-default-variables
+ `((mod . "Mod4")
+ (left . "h")
+ (down . "j")
+ (up . "k")
+ (right . "l")
+ (term . ,#~(string-append #$st "/bin/st"))
+ (menu . ,#~(string-append #$dmenu "/bin/dmenu_run"))))
+
+(define %sway-default-gestures
+ `((swipe:3:right . "workspace next_on_output")
+ (swipe:3:left . "workspace prev_on_output")
+ (swipe:3:down . "move to scratchpad")
+ (swipe:3:up . "scratchpad show")
+ (pinch:2:clockwise
+ . "move container to workspace prev_on_output")
+ (pinch:2:counterclockwise
+ . "move container to workspace next_on_output")
+ (swipe:4:left . "exec alacritty")
+ (swipe:4:right . "exec qutebrowser")
+ (swipe:4:down . "exec st")
+ (swipe:4:up
+ . ,#~(string-append
+ "exec " #$emacs "/bin/emacsclient -a '"
+ #$libnotify "/bin/notify-send Oups \"emacs not loaded :/\"' -c"))
+ (pinch:inward+right . "resize shrink width")
+ (pinch:inward+left . "resize grow width")
+ (pinch:inward+down . "resize shrink height")
+ (pinch:inward+up . "resize grow height")
+ (pinch:outward+up . "move up")
+ (pinch:outward+down . "move down")
+ (pinch:outward+left . "move left")
+ (pinch:outward+right . "move right")))
+
+(define %sway-default-keybindings
+ `(($mod+Shift+e
+ . ,#~(string-append
+ "exec " #$emacs
+ "/bin/emacsclient -a '"
+ #$libnotify "/bin/notify-send Oups \"emacs not loaded :/\"' -c"))
+ ($mod+Return . "exec $term")
+ ($mod+Shift+c . "kill")
+ ($mod+p . "exec $menu")
+ ($mod+Shift+r . "reload")
+ ($mod+Shift+q
+ . ,#~(string-append
+ "exec " #$sway "/bin/swaynag -t warning "
+ "-m 'You pressed the exit shortcut. Do you really want to exit sway?"
+ " This will end your Wayland session.'"
+ " -B 'Yes, exit sway' 'swaymsg exit'"))
+ ($mod+$left . "focus left")
+ ($mod+$right . "focus right")
+ ($mod+$up . "focus up")
+ ($mod+$down . "focus down")
+ ($mod+Shift+$left . "move left")
+ ($mod+Shift+$right . "move right")
+ ($mod+Shift+$up . "move up")
+ ($mod+Shift+$down . "move down")
+ ($mod+ampersand . "workspace number 1")
+ ($mod+eacute . "workspace number 2")
+ ($mod+quotedbl . "workspace number 3")
+ ($mod+apostrophe . "workspace number 4")
+ ($mod+parenleft . "workspace number 5")
+ ($mod+minus . "workspace number 6")
+ ($mod+egrave . "workspace number 7")
+ ($mod+underscore . "workspace number 8")
+ ($mod+ccedilla . "workspace number 9")
+ ($mod+agrave . "workspace number 10")
+ ($mod+Shift+ampersand . "move container to workspace number 1")
+ ($mod+Shift+eacute . "move container to workspace number 2")
+ ($mod+Shift+quotedbl . "move container to workspace number 3")
+ ($mod+Shift+apostrophe . "move container to workspace number 4")
+ ($mod+Shift+parenleft . "move container to workspace number 5")
+ ($mod+Shift+minus . "move container to workspace number 6")
+ ($mod+Shift+egrave . "move container to workspace number 7")
+ ($mod+Shift+underscore . "move container to workspace number 8")
+ ($mod+Shift+ccedilla . "move container to workspace number 9")
+ ($mod+Shift+agrave . "move container to workspace number 10")
+ ($mod+b . "splith")
+ ($mod+v . "splitv")
+ ($mod+s . "layout stacking")
+ ($mod+w . "layout tabbed")
+ ($mod+e . "layout toggle split")
+ ($mod+f . "fullscreen")
+ ($mod+Shift+space . "floating toggle")
+ ($mod+space . "focus mode_toggle")
+ ($mod+z . "focus parent")
+ ($mod+Shift+o . "move scratchpad")
+ ($mod+o . "scratchpad show")
+ ($mod+r . "mode \"resize\"")
+ ($mod+Shift+n . "bar mode toggle")
+ ($mod+Shift+b . "border toggle")
+ ($mod+tab . "workspace back_and_forth")))
+
+
+;;;
+;;; Definition of configurations.
+;;;
+
+(define (list-of-string-or-gexp? lst)
+ (every (lambda (elt)
+ (or (string? elt)
+ (gexp? elt)))
+ lst))
+
+(define (list-of-packages? lst)
+ (every package? lst))
+
+(define (bar-position? p)
+ (member p '(top bottom)))
+
+(define (hidden-state? st)
+ (member st '(hide show)))
+
+(define (string-or-symbol? s)
+ (or (string? s)
+ (symbol? s)))
+
+(define (strings? lst)
+ (every string? lst))
+
+(define-maybe string (no-serialization))
+(define-maybe strings (no-serialization))
+
+(define-configuration/no-serialization sway-input
+ (identifier
+ (string-or-symbol '*)
+ "Identifier of the input.")
+ (xkb-layout
+ maybe-string
+ "Keyboard layout.")
+ (xkb-model
+ maybe-string
+ "Keyboard model.")
+ (xkb-options
+ maybe-strings
+ "Keyboard options.")
+ (xkb-variant
+ maybe-string
+ "Keyboard layout variant.")
+ (extra-content
+ (list-of-string-or-gexp '())
+ "Lines to add at the end of the configuration file."))
+
+(define (sway-inputs? lst)
+ (every sway-input? lst))
+
+(define-configuration/no-serialization sway-border-color
+ (border
+ string
+ "Border color.")
+ (background
+ string
+ "Background color.")
+ (text
+ string
+ "Text color."))
+
+(define-maybe sway-border-color (no-serialization))
+
+(define-configuration/no-serialization sway-color
+ (background
+ maybe-string
+ "Background color of the bar.")
+ (statusline
+ maybe-string
+ "Text color of the separator.")
+ (focused-background
+ maybe-string
+ "Background color of the bar on the currently focused monitor.")
+ (focused-statusline
+ maybe-string
+ "Text color of the statusline on the currently focused monitor.")
+ (focused-workspace
+ maybe-sway-border-color
+ "...")
+ (active-workspace
+ maybe-sway-border-color
+ "...")
+ (inactive-workspace
+ maybe-sway-border-color
+ "...")
+ (urgent-workspace
+ maybe-sway-border-color
+ "...")
+ (binding-mode
+ maybe-sway-border-color
+ "..."))
+
+(define-maybe sway-color (no-serialization))
+
+(define-configuration/no-serialization sway-bar
+ (identifier
+ (symbol 'bar0)
+ "Identifier of the bar.")
+ (position
+ (bar-position 'top)
+ "Position of the bar.")
+ (hidden-state
+ (hidden-state 'hide)
+ "Hidden state.")
+ (binding-mode-indicator
+ (boolean #t)
+ "Binding indicator.")
+ (colors
+ maybe-sway-color
+ "Color palette of the bar.")
+ (status-command
+ (file-like
+ (program-file
+ "sway-bar-status"
+ (with-imported-modules
+ (source-module-closure
+ '((ice-9 textual-ports) (ice-9 regex) (ice-9 popen) (ice-9 format)
+ (srfi srfi-19)))
+ #~(begin
+ (use-modules (ice-9 textual-ports)
+ (ice-9 format)
+ (ice-9 popen)
+ (ice-9 regex)
+ (srfi srfi-19))
+ (let loop ()
+ (let* ((date (date->string (current-date) "~a ~D ~H:~M:~S"))
+ (batline (let* ((p (open-pipe*
+ OPEN_READ
+ #$(file-append acpi "/bin/acpi") "-b"))
+ (bat (get-line p)))
+ (close-pipe p)
+ bat))
+ (bat (match:substring (string-match "[0-9]+%" batline))))
+ (format #t "~a - ~a~%~!" bat date)
+ (sleep 1)
+ (loop)))))))
+ "Status command. It must be file-like."))
+
+(define-configuration/no-serialization point
+ (x integer "X coordinate.")
+ (y integer "Y coordinate."))
+
+(define-maybe point (no-serialization))
+(define-maybe file-like (no-serialization))
+
+(define-configuration/no-serialization sway-output
+ (identifier
+ (string-or-symbol '*)
+ "Identifier of the output.")
+ (resolution
+ maybe-string
+ "Mode of the monitor.")
+ (position
+ maybe-point
+ "Position of the monitor.")
+ (bg
+ maybe-file-like
+ "Background image.")
+ (extra-content
+ (list-of-string-or-gexp '())
+ "Extra lines."))
+
+(define (sway-outputs? lst)
+ (every sway-output? lst))
+
+(define-configuration/no-serialization sway-configuration
+ (keybindings
+ (alist %sway-default-keybindings)
+ "Keybindings.")
+ (gestures
+ (alist %sway-default-gestures)
+ "Gestures.")
+ (packages
+ (list-of-packages
+ (list sway swaylock waybar swaybg slurp grim dmenu bemenu
+ dbus xdg-desktop-portal-wlr xdg-desktop-portal))
+ "List of packages to add to the profile.")
+ (variables
+ (alist %sway-default-variables)
+ "Variables declared at the beginning of the file.")
+ (inputs
+ (sway-inputs (list (sway-input)))
+ "Inputs.")
+ (outputs
+ (sway-outputs '())
+ "Outputs.")
+ (bar
+ (sway-bar (sway-bar))
+ "Bar configuration.")
+ (execs
+ (list-of-string-or-gexp '())
+ "Programs to execute at startup time.")
+ (extra-content
+ (list-of-string-or-gexp '())
+ "Lines to add at the end of the configuration file."))
+
+
+;;;
+;;; Serialization functions.
+;;;
+
+(define (serialize-keybinding var)
+ (let ((name (symbol->string (car var)))
+ (value (cdr var)))
+ #~(string-append "bindsym " #$name " " #$value)))
+
+(define (serialize-gesture var)
+ (let ((name (symbol->string (car var)))
+ (value (cdr var)))
+ #~(string-append "bindgesture " #$name " " #$value)))
+
+(define (serialize-variable var)
+ (let ((name (symbol->string (car var)))
+ (value (cdr var)))
+ #~(string-append "set $" #$name " " #$value)))
+
+(define (serialize-exec exe)
+ #~(string-append "exec " #$exe))
+
+(define (serialize-output out)
+ (let* ((pre-ident (sway-output-identifier out))
+ (ident (if (symbol? pre-ident)
+ (symbol->string pre-ident)
+ (string-append "\"" pre-ident "\"")))
+ (bg (sway-output-bg out))
+ (resolution (sway-output-resolution out))
+ (position (sway-output-position out))
+ (extra-content (sway-output-extra-content out)))
+ (append
+ (filter
+ (lambda (elt) (not (eq? elt %unset-value)))
+ (list
+ ;; Beginning of the block.
+ #~(string-append "output " #$ident " {")
+ ;; Optional elements.
+ (if (eq? %unset-value bg)
+ %unset-value
+ #~(string-append " bg " #$bg " fill"))
+ (if (eq? %unset-value resolution)
+ %unset-value
+ (string-append " resolution " resolution))
+ (if (eq? %unset-value position)
+ %unset-value
+ (string-append " position " (number->string (point-x position))
+ " " (number->string (point-y position))))))
+ extra-content
+ ;; End of the block.
+ '("}"))))
+
+(define-inlinable (add-line-if prefix value)
+ (if (eq? %unset-value value)
+ %unset-value
+ (string-append prefix " " value)))
+
+(define (serialize-input input)
+ (let* ((pre-ident (sway-input-identifier input))
+ (ident (if (symbol? pre-ident)
+ (symbol->string pre-ident)
+ (string-append "\"" pre-ident "\"")))
+ (xkb-layout (sway-input-xkb-layout input))
+ (xkb-model (sway-input-xkb-model input))
+ (xkb-variant (sway-input-xkb-variant input))
+ (xkb-options (sway-input-xkb-options input)))
+ (append
+ (filter
+ (lambda (elt) (not (eq? elt %unset-value)))
+ (list
+ (string-append "input " ident " {")
+ ;; Optional.
+ (add-line-if " xkb_layout" xkb-layout)
+ (add-line-if " xkb_model" xkb-model)
+ (add-line-if " xkb_variant" xkb-variant)
+ (if (eq? %unset-value xkb-options)
+ %unset-value
+ (string-concatenate (cons " xkb_options " xkb-options)))))
+ (map (lambda (s)
+ (string-append (string-pad "" 4) s))
+ (sway-input-extra-content input))
+ '("}"))))
+
+(define (serialize-colors colors)
+ (define (add-border-color-if name val)
+ (if (eq? %unset-value val)
+ %unset-value
+ (string-append
+ name
+ " " (sway-border-color-border val)
+ " " (sway-border-color-background val)
+ " " (sway-border-color-text val))))
+ (let ((background (sway-color-background colors))
+ (statusline (sway-color-statusline colors))
+ (focused-background (sway-color-focused-background colors))
+ (focused-statusline (sway-color-focused-statusline colors))
+ (focused-workspace (sway-color-focused-workspace colors))
+ (active-workspace (sway-color-active-workspace colors))
+ (inactive-workspace (sway-color-inactive-workspace colors))
+ (urgent-workspace (sway-color-urgent-workspace colors))
+ (binding-mode (sway-color-binding-mode colors)))
+ (filter
+ (lambda (elt) (not (eq? elt %unset-value)))
+ (list
+ (add-line-if "background" background)
+ (add-line-if "statusline" statusline)
+ (add-line-if "focused_background" focused-background)
+ (add-line-if "focused_statusline" focused-statusline)
+ (add-border-color-if "focused_workspace" focused-workspace)
+ (add-border-color-if "active_workspace" active-workspace)
+ (add-border-color-if "inactive_workspace" inactive-workspace)
+ (add-border-color-if "urgent_workspace" urgent-workspace)
+ (add-border-color-if "binding_mode" binding-mode)))))
+
+(define (make-sway-config conf)
+ (let* ((extra (sway-configuration-extra-content conf))
+ (bar (sway-configuration-bar conf)))
+
+ (with-imported-modules
+ (source-module-closure
+ '((ice-9 popen) (ice-9 match) (ice-9 format) (guix monads)))
+ (computed-file
+ "sway-config"
+ #~(begin
+ (use-modules (ice-9 format) (ice-9 popen) (ice-9 match)
+ (guix monads))
+ ;; Helper functions to pretty-print the configuration file.
+ (define (line s)
+ (lambda (port)
+ (lambda (i)
+ (format port "~a~a~%" (string-pad "" i) s)
+ (values port i))))
+ (define (lines lst)
+ (lambda (port)
+ (lambda (i)
+ (let loop ((l lst))
+ (match l
+ (() #t)
+ ((head . tail)
+ (format port "~a~a~%" (string-pad "" i)
+ (if (list? head)
+ (string-concatenate head)
+ head))
+ (loop tail))))
+ (values port i))))
+ (define-syntax line*
+ (syntax-rules ()
+ ((line* elt ...)
+ (lines (list elt ...)))))
+ (define-syntax line2
+ (syntax-rules ()
+ ((line2 a b)
+ (line (string-append a b)))))
+ (define (indent k)
+ (lambda (port)
+ (lambda (i)
+ (values port (+ i k)))))
+ (define (begin-block name)
+ (lambda (port)
+ (lambda (i)
+ (format port "~a~a {~%" (string-pad "" i) name)
+ (values port (+ i 4)))))
+ (define (end-block)
+ (lambda (port)
+ (lambda (i)
+ (let ((i (- i 4)))
+ (format port "~a}~%" (string-pad "" i))
+ (values port i)))))
+
+ (let* ((file #$output)
+ (port (open-output-file #$output)))
+ ;; The previous iteration of this work computed the content of the
+ ;; configuration file as a string. The state monad was used to
+ ;; keep track of the state during the computation.
+ ;; However, this first approach was too expensive. Now that I use
+ ;; `computed-file', the "computed value" is the constant port to
+ ;; which I write. Thus, using the state monad is overkill here.
+ ;; It can be replaced by the identity monad, where the value being
+ ;; passed around is the pair of `port' and the indentation level.
+
This message was truncated. Download the full message here.
A
A
Arnaud Daby-Seesaram wrote on 24 Aug 17:32 +0200
[PATCH v2] home: services: Add 'home-sway-service-type'.
(address . 72714@debbugs.gnu.org)(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)
901afa1d4bd6d28400da2f3403bf5cd5f1ee177c.1724513553.git.ds-ac@nanein.fr
* gnu/home/services/sway.scm: New file.
(home-sway-service-type): New variable.
(sway-configuration->file): New procedure.
(sway-configuration): New configuration record.
(sway-bar): New configuration record.
(sway-output): New configuration record.
(sway-input): New configuration record.
(point): New configuration record.
(sway-color): New configuration record.
(sway-border-color): New configuration record.
(flatten): New procedure.
* gnu/local.mk: Add gnu/home/services/sway.scm.
* doc/guix.texi (Sway window manager): New node to document the above changes.

Change-Id: Iad4fee02d1c243eb051245277f2e2643523e6d27
---
This V2 slightly improves my code and adds a TeXinfo documentation. (I also
modified local.mk, which I forgot last time).

doc/guix.texi | 255 +++++++++++++++
gnu/home/services/sway.scm | 630 +++++++++++++++++++++++++++++++++++++
gnu/local.mk | 1 +
3 files changed, 886 insertions(+)
create mode 100644 gnu/home/services/sway.scm

Toggle diff (594 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index fcaf6b3fbb..c69a021a77 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -129,6 +129,7 @@
Copyright @copyright{} 2024 Richard Sent@*
Copyright @copyright{} 2024 Dariqq@*
Copyright @copyright{} 2024 Denis 'GNUtoo' Carikli@*
+Copyright @copyright{} 2024 Arnaud Daby-Seesaram@*
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -45161,6 +45162,7 @@ Home Services
* Messaging: Messaging Home Services. Services for managing messaging.
* Media: Media Home Services. Services for managing media.
* Networking: Networking Home Services. Networking services.
+* Sway: Sway window manager. Setting up the sway configuration.
* Miscellaneous: Miscellaneous Home Services. More services.
@end menu
@c In addition to that Home Services can provide
@@ -47074,6 +47076,259 @@ Media Home Services
@end table
@end deftp
+@node Sway window manager
+@subsection Sway window manager
+@cindex Sway, Home service
+
+The @code{(gnu home services sway)} module provides
+@code{home-sway-service-type}, a home service to configure sway in a
+declarative way.
+
+@quotation Note
+This home service only sets up configuration file and profile packages
+for sway. It does @i{not} start sway in any way. If you want to do so,
+you might be interested in using @code{greetd-wlgreet-sway-session}
+instead.
+
+The function @code{sway-configuration->file} defined below can be used
+to provide the value for the @code{sway-configuration} field of
+@code{greetd-wlgreet-sway-session}.
+@end quotation
+
+@defvar sway-configuration->file
+This function takes a @code{sway-configuration} record (defined below),
+and returns a file-like object represented the serialized configuration.
+@end defvar
+
+@defvar home-sway-service-type
+This is a home service type to set up Sway. It takes care of:
+@itemize
+@item
+providing a @file{~/.config/sway/config} file,
+@item
+adding sway-related packages to your profile.
+@end itemize
+
+Here is an example of a service and its configuration that you could add
+to the @code{services} field of your @code{home-environment}:
+
+@lisp
+(define bg-file
+ (computed-file
+ "background.png"
+ #~(let* ((insvg (string-append
+ #$guix-backgrounds
+ "/share/backgrounds/guix/guix-checkered-16-9.svg"))
+ (out #$output)
+ (cmd (string-append
+ #$librsvg "/bin/rsvg-convert " insvg " -o " out)))
+ (system cmd))))
+
+(service home-sway-service-type
+ (sway-configuration
+ (gestures
+ '((swipe:3:down . "move to scratchpad")
+ (swipe:3:up . "scratchpad show")))
+ (outputs
+ (list (sway-output
+ (identifier '*)
+ (bg bg-file))))))
+@end lisp
+
+The above example describes a sway configuration in which
+@itemize
+@item
+all monitors use a particular wallpaper whose @file{.svg} is provided by
+the @code{guix-background} package;
+@item
+swiping down (resp.@ up) with three fingers moves the active window to
+the scratchpad (resp.@ shows/hides the scratchpad).
+@end itemize
+@end defvar
+
+
+@deftp {Data Type} sway-configuration
+This configuration record describes the sway configuration
+(see@ @cite{sway(5)}). Available fields are:
+
+@table @asis
+@item @code{variables} (default: @code{%sway-default-variables})
+The value of this field is an association list in which keys are symbols
+and values are strings.
+
+Example: @code{'(mod . "Mod4")}.
+
+@item @code{keybindings} (default: @code{%sway-default-keybindings})
+The value of this field is an association list in which keys are symbols
+and values are strings or G-expressions (@pxref{G-Expressions}).
+
+Examples using:
+@itemize
+@item
+a string: @code{'($mod+Return . "exec $term")}
+@item
+a G-exp: @code{`($mod+t . ,#~(string-append #$st "/bin/st"))}
+@end itemize
+
+@item @code{gestures} (default: @code{%sway-default-gestures})
+This value of this field is an association list, as for keybindings.
+
+@item @code{packages} (default: @code{%sway-default-packages})
+This field describes a list of packages to add to the user profile.
+
+@item @code{inputs} (default: @code{(list (sway-input))})
+List of @code{sway-input} configuration records.
+
+@item @code{outputs} (default: @code{'()})
+List of @code{sway-output} configuration records.
+
+@item @code{bar} (default: @code{(sway-bar)})
+Bar configuration.
+
+@item @code{always-execs} (default: @code{'()})
+Programs to execute at startup time @i{and} after every configuration
+reload. The value of this field is a list of strings or G-expressions.
+
+@item @code{execs} (default: @code{'()})
+Programs to execute at startup time. The value of this field is a list
+of strings or G-expressions.
+
+@item @code{extra-content} (default: @code{'()})
+Lines to add to the configuration file. The value of this field is a
+list of strings or G-expressions.
+
+@end table
+@end deftp
+
+@deftp {Data Type} sway-input
+@code{sway-input} records describe input blocks
+(see@ @cite{sway-input(5)}). Available fields are:
+
+@table @asis
+@item @code{identifier} (default: @code{'*})
+Identifier of the input. The field accepts symbols and strings. If a
+string is used, it will be quoted in the generated configuration file.
+
+@item @code{xkb-layout} (optional)
+Keyboard specific option. Comma-separated keyboard layout(s) to use.
+
+@item @code{xkb-model} (optional)
+Keyboard specific option. String providing the keyboard model.
+
+@item @code{xkb-options} (optional)
+Keyboard specific option. Additional xkb options for the keyboard.
+
+@item @code{xkb-variant} (optional)
+Keyboard specific option. String specifying the variant of the layout.
+
+@item @code{extra-content} (default: @code{'()})
+Lines to add to the input block. The value of this field is a list of
+strings or G-expressions.
+
+@end table
+
+For example, the following snippet makes all keyboards use a french
+layout, in which @kbd{capslock} has been remaped to @kbd{ctrl}:
+@lisp
+(sway-input (identifier "type:keyboard")
+ (xkb-layout "fr")
+ (xkb-options '("ctrl:nocaps")))
+@end lisp
+@end deftp
+
+
+@deftp {Data Type} sway-output
+@code{sway-output} records describe sway outputs
+(see@ @cite{sway-output(5)}). Available fields are:
+
+@table @asis
+@item @code{identifier} (default: @code{'*})
+Identifier of the monitor. If the
+@code{identifier} is a symbol, it is inserted as is; if it is a string,
+it will be quoted in the configuration file.
+
+@item @code{resolution} (optional)
+This string defines the resolution of the monitor.
+
+@item @code{position} (optional)
+The (optional) value of this field must be a @code{point}.
+Example:
+@lisp
+(position
+ (point (x 1920)
+ (y 0)))
+@end lisp
+
+@item @code{bg} (optional)
+This field accepts a file-like value representing the wallpaper to use
+on this monitor. It will be used with the @code{fill} option.
+
+@item @code{extra-content} (default: @code{'()})
+Any additional lines to be added to the output configuration block.
+Elements of the list must be either strings or G-expressions.
+
+@end table
+@end deftp
+
+
+@deftp {Data Type} sway-border-color
+
+@table @asis
+@item @code{border} Color of the border.
+@item @code{background} Color of the background.
+@item @code{text} Color of the text.
+@end table
+@end deftp
+
+
+@deftp {Data Type} sway-color
+@table @asis
+@item @code{background}
+@item @code{statusline}
+@item @code{focused-background}
+@item @code{focused-statusline}
+@item @code{focused-workspace}
+@item @code{active-workspace}
+@item @code{inactive-workspace}
+@item @code{urgent-workspace}
+@item @code{binding-mode}
+@end table
+@end deftp
+
+
+@deftp {Data Type} sway-bar
+Describes the Sway bar (see@ @cite{sway-bar(5)}).
+
+@table @asis
+@item @code{identifier} (default: @code{'bar0})
+Identifier of the bar. The value must be a string.
+
+@item @code{position} (default: @code{'top})
+Specify the position of the bar. Accepted values are @code{'top} or
+@code{'bottom}.
+
+@item @code{hidden-state} (default: @code{'hide})
+Specify the apparence of the bar when it is hidden. Accepted values are
+@code{'hide} or @code{show}.
+
+@item @code{binding-mode-indicator} (default: @code{#t})
+Enable or disable the binding mode indicator.
+
+@item @code{colors} (optional)
+An optional @code{sway-color} configuration record.
+
+@item @code{status-command} (default: @code{%sway-status-command})
+This field accept executable file-like values. The default value is a
+script that prints the battery information (retrieved using
+@code{acpi}), date and time every second.
+
+Each line printed on @code{stdout} by this script will be displayed on
+the status area of the bar.
+
+@end table
+@end deftp
+
+
@node Networking Home Services
@subsection Networking Home Services
diff --git a/gnu/home/services/sway.scm b/gnu/home/services/sway.scm
new file mode 100644
index 0000000000..dc399015ed
--- /dev/null
+++ b/gnu/home/services/sway.scm
@@ -0,0 +1,630 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2024 Arnaud Daby-Seesaram <ds-ac@nanein.fr>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix 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 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix 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 GNU Guix. If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu home services sway)
+ #:use-module (guix monads)
+ #:use-module (guix modules)
+ #:use-module (guix gexp)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-26)
+ #:use-module (ice-9 popen)
+ #:use-module (ice-9 format)
+ #:use-module (ice-9 match)
+ #:use-module (guix packages)
+ #:use-module (gnu services configuration)
+ #:use-module (gnu home services)
+ #:use-module (gnu packages freedesktop)
+ #:use-module (gnu packages xdisorg)
+ #:use-module (gnu packages image)
+ #:use-module (gnu packages gnome)
+ #:use-module (gnu packages wm)
+ #:use-module (gnu packages emacs)
+ #:use-module (gnu packages linux)
+ #:use-module (gnu packages base)
+ #:use-module (gnu packages suckless)
+ #:use-module (gnu packages glib)
+ #:export (;; Accessors and predicates do not need to be exported.
+ sway-configuration
+ sway-bar
+ sway-output
+ sway-input
+ point
+ sway-color
+ sway-border-color
+ home-sway-service-type
+ sway-configuration->file
+ %sway-default-variables
+ %sway-default-gestures
+ %sway-default-keybindings
+ %sway-default-status-command
+ ))
+
+;; Helper function.
+(define (flatten l)
+ (let loop ((lst l) (acc '()))
+ (match lst
+ (() acc)
+ ((head . tail)
+ (loop tail (append acc head))))))
+
+
+;;;
+;;; Default settings.
+;;;
+
+(define %sway-default-variables
+ `((mod . "Mod4")
+ (left . "h")
+ (down . "j")
+ (up . "k")
+ (right . "l")
+ (term . ,#~(string-append #$st "/bin/st"))
+ (menu . ,#~(string-append #$dmenu "/bin/dmenu_run"))))
+
+(define %sway-default-gestures
+ `((swipe:3:right . "workspace next_on_output")
+ (swipe:3:left . "workspace prev_on_output")
+ (swipe:3:down . "move to scratchpad")
+ (swipe:3:up . "scratchpad show")
+ (pinch:2:clockwise
+ . "move container to workspace prev_on_output")
+ (pinch:2:counterclockwise
+ . "move container to workspace next_on_output")
+ (swipe:4:left . "exec alacritty")
+ (swipe:4:right . "exec qutebrowser")
+ (swipe:4:down . "exec st")
+ (swipe:4:up
+ . ,#~(string-append
+ "exec " #$emacs "/bin/emacsclient -a '"
+ #$libnotify "/bin/notify-send Oups \"emacs not loaded :/\"' -c"))
+ (pinch:inward+right . "resize shrink width")
+ (pinch:inward+left . "resize grow width")
+ (pinch:inward+down . "resize shrink height")
+ (pinch:inward+up . "resize grow height")
+ (pinch:outward+up . "move up")
+ (pinch:outward+down . "move down")
+ (pinch:outward+left . "move left")
+ (pinch:outward+right . "move right")))
+
+(define %sway-default-keybindings
+ `(($mod+Shift+e
+ . ,#~(string-append
+ "exec " #$emacs
+ "/bin/emacsclient -a '"
+ #$libnotify "/bin/notify-send Oups \"emacs not loaded :/\"' -c"))
+ ($mod+Return . "exec $term")
+ ($mod+Shift+c . "kill")
+ ($mod+p . "exec $menu")
+ ($mod+Shift+r . "reload")
+ ($mod+Shift+q
+ . ,#~(string-append
+ "exec " #$sway "/bin/swaynag -t warning "
+ "-m 'You pressed the exit shortcut. Do you really want to exit sway?"
+ " This will end your Wayland session.'"
+ " -B 'Yes, exit sway' 'swaymsg exit'"))
+ ($mod+$left . "focus left")
+ ($mod+$right . "focus right")
+ ($mod+$up . "focus up")
+ ($mod+$down . "focus down")
+ ($mod+Shift+$left . "move left")
+ ($mod+Shift+$right . "move right")
+ ($mod+Shift+$up . "move up")
+ ($mod+Shift+$down . "move down")
+ ($mod+ampersand . "workspace number 1")
+ ($mod+eacute . "workspace number 2")
+ ($mod+quotedbl . "workspace number 3")
+ ($mod+apostrophe . "workspace number 4")
+ ($mod+parenleft . "workspace number 5")
+ ($mod+minus . "workspace number 6")
+ ($mod+egrave . "workspace number 7")
+ ($mod+underscore . "workspace number 8")
+ ($mod+ccedilla . "workspace number 9")
+ ($mod+agrave . "workspace number 10")
+ ($mod+Shift+ampersand . "move container to workspace number 1")
+ ($mod+Shift+eacute . "move container to workspace number 2")
+ ($mod+Shift+quotedbl . "move container to workspace number 3")
+ ($mod+Shift+apostrophe . "move container to workspace number 4")
+ ($mod+Shift+parenleft . "move container to workspace number 5")
+ ($mod+Shift+minus . "move container to workspace number 6")
+ ($mod+Shift+egrave . "move container to workspace number 7")
+ ($mod+Shift+underscore . "move container to workspace number 8")
+ ($mod+Shift+ccedilla . "move container to workspace number 9")
+ ($mod+Shift+agrave . "move container to workspace number 10")
+ ($mod+b . "splith")
+ ($mod+v . "splitv")
+ ($mod+s . "layout stacking")
+ ($mod+w . "layout tabbed")
+ ($mod+e . "layout toggle split")
+ ($mod+f . "fullscreen")
+ ($mod+Shift+space . "floating toggle")
+ ($mod+space . "focus mode_toggle")
+ ($mod+z . "focus parent")
+ ($mod+Shift+o . "move scratchpad")
+ ($mod+o . "scratchpad show")
+ ($mod+r . "mode \"resize\"")
+ ($mod+Shift+n . "bar mode toggle")
+ ($mod+Shift+b . "border toggle")
+ ($mod+tab . "workspace back_and_forth")))
+
+(define %sway-default-status-command
+ (program-file
+ "sway-bar-status"
+ (with-imported-modules
+ (source-module-closure
+ '((ice-9 textual-ports) (ice-9 regex) (ice-9 popen) (ice-9 format)
+ (srfi srfi-19)))
+ #~(begin
+ (use-modules (ice-9 textual-ports)
+ (ice-9 format)
+ (ice-9 popen)
+ (ice-9 regex)
+ (srfi srfi-19))
+ (let loop ()
+ (let* ((date (date->string (current-date) "~a ~D ~H:~M:~S"))
+ (batline (let* ((p (open-pipe*
+ OPEN_READ
+ #$(file-append acpi "/bin/acpi") "-b"))
+ (bat (get-line p)))
+ (close-pipe p)
+ bat))
+ (bat (match:substring (string-match "[0-9]+%" batline))))
+ (format #t "~a - ~a~%~!" bat date)
+ (sleep 1)
+ (loop)))))))
+
+
+;;;
+;;; Definition of configurations.
+;;;
+
+(define (list-of-string-or-gexp? lst)
+ (every (lambda (elt)
+ (or (string? elt)
+ (gexp? elt)))
+ lst))
+
+(define (list-of-packages? lst)
+ (every package? lst))
+
+(define (bar-position? p)
+ (member p '(top bottom)))
+
+(define (hidden-state? st)
+ (member st '(hide show)))
+
+(define (string-or-symbol? s)
+ (or (string? s)
+ (symbol? s)))
+
+(define (strings? lst)
+ (every string? lst))
+
+(define-maybe string (no-serialization))
+(define-maybe strings (no-serialization))
+
+(define-configuration/no-serialization sway-input
+ (identifier
+ (string-or-symbol '*)
+ "Identifier of the input.")
+ (xkb-layout
+ maybe-string
+ "Keyboard layout.")
+ (xkb-model
+ maybe-string
+ "Keyboard model.")
+ (xkb-options
+ maybe-strings
+ "Keyboard options.")
+ (xkb-variant
+ maybe-string
+ "Keyboard layout variant.")
+ (extra-content
+ (list-of-string-or-gexp '())
+ "Lines to add at the end of the configuration file."))
+
+(define (sway-inputs? lst)
+ (every sway-input? lst))
+
+(define-configuration/no-serialization sway-border-color
+ (border
+ string
+ "Border color.")
+ (background
+ string
+ "Background color.")
+ (text
+ string
+ "Text color."))
+
+(define-maybe sway-border-color (no-serialization))
+
+(define-configuration/no-serialization sway-color
+ (background
+ maybe-string
+ "Background color of the bar.")
+ (statusline
+ maybe-string
+ "Text color of the separator.")
+ (focused-background
+ maybe-string
+ "Background color of the bar on the currently focused monitor.")
+ (focused-statusline
+ maybe-string
+ "Text color of the statusline on the currently focused monitor.")
+ (focused-workspace
+ maybe-sway-border-color
+ "...")
+ (active-workspace
+ maybe-sway-border-color
+ "...")
+ (inactive-workspace
+ maybe-sway-border-color
+ "...")
+ (urgent-workspace
+ maybe-sway-border-color
+ "...")
+ (binding-mode
+ maybe-sway-border-color
+ "..."))
+
+(define-maybe sway-color (no-serialization))
+
+(define-configuration/no-serialization sway-bar
+ (identifier
+ (symbol 'bar0)
+ "Identifier of the bar.")
+ (position
+ (bar-position 'top)
+ "Position of the bar.")
+ (hidden-state
+ (hidden-state 'hide)
+ "Hidden state.")
+ (binding-mode-indicator
+ (boolean #t)
+ "Binding indicator.")
+ (colors
+ maybe-sway-color
+ "Color palette of the bar.")
+ (status-command
+ (file-like %sway-default-status-command)
+ "Status command. It must be file-like."))
+
+(define-configuration/no-serialization point
+ (x integer "X coordinate
This message was truncated. Download the full message here.
A
A
Arnaud Daby-Seesaram wrote on 26 Aug 12:38 +0200
[PATCH v3] home: services: Add 'home-sway-service-type'.
(address . 72714@debbugs.gnu.org)(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)
4b0a03801d5879f745e791635f57b9fa591fc0d2.1724668693.git.ds-ac@nanein.fr
* gnu/home/services/sway.scm: New file.
(home-sway-service-type): New variable.
(sway-configuration->file): New procedure.
(sway-configuration): New configuration record.
(sway-bar): New configuration record.
(sway-output): New configuration record.
(sway-input): New configuration record.
(point): New configuration record.
(sway-color): New configuration record.
(sway-border-color): New configuration record.
(flatten): New procedure.
* gnu/local.mk: Add gnu/home/services/sway.scm.
* doc/guix.texi (Sway window manager): New node to document the above changes.

Change-Id: Iad4fee02d1c243eb051245277f2e2643523e6d27
---
Minor fix: do not attempt to serialise bar colours if none are specified.

doc/guix.texi | 255 +++++++++++++++
gnu/home/services/sway.scm | 632 +++++++++++++++++++++++++++++++++++++
gnu/local.mk | 1 +
3 files changed, 888 insertions(+)
create mode 100644 gnu/home/services/sway.scm

Toggle diff (597 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index fcaf6b3fbb..c69a021a77 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -129,6 +129,7 @@
Copyright @copyright{} 2024 Richard Sent@*
Copyright @copyright{} 2024 Dariqq@*
Copyright @copyright{} 2024 Denis 'GNUtoo' Carikli@*
+Copyright @copyright{} 2024 Arnaud Daby-Seesaram@*
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -45161,6 +45162,7 @@ Home Services
* Messaging: Messaging Home Services. Services for managing messaging.
* Media: Media Home Services. Services for managing media.
* Networking: Networking Home Services. Networking services.
+* Sway: Sway window manager. Setting up the sway configuration.
* Miscellaneous: Miscellaneous Home Services. More services.
@end menu
@c In addition to that Home Services can provide
@@ -47074,6 +47076,259 @@ Media Home Services
@end table
@end deftp
+@node Sway window manager
+@subsection Sway window manager
+@cindex Sway, Home service
+
+The @code{(gnu home services sway)} module provides
+@code{home-sway-service-type}, a home service to configure sway in a
+declarative way.
+
+@quotation Note
+This home service only sets up configuration file and profile packages
+for sway. It does @i{not} start sway in any way. If you want to do so,
+you might be interested in using @code{greetd-wlgreet-sway-session}
+instead.
+
+The function @code{sway-configuration->file} defined below can be used
+to provide the value for the @code{sway-configuration} field of
+@code{greetd-wlgreet-sway-session}.
+@end quotation
+
+@defvar sway-configuration->file
+This function takes a @code{sway-configuration} record (defined below),
+and returns a file-like object represented the serialized configuration.
+@end defvar
+
+@defvar home-sway-service-type
+This is a home service type to set up Sway. It takes care of:
+@itemize
+@item
+providing a @file{~/.config/sway/config} file,
+@item
+adding sway-related packages to your profile.
+@end itemize
+
+Here is an example of a service and its configuration that you could add
+to the @code{services} field of your @code{home-environment}:
+
+@lisp
+(define bg-file
+ (computed-file
+ "background.png"
+ #~(let* ((insvg (string-append
+ #$guix-backgrounds
+ "/share/backgrounds/guix/guix-checkered-16-9.svg"))
+ (out #$output)
+ (cmd (string-append
+ #$librsvg "/bin/rsvg-convert " insvg " -o " out)))
+ (system cmd))))
+
+(service home-sway-service-type
+ (sway-configuration
+ (gestures
+ '((swipe:3:down . "move to scratchpad")
+ (swipe:3:up . "scratchpad show")))
+ (outputs
+ (list (sway-output
+ (identifier '*)
+ (bg bg-file))))))
+@end lisp
+
+The above example describes a sway configuration in which
+@itemize
+@item
+all monitors use a particular wallpaper whose @file{.svg} is provided by
+the @code{guix-background} package;
+@item
+swiping down (resp.@ up) with three fingers moves the active window to
+the scratchpad (resp.@ shows/hides the scratchpad).
+@end itemize
+@end defvar
+
+
+@deftp {Data Type} sway-configuration
+This configuration record describes the sway configuration
+(see@ @cite{sway(5)}). Available fields are:
+
+@table @asis
+@item @code{variables} (default: @code{%sway-default-variables})
+The value of this field is an association list in which keys are symbols
+and values are strings.
+
+Example: @code{'(mod . "Mod4")}.
+
+@item @code{keybindings} (default: @code{%sway-default-keybindings})
+The value of this field is an association list in which keys are symbols
+and values are strings or G-expressions (@pxref{G-Expressions}).
+
+Examples using:
+@itemize
+@item
+a string: @code{'($mod+Return . "exec $term")}
+@item
+a G-exp: @code{`($mod+t . ,#~(string-append #$st "/bin/st"))}
+@end itemize
+
+@item @code{gestures} (default: @code{%sway-default-gestures})
+This value of this field is an association list, as for keybindings.
+
+@item @code{packages} (default: @code{%sway-default-packages})
+This field describes a list of packages to add to the user profile.
+
+@item @code{inputs} (default: @code{(list (sway-input))})
+List of @code{sway-input} configuration records.
+
+@item @code{outputs} (default: @code{'()})
+List of @code{sway-output} configuration records.
+
+@item @code{bar} (default: @code{(sway-bar)})
+Bar configuration.
+
+@item @code{always-execs} (default: @code{'()})
+Programs to execute at startup time @i{and} after every configuration
+reload. The value of this field is a list of strings or G-expressions.
+
+@item @code{execs} (default: @code{'()})
+Programs to execute at startup time. The value of this field is a list
+of strings or G-expressions.
+
+@item @code{extra-content} (default: @code{'()})
+Lines to add to the configuration file. The value of this field is a
+list of strings or G-expressions.
+
+@end table
+@end deftp
+
+@deftp {Data Type} sway-input
+@code{sway-input} records describe input blocks
+(see@ @cite{sway-input(5)}). Available fields are:
+
+@table @asis
+@item @code{identifier} (default: @code{'*})
+Identifier of the input. The field accepts symbols and strings. If a
+string is used, it will be quoted in the generated configuration file.
+
+@item @code{xkb-layout} (optional)
+Keyboard specific option. Comma-separated keyboard layout(s) to use.
+
+@item @code{xkb-model} (optional)
+Keyboard specific option. String providing the keyboard model.
+
+@item @code{xkb-options} (optional)
+Keyboard specific option. Additional xkb options for the keyboard.
+
+@item @code{xkb-variant} (optional)
+Keyboard specific option. String specifying the variant of the layout.
+
+@item @code{extra-content} (default: @code{'()})
+Lines to add to the input block. The value of this field is a list of
+strings or G-expressions.
+
+@end table
+
+For example, the following snippet makes all keyboards use a french
+layout, in which @kbd{capslock} has been remaped to @kbd{ctrl}:
+@lisp
+(sway-input (identifier "type:keyboard")
+ (xkb-layout "fr")
+ (xkb-options '("ctrl:nocaps")))
+@end lisp
+@end deftp
+
+
+@deftp {Data Type} sway-output
+@code{sway-output} records describe sway outputs
+(see@ @cite{sway-output(5)}). Available fields are:
+
+@table @asis
+@item @code{identifier} (default: @code{'*})
+Identifier of the monitor. If the
+@code{identifier} is a symbol, it is inserted as is; if it is a string,
+it will be quoted in the configuration file.
+
+@item @code{resolution} (optional)
+This string defines the resolution of the monitor.
+
+@item @code{position} (optional)
+The (optional) value of this field must be a @code{point}.
+Example:
+@lisp
+(position
+ (point (x 1920)
+ (y 0)))
+@end lisp
+
+@item @code{bg} (optional)
+This field accepts a file-like value representing the wallpaper to use
+on this monitor. It will be used with the @code{fill} option.
+
+@item @code{extra-content} (default: @code{'()})
+Any additional lines to be added to the output configuration block.
+Elements of the list must be either strings or G-expressions.
+
+@end table
+@end deftp
+
+
+@deftp {Data Type} sway-border-color
+
+@table @asis
+@item @code{border} Color of the border.
+@item @code{background} Color of the background.
+@item @code{text} Color of the text.
+@end table
+@end deftp
+
+
+@deftp {Data Type} sway-color
+@table @asis
+@item @code{background}
+@item @code{statusline}
+@item @code{focused-background}
+@item @code{focused-statusline}
+@item @code{focused-workspace}
+@item @code{active-workspace}
+@item @code{inactive-workspace}
+@item @code{urgent-workspace}
+@item @code{binding-mode}
+@end table
+@end deftp
+
+
+@deftp {Data Type} sway-bar
+Describes the Sway bar (see@ @cite{sway-bar(5)}).
+
+@table @asis
+@item @code{identifier} (default: @code{'bar0})
+Identifier of the bar. The value must be a string.
+
+@item @code{position} (default: @code{'top})
+Specify the position of the bar. Accepted values are @code{'top} or
+@code{'bottom}.
+
+@item @code{hidden-state} (default: @code{'hide})
+Specify the apparence of the bar when it is hidden. Accepted values are
+@code{'hide} or @code{show}.
+
+@item @code{binding-mode-indicator} (default: @code{#t})
+Enable or disable the binding mode indicator.
+
+@item @code{colors} (optional)
+An optional @code{sway-color} configuration record.
+
+@item @code{status-command} (default: @code{%sway-status-command})
+This field accept executable file-like values. The default value is a
+script that prints the battery information (retrieved using
+@code{acpi}), date and time every second.
+
+Each line printed on @code{stdout} by this script will be displayed on
+the status area of the bar.
+
+@end table
+@end deftp
+
+
@node Networking Home Services
@subsection Networking Home Services
diff --git a/gnu/home/services/sway.scm b/gnu/home/services/sway.scm
new file mode 100644
index 0000000000..91d01f6eb4
--- /dev/null
+++ b/gnu/home/services/sway.scm
@@ -0,0 +1,632 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2024 Arnaud Daby-Seesaram <ds-ac@nanein.fr>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix 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 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix 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 GNU Guix. If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu home services sway)
+ #:use-module (guix monads)
+ #:use-module (guix modules)
+ #:use-module (guix gexp)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-26)
+ #:use-module (ice-9 popen)
+ #:use-module (ice-9 format)
+ #:use-module (ice-9 match)
+ #:use-module (guix packages)
+ #:use-module (gnu services configuration)
+ #:use-module (gnu home services)
+ #:use-module (gnu packages freedesktop)
+ #:use-module (gnu packages xdisorg)
+ #:use-module (gnu packages image)
+ #:use-module (gnu packages gnome)
+ #:use-module (gnu packages wm)
+ #:use-module (gnu packages emacs)
+ #:use-module (gnu packages linux)
+ #:use-module (gnu packages base)
+ #:use-module (gnu packages suckless)
+ #:use-module (gnu packages glib)
+ #:export (;; Accessors and predicates do not need to be exported.
+ sway-configuration
+ sway-bar
+ sway-output
+ sway-input
+ point
+ sway-color
+ sway-border-color
+ home-sway-service-type
+ sway-configuration->file
+ %sway-default-variables
+ %sway-default-gestures
+ %sway-default-keybindings
+ %sway-default-status-command
+ ))
+
+;; Helper function.
+(define (flatten l)
+ (let loop ((lst l) (acc '()))
+ (match lst
+ (() acc)
+ ((head . tail)
+ (loop tail (append acc head))))))
+
+
+;;;
+;;; Default settings.
+;;;
+
+(define %sway-default-variables
+ `((mod . "Mod4")
+ (left . "h")
+ (down . "j")
+ (up . "k")
+ (right . "l")
+ (term . ,#~(string-append #$st "/bin/st"))
+ (menu . ,#~(string-append #$dmenu "/bin/dmenu_run"))))
+
+(define %sway-default-gestures
+ `((swipe:3:right . "workspace next_on_output")
+ (swipe:3:left . "workspace prev_on_output")
+ (swipe:3:down . "move to scratchpad")
+ (swipe:3:up . "scratchpad show")
+ (pinch:2:clockwise
+ . "move container to workspace prev_on_output")
+ (pinch:2:counterclockwise
+ . "move container to workspace next_on_output")
+ (swipe:4:left . "exec alacritty")
+ (swipe:4:right . "exec qutebrowser")
+ (swipe:4:down . "exec st")
+ (swipe:4:up
+ . ,#~(string-append
+ "exec " #$emacs "/bin/emacsclient -a '"
+ #$libnotify "/bin/notify-send Oups \"emacs not loaded :/\"' -c"))
+ (pinch:inward+right . "resize shrink width")
+ (pinch:inward+left . "resize grow width")
+ (pinch:inward+down . "resize shrink height")
+ (pinch:inward+up . "resize grow height")
+ (pinch:outward+up . "move up")
+ (pinch:outward+down . "move down")
+ (pinch:outward+left . "move left")
+ (pinch:outward+right . "move right")))
+
+(define %sway-default-keybindings
+ `(($mod+Shift+e
+ . ,#~(string-append
+ "exec " #$emacs
+ "/bin/emacsclient -a '"
+ #$libnotify "/bin/notify-send Oups \"emacs not loaded :/\"' -c"))
+ ($mod+Return . "exec $term")
+ ($mod+Shift+c . "kill")
+ ($mod+p . "exec $menu")
+ ($mod+Shift+r . "reload")
+ ($mod+Shift+q
+ . ,#~(string-append
+ "exec " #$sway "/bin/swaynag -t warning "
+ "-m 'You pressed the exit shortcut. Do you really want to exit sway?"
+ " This will end your Wayland session.'"
+ " -B 'Yes, exit sway' 'swaymsg exit'"))
+ ($mod+$left . "focus left")
+ ($mod+$right . "focus right")
+ ($mod+$up . "focus up")
+ ($mod+$down . "focus down")
+ ($mod+Shift+$left . "move left")
+ ($mod+Shift+$right . "move right")
+ ($mod+Shift+$up . "move up")
+ ($mod+Shift+$down . "move down")
+ ($mod+ampersand . "workspace number 1")
+ ($mod+eacute . "workspace number 2")
+ ($mod+quotedbl . "workspace number 3")
+ ($mod+apostrophe . "workspace number 4")
+ ($mod+parenleft . "workspace number 5")
+ ($mod+minus . "workspace number 6")
+ ($mod+egrave . "workspace number 7")
+ ($mod+underscore . "workspace number 8")
+ ($mod+ccedilla . "workspace number 9")
+ ($mod+agrave . "workspace number 10")
+ ($mod+Shift+ampersand . "move container to workspace number 1")
+ ($mod+Shift+eacute . "move container to workspace number 2")
+ ($mod+Shift+quotedbl . "move container to workspace number 3")
+ ($mod+Shift+apostrophe . "move container to workspace number 4")
+ ($mod+Shift+parenleft . "move container to workspace number 5")
+ ($mod+Shift+minus . "move container to workspace number 6")
+ ($mod+Shift+egrave . "move container to workspace number 7")
+ ($mod+Shift+underscore . "move container to workspace number 8")
+ ($mod+Shift+ccedilla . "move container to workspace number 9")
+ ($mod+Shift+agrave . "move container to workspace number 10")
+ ($mod+b . "splith")
+ ($mod+v . "splitv")
+ ($mod+s . "layout stacking")
+ ($mod+w . "layout tabbed")
+ ($mod+e . "layout toggle split")
+ ($mod+f . "fullscreen")
+ ($mod+Shift+space . "floating toggle")
+ ($mod+space . "focus mode_toggle")
+ ($mod+z . "focus parent")
+ ($mod+Shift+o . "move scratchpad")
+ ($mod+o . "scratchpad show")
+ ($mod+r . "mode \"resize\"")
+ ($mod+Shift+n . "bar mode toggle")
+ ($mod+Shift+b . "border toggle")
+ ($mod+tab . "workspace back_and_forth")))
+
+(define %sway-default-status-command
+ (program-file
+ "sway-bar-status"
+ (with-imported-modules
+ (source-module-closure
+ '((ice-9 textual-ports) (ice-9 regex) (ice-9 popen) (ice-9 format)
+ (srfi srfi-19)))
+ #~(begin
+ (use-modules (ice-9 textual-ports)
+ (ice-9 format)
+ (ice-9 popen)
+ (ice-9 regex)
+ (srfi srfi-19))
+ (let loop ()
+ (let* ((date (date->string (current-date) "~a ~D ~H:~M:~S"))
+ (batline (let* ((p (open-pipe*
+ OPEN_READ
+ #$(file-append acpi "/bin/acpi") "-b"))
+ (bat (get-line p)))
+ (close-pipe p)
+ bat))
+ (bat (match:substring (string-match "[0-9]+%" batline))))
+ (format #t "~a - ~a~%~!" bat date)
+ (sleep 1)
+ (loop)))))))
+
+
+;;;
+;;; Definition of configurations.
+;;;
+
+(define (list-of-string-or-gexp? lst)
+ (every (lambda (elt)
+ (or (string? elt)
+ (gexp? elt)))
+ lst))
+
+(define (list-of-packages? lst)
+ (every package? lst))
+
+(define (bar-position? p)
+ (member p '(top bottom)))
+
+(define (hidden-state? st)
+ (member st '(hide show)))
+
+(define (string-or-symbol? s)
+ (or (string? s)
+ (symbol? s)))
+
+(define (strings? lst)
+ (every string? lst))
+
+(define-maybe string (no-serialization))
+(define-maybe strings (no-serialization))
+
+(define-configuration/no-serialization sway-input
+ (identifier
+ (string-or-symbol '*)
+ "Identifier of the input.")
+ (xkb-layout
+ maybe-string
+ "Keyboard layout.")
+ (xkb-model
+ maybe-string
+ "Keyboard model.")
+ (xkb-options
+ maybe-strings
+ "Keyboard options.")
+ (xkb-variant
+ maybe-string
+ "Keyboard layout variant.")
+ (extra-content
+ (list-of-string-or-gexp '())
+ "Lines to add at the end of the configuration file."))
+
+(define (sway-inputs? lst)
+ (every sway-input? lst))
+
+(define-configuration/no-serialization sway-border-color
+ (border
+ string
+ "Border color.")
+ (background
+ string
+ "Background color.")
+ (text
+ string
+ "Text color."))
+
+(define-maybe sway-border-color (no-serialization))
+
+(define-configuration/no-serialization sway-color
+ (background
+ maybe-string
+ "Background color of the bar.")
+ (statusline
+ maybe-string
+ "Text color of the separator.")
+ (focused-background
+ maybe-string
+ "Background color of the bar on the currently focused monitor.")
+ (focused-statusline
+ maybe-string
+ "Text color of the statusline on the currently focused monitor.")
+ (focused-workspace
+ maybe-sway-border-color
+ "...")
+ (active-workspace
+ maybe-sway-border-color
+ "...")
+ (inactive-workspace
+ maybe-sway-border-color
+ "...")
+ (urgent-workspace
+ maybe-sway-border-color
+ "...")
+ (binding-mode
+ maybe-sway-border-color
+ "..."))
+
+(define-maybe sway-color (no-serialization))
+
+(define-configuration/no-serialization sway-bar
+ (identifier
+ (symbol 'bar0)
+ "Identifier of the bar.")
+ (position
+ (bar-position 'top)
+ "Position of the bar.")
+ (hidden-state
+ (hidden-state 'hide)
+ "Hidden state.")
+ (binding-mode-indicator
+ (boolean #t)
+ "Binding indicator.")
+ (colors
+ maybe-sway-color
+ "Color palette of the bar.")
+ (status-command
+ (file-like %sway-default-status-command)
+ "Status command. It must be file-like."))
+
+(define-configuration/no-serialization point
+ (x integer "X coordinate.")
+ (y integer "Y coordinate."))
+
+(define-ma
This message was truncated. Download the full message here.
A
A
Arnaud Daby-Seesaram wrote on 3 Sep 09:27 +0200
[PATCH v4] home: services: Add 'home-sway-service-type'.
(address . 72714@debbugs.gnu.org)(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)
20240903072745.5118-1-ds-ac@nanein.fr
* gnu/home/services/sway.scm: New file.
(home-sway-service-type): New variable.
(sway-configuration->file): New procedure.
(sway-configuration): New configuration record.
(sway-bar): New configuration record.
(sway-output): New configuration record.
(sway-input): New configuration record.
(point): New configuration record.
(sway-color): New configuration record.
(sway-border-color): New configuration record.
(flatten): New procedure.
* gnu/local.mk: Add gnu/home/services/sway.scm.
* doc/guix.texi (Sway window manager): New node to document the above changes.
---
This version is rebased on master and brings default values closer to those of
the default sway configuration (e.g. the status command).

doc/guix.texi | 271 ++++++++++++++
gnu/home/services/sway.scm | 703 +++++++++++++++++++++++++++++++++++++
gnu/local.mk | 1 +
3 files changed, 975 insertions(+)
create mode 100644 gnu/home/services/sway.scm

Toggle diff (603 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index 144adf327e..8e17643b7f 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -130,6 +130,7 @@ Copyright @copyright{} 2024 Richard Sent@*
Copyright @copyright{} 2024 Dariqq@*
Copyright @copyright{} 2024 Denis 'GNUtoo' Carikli@*
Copyright @copyright{} 2024 Fabio Natali@*
+Copyright @copyright{} 2024 Arnaud Daby-Seesaram@*
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -460,6 +461,7 @@ Home Services
* Mail: Mail Home Services. Services for managing mail.
* Messaging: Messaging Home Services. Services for managing messaging.
* Media: Media Home Services. Services for managing media.
+* Sway: Sway window manager. Setting up the Sway configuration.
* Networking: Networking Home Services. Networking services.
* Miscellaneous: Miscellaneous Home Services. More services.
@@ -45175,6 +45177,7 @@ services)}.
* Mail: Mail Home Services. Services for managing mail.
* Messaging: Messaging Home Services. Services for managing messaging.
* Media: Media Home Services. Services for managing media.
+* Sway: Sway window manager. Setting up the Sway configuration.
* Networking: Networking Home Services. Networking services.
* Miscellaneous: Miscellaneous Home Services. More services.
@end menu
@@ -47089,6 +47092,274 @@ kodi} for more information.
@end table
@end deftp
+@node Sway window manager
+@subsection Sway window manager
+
+@cindex sway, configuration
+The @code{(gnu home services sway)} module provides
+@code{home-sway-service-type}, a home service to configure sway in a
+declarative way.
+
+@quotation Note
+This home service only sets up configuration file and profile packages
+for sway. It does @i{not} start sway in any way. If you want to do so,
+you might be interested in using @code{greetd-wlgreet-sway-session}
+instead.
+
+The function @code{sway-configuration->file} defined below can be used
+to provide the value for the @code{sway-configuration} field of
+@code{greetd-wlgreet-sway-session}.
+@end quotation
+
+@defvar sway-configuration->file
+This function takes a @code{sway-configuration} record (defined below),
+and returns a file-like object represented the serialized configuration.
+@end defvar
+
+@defvar home-sway-service-type
+This is a home service type to set up Sway. It takes care of:
+@itemize
+@item
+providing a @file{~/.config/sway/config} file,
+@item
+adding sway-related packages to your profile.
+@end itemize
+
+Here is an example of a service and its configuration that you could add
+to the @code{services} field of your @code{home-environment}:
+
+@lisp
+(define bg-file
+ (computed-file
+ "background.png"
+ #~(let* ((insvg (string-append
+ #$guix-backgrounds
+ "/share/backgrounds/guix/guix-checkered-16-9.svg"))
+ (out #$output)
+ (cmd (string-append
+ #$librsvg "/bin/rsvg-convert " insvg " -o " out)))
+ (system cmd))))
+
+(service home-sway-service-type
+ (sway-configuration
+ (gestures
+ '((swipe:3:down . "move to scratchpad")
+ (swipe:3:up . "scratchpad show")))
+ (outputs
+ (list (sway-output
+ (identifier '*)
+ (bg bg-file))))))
+@end lisp
+
+The above example describes a sway configuration in which
+@itemize
+@item
+all monitors use a particular wallpaper whose @file{.svg} is provided by
+the @code{guix-background} package;
+@item
+swiping down (resp.@ up) with three fingers moves the active window to
+the scratchpad (resp.@ shows/hides the scratchpad).
+@end itemize
+@end defvar
+
+
+@deftp {Data Type} sway-configuration
+This configuration record describes the sway configuration
+(see@ @cite{sway(5)}). Available fields are:
+
+@table @asis
+@item @code{variables} (default: @code{%sway-default-variables})
+The value of this field is an association list in which keys are symbols
+and values are strings or G-expressions (@pxref{G-Expressions}).
+
+Example: @code{'(mod . "Mod4")}.
+
+@item @code{keybindings} (default: @code{%sway-default-keybindings})
+This field describes keybindings for the @emph{default} mode. As above,
+the value is an association list: keys are symbols and values are either
+strings or G-expressions.
+
+@c @example
+Examples using:
+@itemize
+@item
+a string: @code{'($mod+Return . "exec $term")}
+@item
+a G-exp: @code{`($mod+t . ,#~(string-append #$st "/bin/st"))}
+@end itemize
+@c @end example
+
+@item @code{gestures} (default: @code{%sway-default-gestures})
+Similar to the previous field, but for finger-gestures.
+
+@c @example
+The following snippet allows to navigate through workspaces by swiping
+right and left with three fingers:
+@lisp
+`((swipe:3:right . "workspace next_on_output")
+ (swipe:3:left . "workspace prev_on_output"))
+@end lisp
+@c @end example
+
+@item @code{packages} (default: @code{%sway-default-packages})
+This field describes a list of packages to add to the user profile.
+
+@item @code{inputs} (default: @code{(list (sway-input))})
+List of @code{sway-input} configuration records.
+
+@item @code{outputs} (default: @code{'()})
+List of @code{sway-output} configuration records.
+
+@item @code{bar} (default: @code{(sway-bar)})
+Bar configuration.
+
+@item @code{always-execs} (default: @code{'()})
+Programs to execute at startup time @i{and} after every configuration
+reload. The value of this field is a list of strings or G-expressions.
+
+@item @code{execs} (default: @code{%sway-default-execs})
+Programs to execute at startup time. The value of this field is a list
+of strings or G-expressions.
+
+The default value, @code{%sway-default-execs}, executes @code{swayidle}
+in order to lock the screen after 5@ minutes of inactivity (displaying a
+background distributed with Sway) and turn of the screen after
+10@ minutes of inactivity.
+
+@item @code{extra-content} (default: @code{'()})
+Lines to add to the configuration file. The value of this field is a
+list of strings or G-expressions.
+
+@end table
+@end deftp
+
+@deftp {Data Type} sway-input
+@code{sway-input} records describe input blocks
+(see@ @cite{sway-input(5)}). Available fields are:
+
+@table @asis
+@item @code{identifier} (default: @code{'*})
+Identifier of the input. The field accepts symbols and strings. If a
+string is used, it will be quoted in the generated configuration file.
+
+@item @code{xkb-layout} (optional)
+Keyboard specific option. Comma-separated keyboard layout(s) to use.
+
+@item @code{xkb-model} (optional)
+Keyboard specific option. String providing the keyboard model.
+
+@item @code{xkb-options} (optional)
+Keyboard specific option. Additional xkb options for the keyboard.
+
+@item @code{xkb-variant} (optional)
+Keyboard specific option. String specifying the variant of the layout.
+
+@item @code{extra-content} (default: @code{'()})
+Lines to add to the input block. The value of this field is a list of
+strings or G-expressions.
+
+@end table
+
+For example, the following snippet makes all keyboards use a french
+layout, in which @kbd{capslock} has been remaped to @kbd{ctrl}:
+@lisp
+(sway-input (identifier "type:keyboard")
+ (xkb-layout "fr")
+ (xkb-options '("ctrl:nocaps")))
+@end lisp
+@end deftp
+
+
+@deftp {Data Type} sway-output
+@code{sway-output} records describe sway outputs
+(see@ @cite{sway-output(5)}). Available fields are:
+
+@table @asis
+@item @code{identifier} (default: @code{'*})
+Identifier of the monitor. If the
+@code{identifier} is a symbol, it is inserted as is; if it is a string,
+it will be quoted in the configuration file.
+
+@item @code{resolution} (optional)
+This string defines the resolution of the monitor.
+
+@item @code{position} (optional)
+The (optional) value of this field must be a @code{point}.
+Example:
+@lisp
+(position
+ (point (x 1920)
+ (y 0)))
+@end lisp
+
+@item @code{bg} (optional)
+This field accepts a file-like value representing the wallpaper to use
+on this monitor. It will be used with the @code{fill} option.
+
+@item @code{extra-content} (default: @code{'()})
+Any additional lines to be added to the output configuration block.
+Elements of the list must be either strings or G-expressions.
+
+@end table
+@end deftp
+
+
+@deftp {Data Type} sway-border-color
+
+@table @asis
+@item @code{border} Color of the border.
+@item @code{background} Color of the background.
+@item @code{text} Color of the text.
+@end table
+@end deftp
+
+
+@deftp {Data Type} sway-color
+@table @asis
+@item @code{background}
+@item @code{statusline}
+@item @code{focused-background}
+@item @code{focused-statusline}
+@item @code{focused-workspace}
+@item @code{active-workspace}
+@item @code{inactive-workspace}
+@item @code{urgent-workspace}
+@item @code{binding-mode}
+@end table
+@end deftp
+
+
+@deftp {Data Type} sway-bar
+Describes the Sway bar (see@ @cite{sway-bar(5)}).
+
+@table @asis
+@item @code{identifier} (default: @code{'bar0})
+Identifier of the bar. The value must be a string.
+
+@item @code{position} (default: @code{'top})
+Specify the position of the bar. Accepted values are @code{'top} or
+@code{'bottom}.
+
+@item @code{hidden-state} (default: @code{'hide})
+Specify the apparence of the bar when it is hidden. Accepted values are
+@code{'hide} or @code{show}.
+
+@item @code{binding-mode-indicator} (default: @code{#t})
+Enable or disable the binding mode indicator.
+
+@item @code{colors} (optional)
+An optional @code{sway-color} configuration record.
+
+@item @code{status-command} (default: @code{%sway-status-command})
+This field accept strings and executable file-like values. The default
+value is a script that prints the date and time every second.
+
+Each line printed on @code{stdout} by this script will be displayed on
+the status area of the bar.
+
+@end table
+@end deftp
+
@node Networking Home Services
@subsection Networking Home Services
diff --git a/gnu/home/services/sway.scm b/gnu/home/services/sway.scm
new file mode 100644
index 0000000000..bfec0fcdcf
--- /dev/null
+++ b/gnu/home/services/sway.scm
@@ -0,0 +1,703 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2024 Arnaud Daby-Seesaram <ds-ac@nanein.fr>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix 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 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix 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 GNU Guix. If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu home services sway)
+ #:use-module (guix monads)
+ #:use-module (guix modules)
+ #:use-module (guix gexp)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-26)
+ #:use-module (ice-9 popen)
+ #:use-module (ice-9 format)
+ #:use-module (ice-9 match)
+ #:use-module (guix packages)
+ #:use-module (gnu services configuration)
+ #:use-module (gnu home services)
+ #:use-module (gnu packages freedesktop)
+ #:use-module (gnu packages xdisorg)
+ #:use-module (gnu packages image)
+ #:use-module (gnu packages gnome)
+ #:use-module (gnu packages wm)
+ #:use-module (gnu packages emacs)
+ #:use-module (gnu packages linux)
+ #:use-module (gnu packages base)
+ #:use-module (gnu packages suckless)
+ #:use-module (gnu packages glib)
+ #:export (;; Event codes
+ %ev-code-mouse-left
+ %ev-code-mouse-right
+ %ev-code-mouse-scroll-click
+
+ ;; Configuration records.
+ sway-configuration
+ sway-bar
+ sway-output
+ sway-input
+ point
+ sway-color
+ sway-border-color
+ home-sway-service-type
+ sway-configuration->file
+ sway-mode
+
+ ;; Default values.
+ %sway-default-variables
+ %sway-default-gestures
+ %sway-default-keybindings
+ %sway-default-status-command
+ %sway-default-execs))
+
+;; Helper function.
+(define (flatten l)
+ (let loop ((lst (reverse l)) (acc '()))
+ (match lst
+ (() acc)
+ ((head . tail)
+ (loop tail (append head acc))))))
+
+
+;;;
+;;; Default settings and useful constants.
+;;;
+
+(define %ev-code-mouse-left 272)
+(define %ev-code-mouse-right 273)
+(define %ev-code-mouse-scroll-click 274)
+
+(define %sway-default-variables
+ `((mod . "Mod4")
+ (left . "h")
+ (down . "j")
+ (up . "k")
+ (right . "l")
+ (term . ,#~(string-append #$st "/bin/st"))
+ (menu . ,#~(string-append
+ #$dmenu "/bin/dmenu_path | "
+ #$wmenu "/bin/wmenu | "
+ #$findutils "/bin/xargs "
+ #$sway "/bin/swaymsg exec --"))))
+
+(define %sway-default-gestures
+ `((swipe:3:right . "workspace next_on_output")
+ (swipe:3:left . "workspace prev_on_output")
+ (swipe:3:down . "move to scratchpad")
+ (swipe:3:up . "scratchpad show")))
+
+(define %sway-default-keybindings
+ `(($mod+Return . "exec $term")
+ ($mod+Shift+q . "kill")
+ ($mod+d . "exec $menu")
+ ($mod+Shift+c . "reload")
+ ($mod+Shift+e
+ . ,#~(string-append
+ "exec " #$sway "/bin/swaynag -t warning -m 'You pressed the exit "
+ "shortcut. Do you really want to exit sway? This will end your "
+ "Wayland session.' -B 'Yes, exit sway' '"
+ #$sway "/bin/swaymsg exit'"))
+ ($mod+$left . "focus left")
+ ($mod+$down . "focus down")
+ ($mod+$up . "focus up")
+ ($mod+$right . "focus right")
+ ($mod+Left . "focus left")
+ ($mod+Down . "focus down")
+ ($mod+Up . "focus up")
+ ($mod+Right . "focus right")
+ ($mod+Shift+$left . "move left")
+ ($mod+Shift+$down . "move down")
+ ($mod+Shift+$up . "move up")
+ ($mod+Shift+$right . "move right")
+ ($mod+Shift+Left . "move left")
+ ($mod+Shift+Down . "move down")
+ ($mod+Shift+Up . "move up")
+ ($mod+Shift+Right . "move right")
+ ($mod+1 . "workspace number 1")
+ ($mod+2 . "workspace number 2")
+ ($mod+3 . "workspace number 3")
+ ($mod+4 . "workspace number 4")
+ ($mod+5 . "workspace number 5")
+ ($mod+6 . "workspace number 6")
+ ($mod+7 . "workspace number 7")
+ ($mod+8 . "workspace number 8")
+ ($mod+9 . "workspace number 9")
+ ($mod+0 . "workspace number 10")
+ ($mod+Shift+1 . "move container to workspace number 1")
+ ($mod+Shift+2 . "move container to workspace number 2")
+ ($mod+Shift+3 . "move container to workspace number 3")
+ ($mod+Shift+4 . "move container to workspace number 4")
+ ($mod+Shift+5 . "move container to workspace number 5")
+ ($mod+Shift+6 . "move container to workspace number 6")
+ ($mod+Shift+7 . "move container to workspace number 7")
+ ($mod+Shift+8 . "move container to workspace number 8")
+ ($mod+Shift+9 . "move container to workspace number 9")
+ ($mod+Shift+0 . "move container to workspace number 10")
+ ($mod+b . "splith")
+ ($mod+v . "splitv")
+ ($mod+s . "layout stacking")
+ ($mod+w . "layout tabbed")
+ ($mod+e . "layout toggle split")
+ ($mod+f . "fullscreen")
+ ($mod+Shift+space . "floating toggle")
+ ($mod+space . "focus mode_toggle")
+ ($mod+a . "focus parent")
+ ($mod+Shift+minus . "move scratchpad")
+ ($mod+minus . "scratchpad show")
+ ($mod+r . "mode \"resize\"")))
+
+(define %sway-default-status-command
+ "while date +'%Y-%m-%d %X'; do sleep 1; done")
+
+(define %sway-default-execs
+ (list
+ #~(string-append
+ #$swayidle "/bin/swayidle -w \\\n"
+ ;; 300: lock screen.
+ " timeout 300 '" #$swaylock "/bin/swaylock "
+ "--indicator-radius 75 "
+ "-i " #$sway "/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png"
+ " -f -c 000000' \\\n"
+ ;; 600: lock + screen off.
+ " timeout 600 '" #$sway "/bin/swaymsg \"output * power off\"' \\\n"
+ ;; Resume + sleep.
+ " resume '" #$sway "/bin/swaymsg \"output * power on\"' \\\n"
+ " before-sleep '" #$swaylock "/bin/swaylock -f -c 000000'")))
+
+
+;;;
+;;; Definition of configurations.
+;;;
+
+(define (list-of-string-or-gexp? lst)
+ (every (lambda (elt)
+ (or (string? elt)
+ (gexp? elt)))
+ lst))
+
+(define (list-of-packages? lst)
+ (every package? lst))
+
+(define (bar-position? p)
+ (member p '(top bottom)))
+
+(define (hidden-state? st)
+ (member st '(hide show)))
+
+(define (string-or-symbol? s)
+ (or (string? s)
+ (symbol? s)))
+
+(define (strings? lst)
+ (every string? lst))
+
+(define-maybe string (no-serialization))
+(define-maybe strings (no-serialization))
+
+(define-configuration/no-serialization sway-input
+ (identifier
+ (string-or-symbol '*)
+ "Identifier of the input.")
+ (xkb-layout
+ maybe-string
+ "Keyboard layout.")
+ (xkb-model
+ maybe-string
+ "Keyboard model.")
+ (xkb-options
+ maybe-strings
+ "Keyboard options.")
+ (xkb-variant
+ maybe-string
+ "Keyboard layout variant.")
+ (extra-content
+ (list-of-string-or-gexp '())
+ "Lines to add at the end of the configuration file."))
+
+(define (sway-inputs? lst)
+ (every sway-input? lst))
+
+(define-configuration/no-serialization sway-border-color
+ (border
+ string
+ "Border color.")
+ (background
+ string
+ "Background color.")
+ (text
+ string
+ "Text color."))
+
+(define-maybe sway-border-color (no-serialization))
+
+(define-configuration/no-serialization sway-color
+ (background
+ maybe-string
+ "Background color of the bar.")
+ (statusline
+ maybe-string
+ "Text color of the separator.")
+ (focused-background
+ maybe-string
+ "Background color of the bar on the currently focused monitor.")
+ (focused-statusline
+ maybe-string
+ "Text color of the statusline on the currently focused monitor.")
+ (focused-workspace
+ maybe-sway-border-color
+ "...")
+ (active-workspace
+ maybe-sway-border-color
+ "...")
+ (inactive-workspace
+ maybe-sway-border-color
+ "...")
+ (urgent-workspace
+ maybe-sway-border-color
+ "...")
+ (binding-mode
+ maybe-sway-border-color
+ "..."))
+
+(define-maybe sway-color (no-serialization))
+
+(define (make-alist-predicate key? val?)
+ (lambda (lst)
+ (every
+ (lambda (item)
+ (match item
+ ((k . v)
+ (and (key? k)
+ (val? v)))
+ (_ #f)))
+ lst)))
+
+(define (string-or-gexp? s)
+ (or (string? s)
+ (gexp? s)))
+
+(define bindings?
+ (make-alist-predicate symbol? string-or-gexp?))
+(define mouse-bindings?
+ (make-alist-pr
This message was truncated. Download the full message here.
P
P
pelzflorian (Florian Pelz) wrote on 14 Sep 15:28 +0200
(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)(address . 72714@debbugs.gnu.org)
87bk0qe54l.fsf@pelzflorian.de
Thank you Arnaud for this well-written home-sway-service!

Some comments for you or the one who pushes your patch. I would
rather not take any responsibility for sway myself.

Toggle quote (3 lines)
> @quotation Note
> This home service only sets up configuration file and profile packages

Typo: Please add 'the': sets up the configuration file and profile packages

Toggle quote (4 lines)
> The function @code{sway-configuration->file} defined below can be used
> to provide the value for the @code{sway-configuration} field of
> @code{greetd-wlgreet-sway-session}.

Good. Even though it is a little strange that one would add a home
module (gnu home services sway) to the operating-system configuration,
I know no better place for this `sway-configuration->file' procedure,
since the record is for Guix Home and being able to use it for greetd
is just an extra feature.


Toggle quote (23 lines)
> @lisp
> (define bg-file
> (computed-file
> "background.png"
> #~(let* ((insvg (string-append
> #$guix-backgrounds
> "/share/backgrounds/guix/guix-checkered-16-9.svg"))
> (out #$output)
> (cmd (string-append
> #$librsvg "/bin/rsvg-convert " insvg " -o " out)))
> (system cmd))))
>
> (service home-sway-service-type
> (sway-configuration
> (gestures
> '((swipe:3:down . "move to scratchpad")
> (swipe:3:up . "scratchpad show")))
> (outputs
> (list (sway-output
> (identifier '*)
> (bg bg-file))))))
> @end lisp

Why not (bg #~(file-append #$guix-backgrounds
"\
/share/backgrounds/guix/guix-checkered-16-9.svg"))
? This does not work right now, but could you change bg and
perhaps status-command to accept gexps?


Toggle quote (3 lines)
> swiping down (resp.@ up) with three fingers moves the active window to
> the scratchpad (resp.@ shows/hides the scratchpad).

Should be with a colon: resp.@: up

You should run untabify on all of gnu/home/services/sway.scm
to get rid of nasty tabs.

Otherwise looks really good to me (although I have not cross-checked
the man pages).

Regards,
Florian
P
P
pelzflorian (Florian Pelz) wrote on 14 Sep 16:06 +0200
(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)(address . 72714@debbugs.gnu.org)
87wmje1g8y.fsf@pelzflorian.de
One more thing,

Toggle quote (7 lines)
> (add-line-if " xkb_layout" xkb-layout)
> (add-line-if " xkb_model" xkb-model)
> (add-line-if " xkb_variant" xkb-variant)
> (if (eq? %unset-value xkb-options)
> %unset-value
> (string-concatenate (cons " xkb_options " xkb-options)))))

this does not put a comma between each element of xkb-options.

Could you make it join the xkb-options with a comma in between?

Regards,
Florian
A
A
Arnaud Daby-Seesaram wrote on 17 Sep 08:52 +0200
(name . pelzflorian (Florian Pelz))(address . pelzflorian@pelzflorian.de)(address . 72714@debbugs.gnu.org)
87plp2db5y.fsf@nanein.fr
Hi Florian,

Thank you for your review. I will submit a v5 soon to take your remarks
into account and add an additional configuration field (to easily add
modes, e.g. the resize mode).

Toggle quote (9 lines)
>> The function @code{sway-configuration->file} defined below can be used
>> to provide the value for the @code{sway-configuration} field of
>> @code{greetd-wlgreet-sway-session}.
>
> Good. Even though it is a little strange that one would add a home
> module (gnu home services sway) to the operating-system configuration,
> I know no better place for this `sway-configuration->file' procedure,
> since the record is for Guix Home and being able to use it for greetd
> is just an extra feature.
Yes, I agree; I could not find a better place for this function either.
Do you think that this note is helpful, or should I remove it?

Best regards,

--
Arnaud
-----BEGIN PGP SIGNATURE-----

iQJEBAEBCgAuFiEEMgqfJ4U0fby1t860ojLKXoMTiAwFAmbpJzoQHGRzLWFjQG5h
bmVpbi5mcgAKCRCiMspegxOIDAlmEACVja8D3L53O0CnLdRCgYY0vBQcKwt4R79T
h5BvcAWF+mZK+lGZ+myLtTLSh9oYuF3dCjD29KCnpC07/b4HohDow9ibfGEoe+sp
7GFAef0PH+bWjMiQVgOVNkFZeXH8XuaDCjNMgvkVZ41BzNp+mKQ2zCbZnVNzNRnY
O6GnbYZoGhAJqZa6knCIlMaTUsMYgAaWl3NvBtBHG4+8CPPPMONcRG1DmOeCUyJY
GrzUOvTMIGcMbr6i8dPlh4Z90gHa6OleeMy7U9rcZqxErpuYS8wCEa6bg28rG5Y/
R4mT/DcYNseV094+ljpAgl/7eGqxwe05aaj/8tjg3os2KoES6T5/gsYTVO1iar0B
1v93FrjmhVxnZrxLULhFlA13y4wTT28TMXvU7v8NiT5iuWhn2lDswsoN9pJf9O9+
7f5I5oud6WKSGk21P+WjjLWyJ2poUMBHzCqUc+E4aZV2/kk27KananJI1MwaQsm4
pPa/mWE6wsdgI7RSbQD/s13erP6nazqa0VgNM7tH78R2zv4vVe2vopUPhadVtEsY
KMzA2/1LogvgU/bpTns4IIpIX9UPJRCqWG7gR0MBYJbPyEgS1m5boqKR3SI8RlyV
pqP9n6URCBazBh+avYbO9CXXdyHmWZFBsXn17eu4OFIK5WSg5JVvFbPIe6Ft+qYM
yj85Htihvg==
=PX4M
-----END PGP SIGNATURE-----

A
A
Arnaud Daby-Seesaram wrote on 18 Sep 10:15 +0200
[PATCH v5] home: services: Add 'home-sway-service-type'.
(address . 72714@debbugs.gnu.org)(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)
20240918081545.8885-1-ds-ac@nanein.fr
* gnu/home/services/sway.scm: New file.
(home-sway-service-type): New variable.
(sway-configuration->file): New procedure.
(sway-configuration): New configuration record.
(sway-bar): New configuration record.
(sway-output): New configuration record.
(sway-input): New configuration record.
(point): New configuration record.
(sway-color): New configuration record.
(sway-border-color): New configuration record.
(flatten): New procedure.
* gnu/local.mk: Add gnu/home/services/sway.scm.
* doc/guix.texi (Sway window manager): New node to document the above changes.
---
doc/guix.texi | 329 +++++++++++++++++
gnu/home/services/sway.scm | 711 +++++++++++++++++++++++++++++++++++++
gnu/local.mk | 1 +
3 files changed, 1041 insertions(+)
create mode 100644 gnu/home/services/sway.scm

Toggle diff (566 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index bdaefe3802..07598a2a7e 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -130,6 +130,7 @@ Copyright @copyright{} 2024 Richard Sent@*
Copyright @copyright{} 2024 Dariqq@*
Copyright @copyright{} 2024 Denis 'GNUtoo' Carikli@*
Copyright @copyright{} 2024 Fabio Natali@*
+Copyright @copyright{} 2024 Arnaud Daby-Seesaram@*
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -460,6 +461,7 @@ Home Services
* Mail: Mail Home Services. Services for managing mail.
* Messaging: Messaging Home Services. Services for managing messaging.
* Media: Media Home Services. Services for managing media.
+* Sway: Sway window manager. Setting up the Sway configuration.
* Networking: Networking Home Services. Networking services.
* Miscellaneous: Miscellaneous Home Services. More services.
@@ -45190,6 +45192,7 @@ services)}.
* Mail: Mail Home Services. Services for managing mail.
* Messaging: Messaging Home Services. Services for managing messaging.
* Media: Media Home Services. Services for managing media.
+* Sway: Sway window manager. Setting up the Sway configuration.
* Networking: Networking Home Services. Networking services.
* Miscellaneous: Miscellaneous Home Services. More services.
@end menu
@@ -47104,6 +47107,332 @@ kodi} for more information.
@end table
@end deftp
+@node Sway window manager
+@subsection Sway window manager
+
+@cindex sway, Home Service
+@cindex sway, configuration
+The @code{(gnu home services sway)} module provides
+@code{home-sway-service-type}, a home service to configure sway in a
+declarative way.
+
+@quotation Note
+This home service only sets up the configuration file and profile
+packages for sway. It does @i{not} start sway in any way. If you want
+to do so, you might be interested in using
+@code{greetd-wlgreet-sway-session} instead.
+
+The function @code{sway-configuration->file} defined below can be used
+to provide the value for the @code{sway-configuration} field of
+@code{greetd-wlgreet-sway-session}.
+@end quotation
+
+@defvar sway-configuration->file
+This function takes a @code{sway-configuration} record (defined below),
+and returns a file-like object represented the serialized configuration.
+@end defvar
+
+@defvar home-sway-service-type
+This is a home service type to set up Sway. It takes care of:
+@itemize
+@item
+providing a @file{~/.config/sway/config} file,
+@item
+adding sway-related packages to your profile.
+@end itemize
+
+Here is an example of a service and its configuration that you could add
+to the @code{services} field of your @code{home-environment}:
+
+@lisp
+(service home-sway-service-type
+ (sway-configuration
+ (gestures
+ '((swipe:3:down . "move to scratchpad")
+ (swipe:3:up . "scratchpad show")))
+ (outputs
+ (list (sway-output
+ (identifier '*)
+ (bg (file-append guix-backgrounds
+ "\
+/share/backgrounds/guix/guix-checkered-16-9.svg")))))))
+@end lisp
+
+The above example describes a sway configuration in which
+@itemize
+@item
+all monitors use a particular wallpaper whose @file{.svg} is provided by
+the @code{guix-background} package;
+@item
+swiping down (resp.@: up) with three fingers moves the active window to
+the scratchpad (resp.@: shows/hides the scratchpad).
+@end itemize
+@end defvar
+
+@deftp {Data Type} sway-configuration
+This configuration record describes the sway configuration
+(see@ @cite{sway(5)}). Available fields are:
+
+@table @asis
+@item @code{variables} (default: @code{%sway-default-variables})
+The value of this field is an association list in which keys are symbols
+and values are strings or G-expressions (@pxref{G-Expressions}).
+
+Example: @code{'(mod . "Mod4")}.
+
+@item @code{keybindings} (default: @code{%sway-default-keybindings})
+This field describes keybindings for the @emph{default} mode. As above,
+the value is an association list: keys are symbols and values are either
+strings, G-expressions or file-append objects.
+
+Examples using:
+@itemize
+@item
+a string: @code{'($mod+Return . "exec $term")}
+@item
+a G-exp: @code{`($mod+t . ,#~(string-append #$st "/bin/st"))}
+@item
+a file-append: @code{`($mod+t . ,(file-append st "/bin/st"))}
+@end itemize
+
+@item @code{gestures} (default: @code{%sway-default-gestures})
+Similar to the previous field, but for finger-gestures.
+
+The following snippet allows to navigate through workspaces by swiping
+right and left with three fingers:
+@lisp
+'((swipe:3:right . "workspace next_on_output")
+ (swipe:3:left . "workspace prev_on_output"))
+@end lisp
+
+@item @code{packages} (default: @code{%sway-default-packages})
+This field describes a list of packages to add to the user profile.
+
+@item @code{inputs} (default: @code{(list (sway-input))})
+List of @code{sway-input} configuration records.
+
+@item @code{outputs} (default: @code{'()})
+List of @code{sway-output} configuration records.
+
+@item @code{bar} (default: @code{(sway-bar)})
+Bar configuration.
+
+@item @code{modes} (default: @code{'()})
+Optional list of @code{sway-mode} records (described below).
+
+@item @code{always-execs} (default: @code{'()})
+Programs to execute at startup time @i{and} after every configuration
+reload. The value of this field is a list of strings or G-expressions.
+
+@item @code{execs} (default: @code{%sway-default-execs})
+Programs to execute at startup time. The value of this field is a list
+of strings or G-expressions.
+
+The default value, @code{%sway-default-execs}, executes @code{swayidle}
+in order to lock the screen after 5@ minutes of inactivity (displaying a
+background distributed with Sway) and turn of the screen after
+10@ minutes of inactivity.
+
+@item @code{extra-content} (default: @code{'()})
+Lines to add to the configuration file. The value of this field is a
+list of strings or G-expressions.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-input
+@code{sway-input} records describe input blocks
+(see@ @cite{sway-input(5)}). Available fields are:
+
+@table @asis
+@item @code{identifier} (default: @code{'*})
+Identifier of the input. The field accepts symbols and strings. If a
+string is used, it will be quoted in the generated configuration file.
+
+@item @code{xkb-layout} (optional)
+Keyboard specific option. Comma-separated keyboard layout(s) to use.
+
+@item @code{xkb-model} (optional)
+Keyboard specific option. String providing the keyboard model.
+
+@item @code{xkb-options} (optional)
+Keyboard specific option. Additional xkb options for the keyboard.
+
+@item @code{xkb-variant} (optional)
+Keyboard specific option. String specifying the variant of the layout.
+
+@item @code{extra-content} (default: @code{'()})
+Lines to add to the input block. The value of this field is a list of
+strings.
+@end table
+
+For example, the following snippet makes all keyboards use a french
+layout, in which @kbd{capslock} has been remaped to @kbd{ctrl}:
+@lisp
+(sway-input (identifier "type:keyboard")
+ (xkb-layout "fr")
+ (xkb-options '("ctrl:nocaps")))
+@end lisp
+@end deftp
+
+@deftp {Data Type} sway-output
+@code{sway-output} records describe sway outputs
+(see@ @cite{sway-output(5)}). Available fields are:
+
+@table @asis
+@item @code{identifier} (default: @code{'*})
+Identifier of the monitor. If the
+@code{identifier} is a symbol, it is inserted as is; if it is a string,
+it will be quoted in the configuration file.
+
+@item @code{resolution} (optional)
+This string defines the resolution of the monitor.
+
+@item @code{position} (optional)
+The (optional) value of this field must be a @code{point}.
+Example:
+@lisp
+(position
+ (point (x 1920)
+ (y 0)))
+@end lisp
+
+@item @code{bg} (optional)
+This field accepts a file-like value representing the wallpaper to use
+on this monitor. It will be used with the @code{fill} option.
+
+@item @code{extra-content} (default: @code{'()})
+Any additional lines to be added to the output configuration block.
+Elements of the list must be either strings or G-expressions.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-border-color
+
+@table @code
+@item border
+Color of the border.
+@item background
+Color of the background.
+@item text
+Color of the text.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-color
+@table @asis
+@item @code{background} (optional string)
+Background color of the bar.
+@item @code{statusline} (optional string)
+Text color of the separator.
+@item @code{focused-background} (optional string)
+Background color of the bar on the currently focused monitor.
+@item @code{focused-statusline} (optional string)
+Text color of the statusline on the currently focused monitor.
+@item @code{focused-workspace} (optional @code{sway-border-color})
+Color scheme for focused workspaces.
+@item @code{active-workspace} (optional @code{sway-border-color})
+Colour scheme for active workspaces.
+@item @code{inactive-workspace} (optional @code{sway-border-color})
+Colour scheme for inactive workspaces.
+@item @code{urgent-workspace} (optional @code{sway-border-color})
+Colour scheme for workspaces containing `urgent' windows.
+@item @code{binding-mode} (optional @code{sway-border-color})
+Colour scheme for the binding mode indicator.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-bar
+Describes the Sway bar (see@ @cite{sway-bar(5)}).
+
+@table @asis
+@item @code{identifier} (default: @code{'bar0})
+Identifier of the bar. The value must be a string.
+
+@item @code{position} (default: @code{'top})
+Specify the position of the bar. Accepted values are @code{'top} or
+@code{'bottom}.
+
+@item @code{hidden-state} (default: @code{'hide})
+Specify the apparence of the bar when it is hidden. Accepted values are
+@code{'hide} or @code{show}.
+
+@item @code{binding-mode-indicator} (default: @code{#t})
+Enable or disable the binding mode indicator.
+
+@item @code{colors} (optional)
+An optional @code{sway-color} configuration record.
+
+@item @code{status-command} (default: @code{%sway-status-command})
+This field accept strings, G-expressions and executable file-like
+values. The default value is a command (string) that prints the date
+and time every second.
+
+Each line printed on @code{stdout} by this command (or script) will be
+displayed on the status area of the bar.
+
+Below are a few examples using:
+@itemize
+@item
+a string: @code{"while date +'%Y-%m-%d %X'; do sleep 1; done"},
+@item
+a G-exp:
+@lisp
+#~(string-append "while "
+ #$coreutils "/bin/date"
+ " +'%Y-%m-%d %X'; do sleep 1; done")
+@end lisp
+@item
+an executable file:
+@lisp
+(program-file
+ "sway-bar-status"
+ (with-imported-modules
+ (source-module-closure
+ '((ice-9 textual-ports) (ice-9 regex)
+ (ice-9 popen) (ice-9 format)
+ (srfi srfi-19)))
+ #~(begin
+ (use-modules (ice-9 format)
+ (srfi srfi-19))
+ (let loop ()
+ (let* ((date (date->string
+ (current-date)
+ "~d/~m/~Y (~a) ~H:~M:~S")))
+ (format #t "~a~%~!" date)
+ (sleep 1)
+ (loop))))))
+@end lisp
+@end itemize
+@end table
+@end deftp
+
+@deftp {Data Type} sway-mode
+Describes a Sway mode.
+
+Here is a mockup of the resize mode of the default Sway configuration:
+@example
+(sway-mode
+ (mode-name "resize")
+ (keybindings
+ '(($left . "resize shrink width 10px")
+ ($right . "resize grow width 10px")
+ ($down . "resize grow height 10px")
+ ($up . "resize shrink height 10px")
+ (Return . "mode \"default\"")
+ (Escape . "mode \"default\""))))
+@end example
+
+@table @asis
+@item @code{mode-name} (default @code{"default"})
+Name of the mode.
+@item @code{keybindings} (default @code{'()})
+This field describes keybindings. The value is an association list:
+keys are symbols and values are either strings or G-expressions.
+@item @code{mouse-bindings} (default @code{'()})
+Ditto, but keys are mouse events.
+@end table
+@end deftp
+
@node Networking Home Services
@subsection Networking Home Services
diff --git a/gnu/home/services/sway.scm b/gnu/home/services/sway.scm
new file mode 100644
index 0000000000..7d665e7280
--- /dev/null
+++ b/gnu/home/services/sway.scm
@@ -0,0 +1,711 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2024 Arnaud Daby-Seesaram <ds-ac@nanein.fr>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix 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 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix 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 GNU Guix. If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu home services sway)
+ #:use-module (guix monads)
+ #:use-module (guix modules)
+ #:use-module (guix gexp)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-26)
+ #:use-module (ice-9 popen)
+ #:use-module (ice-9 format)
+ #:use-module (ice-9 match)
+ #:use-module (guix packages)
+ #:use-module (gnu services configuration)
+ #:use-module (gnu home services)
+ #:use-module (gnu packages freedesktop)
+ #:use-module (gnu packages xdisorg)
+ #:use-module (gnu packages image)
+ #:use-module (gnu packages gnome)
+ #:use-module (gnu packages wm)
+ #:use-module (gnu packages emacs)
+ #:use-module (gnu packages linux)
+ #:use-module (gnu packages base)
+ #:use-module (gnu packages suckless)
+ #:use-module (gnu packages glib)
+ #:export (;; Event codes
+ %ev-code-mouse-left
+ %ev-code-mouse-right
+ %ev-code-mouse-scroll-click
+
+ ;; Configuration records.
+ sway-configuration
+ sway-bar
+ sway-output
+ sway-input
+ point
+ sway-color
+ sway-border-color
+ home-sway-service-type
+ sway-configuration->file
+ sway-mode
+
+ ;; Default values.
+ %sway-default-variables
+ %sway-default-gestures
+ %sway-default-keybindings
+ %sway-default-status-command
+ %sway-default-execs))
+
+;; Helper function.
+(define (flatten l)
+ (let loop ((lst (reverse l)) (acc '()))
+ (match lst
+ (() acc)
+ ((head . tail)
+ (loop tail (append head acc))))))
+
+
+;;;
+;;; Default settings and useful constants.
+;;;
+
+(define %ev-code-mouse-left 272)
+(define %ev-code-mouse-right 273)
+(define %ev-code-mouse-scroll-click 274)
+
+(define %sway-default-variables
+ `((mod . "Mod4")
+ (left . "h")
+ (down . "j")
+ (up . "k")
+ (right . "l")
+ (term . ,(file-append st "/bin/st"))
+ (menu . ,#~(string-append
+ #$dmenu "/bin/dmenu_path | "
+ #$wmenu "/bin/wmenu | "
+ #$findutils "/bin/xargs "
+ #$sway "/bin/swaymsg exec --"))))
+
+(define %sway-default-gestures
+ '((swipe:3:right . "workspace next_on_output")
+ (swipe:3:left . "workspace prev_on_output")
+ (swipe:3:down . "move to scratchpad")
+ (swipe:3:up . "scratchpad show")))
+
+(define %sway-default-keybindings
+ `(($mod+Return . "exec $term")
+ ($mod+Shift+q . "kill")
+ ($mod+d . "exec $menu")
+ ($mod+Shift+c . "reload")
+ ($mod+Shift+e
+ . ,#~(string-append
+ "exec " #$sway "/bin/swaynag -t warning -m 'You pressed the exit "
+ "shortcut. Do you really want to exit sway? This will end your "
+ "Wayland session.' -B 'Yes, exit sway' '"
+ #$sway "/bin/swaymsg exit'"))
+ ($mod+$left . "focus left")
+ ($mod+$down . "focus down")
+ ($mod+$up . "focus up")
+ ($mod+$right . "focus right")
+ ($mod+Left . "focus left")
+ ($mod+Down . "focus down")
+ ($mod+Up . "focus up")
+ ($mod+Right . "focus right")
+ ($mod+Shift+$left . "move left")
+ ($mod+Shift+$down . "move down")
+ ($mod+Shift+$up . "move up")
+ ($mod+Shift+$right . "move right")
+ ($mod+Shift+Left . "move left")
+ ($mod+Shift+Down . "move down")
+ ($mod+Shift+Up . "move up")
+ ($mod+Shift+Right . "move right")
+ ($mod+1 . "workspace number 1")
+ ($mod+2 . "workspace number 2")
+ ($mod+3 . "workspace number 3")
+ ($mod+4 . "workspace number 4")
+ ($mod+5 . "workspace number 5")
+ ($mod+6 . "workspace number 6")
+ ($mod+7 . "workspace number 7")
+ ($mod+8 . "workspace number 8")
+ ($mod+9 . "workspace number 9")
+ ($mod+0 . "workspace number 10")
+ ($mod+Shift+1 . "move container to workspace number 1")
+ ($mod+Shift+2 . "move container to workspace number 2")
+ ($mod+Shift+3 . "move container to workspace number 3")
+ ($mod+Shift+4 . "move container to workspace number 4")
+ ($mod+Shift+5 . "move container to workspace number 5")
+ ($mod+Shift+6 . "move container to workspace number 6")
+ ($mod+Shift+7 . "move container to workspace number 7")
+ ($mod+Shift+8 . "move container to workspace number 8")
+ ($mod+Shift+9 . "move container to workspace number 9")
+ ($mod+Shift+0 . "move container to workspace number 10")
+ ($mod+b . "splith")
+ ($mod+v . "splitv")
+ ($mod+s . "layout stacking")
+ ($mod+w . "layout tabbed")
+ ($mod+e . "layout toggle split")
+ ($mod+f . "fullscreen")
+ ($mod+Shift+space . "floating toggle")
+ ($mod+space . "focus mode_toggle")
+ ($mod+a . "focus parent")
+ ($mod+Shift+minus . "move scratchpad")
+ ($mod+minus . "scratchpad show")
+ ($mod+r . "mode \"resize\"")))
+
+(define %sway-default-status-command
+ "while date +'%Y-%m-%d %X'; do sleep 1; done")
+
+(define %sway-default-execs
+ (list
+ #~(string-append
+ #$swayidle "/bin/swayidle -w \\\n"
+ ;; 300: lock screen.
+ " timeout 300 '" #$swaylock "/bin/swaylock "
+ "--indicator-radius 75 "
+ "-i " #$sway "/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png"
+ " -f -c 000000' \\\n"
+ ;; 600: lock + screen off.
+ " timeout 600 '" #$sway "/bin/swaymsg \"output * power off\"' \\\n"
+ ;; Resume + sleep.
+ " resume '" #$sway "/bin/swaymsg \"output * power on\"' \\\n"
+ " before-sleep '" #$swaylock "/bin/swaylock -f -c 000000'")))
+
+
+;;;
+;;; Definition of configurations.
+;;;
+
+(define (string-ish? s)
+ (or (gexp? s)
+ (file-append? s)
+ (string? s)))
+
+(define (list-of-string-ish? lst)
+ (every string-ish? lst))
+
+(define (list-of-packages? lst)
+ (every package? lst))
+
+(define (bar-position? p)
+ (member p '(top bottom)))
+
+(define (hidden-state? st)
+ (member st '(hide show
This message was truncated. Download the full message here.
A
A
Arnaud Daby-Seesaram wrote on 18 Sep 20:56 +0200
(address . 72714@debbugs.gnu.org)
87zfo494f1.fsf@nanein.fr
Apologies for the noise.

I just realised that I forgot one line in the commit message:
(sway-mode): New configuration record.

Best,

--
Arnaud
-----BEGIN PGP SIGNATURE-----

iQJEBAEBCgAuFiEEMgqfJ4U0fby1t860ojLKXoMTiAwFAmbrImMQHGRzLWFjQG5h
bmVpbi5mcgAKCRCiMspegxOIDI2TD/4rsIzME46DhQkk1Vy8jieL7Y48PYJiTNYw
VpiRhKzZmjn5vEMyV23tUQiOGPuBSZAxiqKH2Fw/Y7BwPAhck+ciqsM+c+8FS6Hn
qcdLyw7pRV8Z3O5z6q2E65hxBNLKqMLPmS3BFZ0OkwKarl+YN4dHa98dozyN7B79
XMX7v/Y+QOC7GeLhvlmVq2tmb6caj1NYT85rK/44PeQQQ2wAkko4UdxRdCIND280
j0Li0BOQrR0lkeGDx8gbjAxuIxVm4zB5zhkdmkbN8083YU+mJPlK2PYJGTF72ZMF
ijApVAiS4L2o1d92A8EOfR9yeJDiCcmCBpvjHYhWiMCotvwTSugbmbbIou/A3YJF
k1NLRBX/P2hlPb+va01d5sFTNC5JK4kvy6V6bSHRXui9+xGBiZRmxJkyL+2eOXgl
DIvcx1hWFuZ6ggA5iKD9H8CXvD29BOs1WtvkUvePwa2Etf2z/nJAjo5sh8k2vJko
fT+6Jv0O5ZF4siSrtg3/3jXvd0V29QIaUXaB7Uzw3BwYGxMGJWaAxnKsfHQg0K9T
jI2Ng5hX4VJUPkS+WLaBADIEy0gThmTJ++R7CizbwtLkPmreCyM5SCPnzCtqfNGI
8tqrTp+wSg+XIsHrHCiN5Ugk8HX3mv1ZLk1ujjKSDlpZqAMIcvYqL7i+unThwkN9
paaDp82T2A==
=crwo
-----END PGP SIGNATURE-----

P
P
pelzflorian (Florian Pelz) wrote on 20 Sep 18:45 +0200
Re: [bug#72714] [PATCH v4] home: services: Add 'home-sway-service-type'.
(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)(address . 72714@debbugs.gnu.org)
87bk0icm0j.fsf@pelzflorian.de
Hello Arnaud. I’m still looking at the details of sway, so I could
myself push your patch with confidence to guix.git, but would also be
happy if others pushed it. I am already using it on my family’s media
PC now [1]. Thank you for it!

Arnaud Daby-Seesaram <ds-ac@nanein.fr> writes:
Toggle quote (14 lines)
>>> The function @code{sway-configuration->file} defined below can be used
>>> to provide the value for the @code{sway-configuration} field of
>>> @code{greetd-wlgreet-sway-session}.
>>
>> Good. Even though it is a little strange that one would add a home
>> module (gnu home services sway) to the operating-system configuration,
>> I know no better place for this `sway-configuration->file' procedure,
>> since the record is for Guix Home and being able to use it for greetd
>> is just an extra feature.
> Yes, I agree; I could not find a better place for this function either.
> Do you think that this note is helpful, or should I remove it?
>
> Best regards,

That one can use your `sway-configuration' enables one to configure the
inputs field declaratively to use another keyboard layout in the
greeter. It is a good feature. But perhaps add the word “optionally”
to make clear users do not have to provide a sway-configuration to the
greeter.


Toggle quote (14 lines)
> @lisp
> (service home-sway-service-type
> (sway-configuration
> (gestures
> '((swipe:3:down . "move to scratchpad")
> (swipe:3:up . "scratchpad show")))
> (outputs
> (list (sway-output
> (identifier '*)
> (bg (file-append guix-backgrounds
> "\
> /share/backgrounds/guix/guix-checkered-16-9.svg")))))))
> @end lisp

Now that I tested this code, I notice that SVG backgrounds work only
if and only if librsvg is found. Still, I think it is better this way
with file-append. Perhaps add a note to doc/guix.texi here that this
librsvg must be installed or propagated in the packages field.

Toggle quote (5 lines)
> @table @asis
> @item @code{mode-name} (default @code{"default"})
> Name of the mode.
> @item @code{keybindings} (default @code{'()})

These fields are missing a colon “default: ”. In other places you
correctly write “default: ”.

Regards,
Florian

H
H
Hilton Chain wrote on 22 Sep 10:14 +0200
Re: [bug#72714] [PATCH v5] home: services: Add 'home-sway-service-type'.
(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)(address . 72714@debbugs.gnu.org)
87r09cm7ev.wl-hako@ultrarare.space
Hi Arnaud,

On Wed, 18 Sep 2024 16:15:40 +0800,
Arnaud Daby-Seesaram via Guix-patches via wrote:
Toggle quote (21 lines)
>
> * gnu/home/services/sway.scm: New file.
> (home-sway-service-type): New variable.
> (sway-configuration->file): New procedure.
> (sway-configuration): New configuration record.
> (sway-bar): New configuration record.
> (sway-output): New configuration record.
> (sway-input): New configuration record.
> (point): New configuration record.
> (sway-color): New configuration record.
> (sway-border-color): New configuration record.
> (flatten): New procedure.
> * gnu/local.mk: Add gnu/home/services/sway.scm.
> * doc/guix.texi (Sway window manager): New node to document the above changes.
> ---
> doc/guix.texi | 329 +++++++++++++++++
> gnu/home/services/sway.scm | 711 +++++++++++++++++++++++++++++++++++++
> gnu/local.mk | 1 +
> 3 files changed, 1041 insertions(+)
> create mode 100644 gnu/home/services/sway.scm

Thank you for the sway service! Tried to convert my config and the resulted
code looks much clearer :)

Can `sway-configuration-bar' be optional? In my case it's not used.

Thanks
A
A
Arnaud Daby-Seesaram wrote on 22 Sep 15:43 +0200
Re: [bug#72714] [PATCH v4] home: services: Add 'home-sway-service-type'.
(name . pelzflorian (Florian Pelz))(address . pelzflorian@pelzflorian.de)
875xqn4xda.fsf@nanein.fr
Hello Florian and Hilton,

Thank you for your words and reviews! It is nice to know that a few
people are interested :).

Toggle quote (3 lines)
> I’m still looking at the details of sway, so I could myself push your
> patch with confidence to guix.git, but would also be happy if others
> pushed it
Nice, NB: it is also fine


Upon reading the code again, one point is still unclear: the list of
packages that I include in user profiles seems a bit random :/.

- sway, swaylock and swaybg: useful to launch some commands manually
(including swaymsg).

- waybar, dmenu and bemenu: do not seem necessary. I will probably
remove them.

- dbus, xdg-desktop-portal and xdg-desktop-portal-wlr: may be
interesting to have. On my laptop, screen sharing¹ only works when
xdg-desktop-portal and xdg-desktop-portal-wlr are in the same profile²
(associated executable files end up in ~/.guix-home/profile/libexec/).

¹: I do not have a fully functional setup
for screen sharing yet (it does not work
in all web browsers). I (or someone else)
should probably add elements in the
default `execs' / `always-execs' fields
if/when they have a working setup later.
NB: this should not be a road blocker for
the current patch IMHO.

²: I do not know if that is a hard
requirement or if my issues are related to
something else.

- slurp and grim: screenshots (+ screen selection when screen sharing).

I will probably define a new variable `%sway-default-packages'
containing the above packages (minus waybar, ...). WDYT?


Hilton Chain <hako@ultrarare.space> writes:
Toggle quote (1 lines)
> Can `sway-configuration-bar' be optional? In my case it's not used.
Yes indeed. In the v6, I will try to make a few fields optional, and
also avoid empty groups in produced configuration file.


Toggle quote (4 lines)
> Arnaud Daby-Seesaram <ds-ac@nanein.fr> writes:
>>>> The function @code{sway-configuration->file} defined below can be used
>>>> to provide the value for the @code{sway-configuration} field of
>>>> @code{greetd-wlgreet-sway-session}.
[...]
Toggle quote (5 lines)
> That one can use your `sway-configuration' enables one to configure the
> inputs field declaratively to use another keyboard layout in the
> greeter. It is a good feature. But perhaps add the word “optionally”
> to make clear users do not have to provide a sway-configuration to the
> greeter.
Indeed; I will try to phrase this properly.

Toggle quote (18 lines)
>> @lisp
>> (service home-sway-service-type
>> (sway-configuration
>> (gestures
>> '((swipe:3:down . "move to scratchpad")
>> (swipe:3:up . "scratchpad show")))
>> (outputs
>> (list (sway-output
>> (identifier '*)
>> (bg (file-append guix-backgrounds
>> "\
>> /share/backgrounds/guix/guix-checkered-16-9.svg")))))))
>> @end lisp
>
> Now that I tested this code, I notice that SVG backgrounds work only
> if and only if librsvg is found. Still, I think it is better this way
> with file-append. Perhaps add a note to doc/guix.texi here that this
> librsvg must be installed or propagated in the packages field.
I will add a note in the next version of the doc, to hint towards the
two solutions to use a svg file: adding librsvg to the profile, or
computing the png and put it in the store using a "computed-file" in the
configuration (as in the second version of the patch).

Toggle quote (7 lines)
>> @table @asis
>> @item @code{mode-name} (default @code{"default"})
>> Name of the mode.
>> @item @code{keybindings} (default @code{'()})
>
> These fields are missing a colon “default: ”. In other places you
> correctly write “default: ”.
Got it, thx!

Best regards,

--
Arnaud
-----BEGIN PGP SIGNATURE-----

iQJEBAEBCgAuFiEEMgqfJ4U0fby1t860ojLKXoMTiAwFAmbwHxEQHGRzLWFjQG5h
bmVpbi5mcgAKCRCiMspegxOIDJ0LD/9J1qsU6TzAroRjZMrYHZB0RJ0UrthVqqtk
84ZMqX7hOUnZmpaxuMQGcuLHtgSJaR9oEjlKuG1mr9DlPkazPo0FLnYyAqwdnJb5
wJbahFcUuHdMtAG3FFJmUhriMVpXHnCRqCQP2KompuZZ2REjM7krTdloAXvKVtwC
8n1WD5JPdCWQ8RvlZ2oBeoYUk9KfG955020ygOdgckuSmQPhjLtUwElDUPYIMwfS
AvwTOkJ3TNDId0ERvzHu2hjZSOmVdWe/GyWv726n1krzsYFtJUvIO8SeBdwYvkYe
LpVnAiF14547nyonGqClHBjZgsXjbnwAzu5WBEmXpLth4wLUcLtUR9TaTMHsZZBh
vx5Q1AmgTTamM2kgMxfHMe2Of+jcM4dlCyFZCHsoGnHEdunokaVNe42xG90OB8lO
QWGvEpufABiyZGQFoTPrSVAjjxvkqvRd0+YiSem88o+5o3qV8pC005/Bpdq4I8HG
UPoXjgcmbqVI7gnofXuclUVNxwE7wyVuVvYjmEk3NkVHszGWV2GdPIcHYGM4MSHx
+wszNPizFBqxEVwxo96deNKlH0S97+VCvzvdHFXKEN7RKE+eToMauJlMvm4mFLlA
5J+JN7T2xvVXN5CuwIQWs7+JcDdYmXF7HAKuDVXCl1rIAp3funXDqRr8NhYSd2Jk
1qQROLWCVg==
=12ki
-----END PGP SIGNATURE-----

P
P
pelzflorian (Florian Pelz) wrote on 25 Sep 08:58 +0200
(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)
87v7ykrzhx.fsf@pelzflorian.de
Hello Arnaud.

Arnaud Daby-Seesaram <ds-ac@nanein.fr> writes:
Toggle quote (3 lines)
> I will probably define a new variable `%sway-default-packages'
> containing the above packages (minus waybar, ...). WDYT?

Yes, good idea.

Though some of these commands like dbus and xdg portals are unnecessary
because noone will run them manually from within sway.

Also note that the menu should default to wmenu instead of dmenu
according to swaywm.org release notes for current sway 1.9. Both are in
$(guix build sway)/etc/sway/config, but dmenu got used, but probably for
compatibility only.

wmenu should be the only menu.

Do we have an API stability guarantee that `%sway-default-packages' will
remain the same? I guess we better try not to remove packages from it
in the future but get it right from the start.


Toggle quote (5 lines)
> I will add a note in the next version of the doc, to hint towards the
> two solutions to use a svg file: adding librsvg to the profile, or
> computing the png and put it in the store using a "computed-file" in the
> configuration (as in the second version of the patch).

Do we need a computed-file example? Sway’s default background
$(guix build sway)/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png
is a .png file already. We need not use guix-backgrounds. Rationale:

In the computed-file version, note that librsvg needs rust and rust does
not build on i686-linux nor armhf. I tested in an i686-linux VM and the
rest of your home-sway-service-type works great there (using elogind and
manually running sway, because greetd would need rust). Using
imagemagick’s convert just gives a bogus pure black .png file.

I still have not found the time to look at `sway-bar' and `point' and
`sway-color' and such details.

Regards,
Florian
A
A
Arnaud Daby-Seesaram wrote on 25 Sep 09:52 +0200
(name . pelzflorian (Florian Pelz))(address . pelzflorian@pelzflorian.de)
87ikukqiez.fsf@nanein.fr
Hello Florian,

Toggle quote (6 lines)
> "pelzflorian (Florian Pelz)" <pelzflorian@pelzflorian.de> writes:
>> I’m still looking at the details of sway, so I could myself push your
>> patch with confidence to guix.git, but would also be happy if others
>> pushed it
> Nice, NB: it is also fine

I meant: it is also fine if you prefer to wait a few weeks for someone
else with commit access to comment/push this patch (as I do not want to
put pressure on you, and you said that you preferred not to take
responsibility for sway in a previous email).


"pelzflorian (Florian Pelz)" <pelzflorian@pelzflorian.de> writes:
Toggle quote (2 lines)
> I still have not found the time to look at `sway-bar' and `point' and
> `sway-color' and such details.
As I have changed these configuration records and the serialisation
function (hopefully making it easier to read and modify) in the v6, I
will send it today. I will not address your comments from today, but
should contain improvements over the previous code.


"pelzflorian (Florian Pelz)" <pelzflorian@pelzflorian.de> writes:
Toggle quote (9 lines)
> Arnaud Daby-Seesaram <ds-ac@nanein.fr> writes:
>> I will probably define a new variable `%sway-default-packages'
>> containing the above packages (minus waybar, ...). WDYT?
>
> Yes, good idea.
>
> Though some of these commands like dbus and xdg portals are unnecessary
> because noone will run them manually from within sway.

Yes, indeed. This week, I will test sway with only (list sway) and
(list sway swaybg) to see what works and what fails in each case. Then,
I will try to minimise the list of v5 (as users can always provide their
own lists if they want more packages to be available).

Toggle quote (7 lines)
> Also note that the menu should default to wmenu instead of dmenu
> according to swaywm.org release notes for current sway 1.9. Both are in
> $(guix build sway)/etc/sway/config, but dmenu got used, but probably for
> compatibility only.
>
> wmenu should be the only menu.

Noted. I used an outdated default sway configuration when defining
default variables, my bad.
This will not be modified in the v6 (as I send it right away), but
should be done later; I have added a comment in the code to remind me of
that.

Toggle quote (4 lines)
> Do we have an API stability guarantee that `%sway-default-packages' will
> remain the same? I guess we better try not to remove packages from it
> in the future but get it right from the start.

Indeed, this would be better. As mentioned above, I will try to
minimise this list and only keep packages that are necessary for using
sway. I will try to report on that within the week.


Toggle quote (7 lines)
>> I will add a note in the next version of the doc, to hint towards the
>> two solutions to use a svg file: adding librsvg to the profile, or
>> computing the png and put it in the store using a "computed-file" in the
>> configuration (as in the second version of the patch).
>
> Do we need a computed-file example? [...] Rationale: [...]

Thank you for this thorough testing and associated explanation.

I agree with you and have removed this example from the documentation
(only leaving the note that librsvg is needed in the profile in order to
use svg files).


Best,

--
Arnaud
-----BEGIN PGP SIGNATURE-----

iQJEBAEBCgAuFiEEMgqfJ4U0fby1t860ojLKXoMTiAwFAmbzwUQQHGRzLWFjQG5h
bmVpbi5mcgAKCRCiMspegxOIDDLmD/9mkq0SoHhaz91H7rJUI2DhkD0V0PGb+t1c
spAw8opIVr00DDbsy9Pyyuv9uzROBe0Iv1F2RfzoEnLSSy32WaepFnUSv4XtGY35
2NPAe+1h/03K+hQHNnxs+2Hye6CfhtVdNDim4WjCbUPkTqqVRhvvLqDVRo3NoPff
yzZJflp23yWtkd2jzzExV7faM/Y+im0CopZz2WXnHo5dAAUeZoYQ3m5EytbtRfOW
Jj6JgYxm/N0/O/DxyUqs4tru2GX2Ivn45t6dvDG57EQqXozWzXmCgEaSS+0PJtzd
ZbRbBYLkPw9qheO+R1/q2XnwwnS2It9hb+v8nwyV4nh1YrBctUOaSf+bdd+IYC9f
QlwtPdtsdef8NX34OCpGaWJr25NjtpEBBIH7dwvCqe7a7SD6AO6w2y5FR9CU6IBJ
PJGNEDbX+aYYGBJk55xfePcm2FN5GH7v/F4mPvQKWtBKtRhNZvVdz72MYr4iArYZ
ei/U4ibNROv8852Fr8m7QYhYR0DIFuIMWCHzlFP5drkpoRB9kTzdbmFSbWZsVDWM
A4VPysVv4WVneM5cqE4017KT9qD/48CApDVrMVYjMJXYNXxPV8nLfOWsk3lzY8sy
yf5YeppgLLnddCHASlGIKkNB7pbSDK+mkTR7y2A7at73eQ/bklWqldD0Eel5MNDr
jUii2FyvKA==
=ol8n
-----END PGP SIGNATURE-----

A
A
Arnaud Daby-Seesaram wrote on 25 Sep 10:00 +0200
[PATCH v6] home: services: Add 'home-sway-service-type'.
(address . 72714@debbugs.gnu.org)(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)
20240925080442.13752-1-ds-ac@nanein.fr
* gnu/home/services/sway.scm: New file.
(home-sway-service-type): New variable.
(sway-configuration->file): New procedure.
(sway-configuration): New configuration record.
(sway-bar): New configuration record.
(sway-output): New configuration record.
(sway-input): New configuration record.
(point): New configuration record.
(sway-color): New configuration record.
(sway-border-color): New configuration record.
(sway-mode): New configuration record.
(flatten): New procedure.
* gnu/local.mk: Add gnu/home/services/sway.scm.
* doc/guix.texi (Sway window manager): New node to document the above changes.
---
I only send this version of the patch to provide the latest version of
my code.

I have checked that a few produced configuration files were valid sway
files (with "sway -c"), but have not yet performed further testing on
this version.

Note: I have not proof-read the documentation; it might be a little
behind on the code or contain misspellings.

doc/guix.texi | 361 ++++++++++++++++++
gnu/home/services/sway.scm | 755 +++++++++++++++++++++++++++++++++++++
gnu/local.mk | 1 +
3 files changed, 1117 insertions(+)
create mode 100644 gnu/home/services/sway.scm

Toggle diff (550 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index 52e36e4354..dc7ab5884f 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -130,6 +130,7 @@ Copyright @copyright{} 2024 Richard Sent@*
Copyright @copyright{} 2024 Dariqq@*
Copyright @copyright{} 2024 Denis 'GNUtoo' Carikli@*
Copyright @copyright{} 2024 Fabio Natali@*
+Copyright @copyright{} 2024 Arnaud Daby-Seesaram@*
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -460,6 +461,7 @@ Home Services
* Mail: Mail Home Services. Services for managing mail.
* Messaging: Messaging Home Services. Services for managing messaging.
* Media: Media Home Services. Services for managing media.
+* Sway: Sway window manager. Setting up the Sway configuration.
* Networking: Networking Home Services. Networking services.
* Miscellaneous: Miscellaneous Home Services. More services.
@@ -45196,6 +45198,7 @@ services)}.
* Mail: Mail Home Services. Services for managing mail.
* Messaging: Messaging Home Services. Services for managing messaging.
* Media: Media Home Services. Services for managing media.
+* Sway: Sway window manager. Setting up the Sway configuration.
* Networking: Networking Home Services. Networking services.
* Miscellaneous: Miscellaneous Home Services. More services.
@end menu
@@ -47110,6 +47113,364 @@ kodi} for more information.
@end table
@end deftp
+@node Sway window manager
+@subsection Sway window manager
+
+@cindex sway, Home Service
+@cindex sway, configuration
+The @code{(gnu home services sway)} module provides
+@code{home-sway-service-type}, a home service to configure sway in a
+declarative way.
+
+@quotation Note
+This home service only sets up the configuration file and profile
+packages for sway. It does @i{not} start sway in any way. If you want
+to do so, you might be interested in using
+@code{greetd-wlgreet-sway-session} instead.
+
+The function @code{sway-configuration->file} defined below can be used
+to provide the value for the @emph{optional} @code{sway-configuration}
+field of @code{greetd-wlgreet-sway-session}.
+@end quotation
+
+@defvar sway-configuration->file
+This function takes a @code{sway-configuration} record (defined below),
+and returns a file-like object represented the serialized configuration.
+@end defvar
+
+@defvar home-sway-service-type
+This is a home service type to set up Sway. It takes care of:
+@itemize
+@item
+providing a @file{~/.config/sway/config} file,
+@item
+adding sway-related packages to your profile.
+@end itemize
+
+Here is an example of a service and its configuration that you could add
+to the @code{services} field of your @code{home-environment}:
+
+@lisp
+(service home-sway-service-type
+ (sway-configuration
+ (gestures
+ '((swipe:3:down . "move to scratchpad")
+ (swipe:3:up . "scratchpad show")))
+ (outputs
+ (list (sway-output
+ (identifier '*)
+ (bg (file-append sway
+ "\
+/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png")))))))
+@end lisp
+
+The above example describes a sway configuration in which
+@itemize
+@item
+all monitors use a particular wallpaper whose @file{.png} is provided by
+the @code{sway} package;
+@item
+swiping down (resp.@: up) with three fingers moves the active window to
+the scratchpad (resp.@: shows/hides the scratchpad).
+@end itemize
+@end defvar
+
+@deftp {Data Type} sway-configuration
+This configuration record describes the sway configuration
+(see@ @cite{sway(5)}). Available fields are:
+
+@table @asis
+@item @code{variables} (default: @code{%sway-default-variables})
+The value of this field is an association list in which keys are symbols
+and values are strings or G-expressions (@pxref{G-Expressions}).
+
+Example: @code{'(mod . "Mod4")}.
+
+@item @code{keybindings} (default: @code{%sway-default-keybindings})
+This field describes keybindings for the @emph{default} mode. As above,
+the value is an association list: keys are symbols and values are either
+strings, G-expressions or file-append objects.
+
+Examples using:
+@itemize
+@item
+a string: @code{'($mod+Return . "exec $term")}
+@item
+a G-exp: @code{`($mod+t . ,#~(string-append #$st "/bin/st"))}
+@item
+a file-append: @code{`($mod+t . ,(file-append st "/bin/st"))}
+@end itemize
+
+@item @code{gestures} (default: @code{%sway-default-gestures})
+Similar to the previous field, but for finger-gestures.
+
+The following snippet allows to navigate through workspaces by swiping
+right and left with three fingers:
+@lisp
+'((swipe:3:right . "workspace next_on_output")
+ (swipe:3:left . "workspace prev_on_output"))
+@end lisp
+
+@item @code{packages} (default: @code{%sway-default-packages})
+This field describes a list of packages to add to the user profile.
+
+@item @code{inputs} (default: @code{'()})
+List of @code{sway-input} configuration records.
+
+@item @code{outputs} (default: @code{'()})
+List of @code{sway-output} configuration records.
+
+@item @code{bar} (optional)
+Optional @code{sway-bar} configuration record to declare the sway-bar
+configuration.
+
+@item @code{modes} (default: @code{'()})
+Optional list of @code{sway-mode} records (described below).
+
+@item @code{always-execs} (default: @code{'()})
+Programs to execute at startup time @i{and} after every configuration
+reload. The value of this field is a list of strings or G-expressions.
+
+@item @code{execs} (default: @code{%sway-default-execs})
+Programs to execute at startup time. The value of this field is a list
+of strings or G-expressions.
+
+The default value, @code{%sway-default-execs}, executes @code{swayidle}
+in order to lock the screen after 5@ minutes of inactivity (displaying a
+background distributed with Sway) and turn of the screen after
+10@ minutes of inactivity.
+
+@item @code{extra-content} (default: @code{'()})
+Lines to add to the configuration file. The value of this field is a
+list of strings or G-expressions.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-input
+@code{sway-input} records describe input blocks (see@
+@cite{sway-input(5)}). For example, the following snippet makes all
+keyboards use a french layout, in which @kbd{capslock} has been remaped
+to @kbd{ctrl}:
+@lisp
+(sway-input (identifier "type:keyboard")
+ (xkb-layout "fr")
+ (xkb-options '("ctrl:nocaps")))
+@end lisp
+
+Available fields for @code{sway-input} configuration records are:
+
+@table @asis
+@item @code{identifier} (default: @code{'*})
+Identifier of the input. The field accepts symbols and strings. If a
+string is used, it will be quoted in the generated configuration file.
+
+@item @code{xkb-layout} (optional)
+Keyboard specific option. String providing a comma-separated keyboard
+layout(s) to use.
+
+@item @code{xkb-model} (optional)
+Keyboard specific option. String providing the keyboard model.
+
+@item @code{xkb-options} (optional)
+Keyboard specific option. List of strings specifying additional xkb
+options for the keyboard.
+
+@item @code{xkb-variant} (optional)
+Keyboard specific option. String specifying the variant of the layout.
+
+@item @code{extra-content} (default: @code{'()})
+Lines to add to the input block. The value of this field is a list of
+strings.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-output
+@code{sway-output} records describe sway outputs
+(see@ @cite{sway-output(5)}). Available fields are:
+
+@table @asis
+@item @code{identifier} (default: @code{'*})
+Identifier of the monitor. If the
+@code{identifier} is a symbol, it is inserted as is; if it is a string,
+it will be quoted in the configuration file.
+
+@item @code{resolution} (optional)
+This string defines the resolution of the monitor.
+
+@item @code{position} (optional)
+The (optional) value of this field must be a @code{point}.
+Example:
+@lisp
+(position
+ (point (x 1920)
+ (y 0)))
+@end lisp
+
+@item @code{bg} (optional)
+This field accepts a file-like value representing the wallpaper to use
+on this monitor. It will be used with the @code{fill} option.
+
+@quotation Note
+If you have @code{librsvg} in your profile, it is possible to specify
+the path to an SVG file.
+@end quotation
+
+@item @code{extra-content} (default: @code{'()})
+List defining additional lines to add to the output configuration block.
+Elements of the list must be either strings or G-expressions.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-border-color
+
+@table @code
+@item border
+Color of the border.
+@item background
+Color of the background.
+@item text
+Color of the text.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-color
+@table @asis
+@item @code{background} (optional string)
+Background color of the bar.
+
+@item @code{statusline} (optional string)
+Text color of the status line.
+
+@item @code{focused-background} (optional string)
+Background color of the bar on the currently focused monitor.
+
+@item @code{focused-statusline} (optional string)
+Text color of the statusline on the currently focused monitor.
+
+@item @code{focused-workspace} (optional @code{sway-border-color})
+Color scheme for focused workspaces.
+
+@item @code{active-workspace} (optional @code{sway-border-color})
+Colour scheme for active workspaces.
+
+@item @code{inactive-workspace} (optional @code{sway-border-color})
+Colour scheme for inactive workspaces.
+
+@item @code{urgent-workspace} (optional @code{sway-border-color})
+Colour scheme for workspaces containing ``urgent'' windows.
+
+@item @code{binding-mode} (optional @code{sway-border-color})
+Colour scheme for the binding mode indicator.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-bar
+Describes the Sway bar (see@ @cite{sway-bar(5)}).
+
+@table @asis
+@item @code{identifier} (default: @code{'bar0})
+Identifier of the bar. The value must be a symbol.
+
+@item @code{position} (optional)
+Specify the position of the bar. Accepted values are @code{'top} or
+@code{'bottom}.
+
+@item @code{hidden-state} (optional)
+Specify the apparence of the bar when it is hidden. Accepted values are
+@code{'hide} or @code{show}.
+
+@item @code{binding-mode-indicator} (optional)
+Boolean enabling or disabling the binding mode indicator.
+
+@item @code{colors} (optional)
+An optional @code{sway-color} configuration record.
+
+@item @code{status-command} (default: @code{%sway-status-command})
+This field accept strings, G-expressions and executable file-like
+values. The default value is a command (string) that prints the date
+and time every second.
+
+Each line printed on @code{stdout} by this command (or script) will be
+displayed on the status area of the bar.
+
+Below are a few examples using:
+@itemize
+@item
+a string: @code{"while date +'%Y-%m-%d %X'; do sleep 1; done"},
+@item
+a G-exp:
+@lisp
+#~(string-append "while "
+ #$coreutils "/bin/date"
+ " +'%Y-%m-%d %X'; do sleep 1; done")
+@end lisp
+@item
+an executable file:
+@lisp
+(program-file
+ "sway-bar-status"
+ (with-imported-modules
+ (source-module-closure
+ '((ice-9 format) (srfi srfi-19)))
+ #~(begin
+ (use-modules (ice-9 format)
+ (srfi srfi-19))
+ (let loop ()
+ (let* ((date (date->string
+ (current-date)
+ "~d/~m/~Y (~a) ~H:~M:~S")))
+ (format #t "~a~%~!" date)
+ (sleep 1)
+ (loop))))))
+@end lisp
+@end itemize
+
+@item @code{mouse-bindings} (default: @code{'()})
+This field accepts an associative list. Keys are integers describing
+mouse events. Values can be either strings, G-expressions or
+file-append objects.
+
+The module @code{(gnu home services sway)} exports constants
+@code{%ev-code-mouse-left}, @code{%ev-code-mouse-right} and
+@code{%ev-code-mouse-scroll-click} whose values are integers
+corresponding to left, right and scroll click respectively. For
+example, with the @code{`((,%ev-code-mouse-left . ,(file-append st
+"/bin/st")))}, left clicks in the status bar open the @code{st}
+terminal.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-mode
+Describes a Sway mode. For example, the following snippet defines a
+mockup of the resize mode of the default Sway configuration:
+@example
+(sway-mode
+ (mode-name "resize")
+ (keybindings
+ '(($left . "resize shrink width 10px")
+ ($right . "resize grow width 10px")
+ ($down . "resize grow height 10px")
+ ($up . "resize shrink height 10px")
+ (Return . "mode \"default\"")
+ (Escape . "mode \"default\""))))
+@end example
+
+@table @asis
+@item @code{mode-name} (default: @code{"default"})
+Name of the mode. This field accepts strings.
+
+@item @code{keybindings} (default: @code{'()})
+This field describes keybindings. The value is an association list:
+keys are symbols and values are either strings or G-expressions, as
+above.
+
+@item @code{mouse-bindings} (default: @code{'()})
+Ditto, but keys are mouse events (integers). Constants
+@code{%ev-code-mouse-*} described above can be used as helpers to define
+mouse bindings.
+@end table
+@end deftp
+
@node Networking Home Services
@subsection Networking Home Services
diff --git a/gnu/home/services/sway.scm b/gnu/home/services/sway.scm
new file mode 100644
index 0000000000..6e55fda5fc
--- /dev/null
+++ b/gnu/home/services/sway.scm
@@ -0,0 +1,755 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2024 Arnaud Daby-Seesaram <ds-ac@nanein.fr>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix 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 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix 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 GNU Guix. If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu home services sway)
+ #:use-module (guix modules)
+ #:use-module (guix gexp)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-26)
+ #:use-module (ice-9 popen)
+ #:use-module (ice-9 format)
+ #:use-module (ice-9 match)
+ #:use-module (guix packages)
+ #:use-module (gnu services configuration)
+ #:use-module (gnu home services)
+ #:use-module (gnu packages freedesktop)
+ #:use-module (gnu packages xdisorg)
+ #:use-module (gnu packages image)
+ #:use-module (gnu packages gnome)
+ #:use-module (gnu packages wm)
+ #:use-module (gnu packages emacs)
+ #:use-module (gnu packages linux)
+ #:use-module (gnu packages base)
+ #:use-module (gnu packages suckless)
+ #:use-module (gnu packages glib)
+ #:export (;; Event codes
+ %ev-code-mouse-left
+ %ev-code-mouse-right
+ %ev-code-mouse-scroll-click
+
+ ;; Configuration records.
+ sway-configuration
+ sway-bar
+ sway-output
+ sway-input
+ point
+ sway-color
+ sway-border-color
+ home-sway-service-type
+ sway-configuration->file
+ sway-mode
+
+ ;; Default values.
+ %sway-default-variables
+ %sway-default-gestures
+ %sway-default-keybindings
+ %sway-default-status-command
+ %sway-default-execs
+ %sway-default-packages))
+
+;; Helper function.
+(define (flatten l)
+ (let loop ((lst (reverse l)) (acc '()))
+ (match lst
+ (() acc)
+ ((head . tail)
+ (loop tail (append head acc))))))
+
+
+;;;
+;;; Default settings and useful constants.
+;;;
+
+(define %ev-code-mouse-left 272)
+(define %ev-code-mouse-right 273)
+(define %ev-code-mouse-scroll-click 274)
+
+;; TODO: reduce this list to a minimal, and make sure that sway behaves well.
+(define %sway-default-packages
+ (list sway swaybg))
+
+;; TODO: Update default values to match current default configuration files of
+;; sway.
+(define %sway-default-variables
+ `((mod . "Mod4")
+ (left . "h")
+ (down . "j")
+ (up . "k")
+ (right . "l")
+ (term . ,(file-append st "/bin/st"))
+ (menu . ,#~(string-append
+ #$dmenu "/bin/dmenu_path | "
+ #$wmenu "/bin/wmenu | "
+ #$findutils "/bin/xargs "
+ #$sway "/bin/swaymsg exec --"))))
+
+(define %sway-default-gestures
+ '((swipe:3:right . "workspace next_on_output")
+ (swipe:3:left . "workspace prev_on_output")
+ (swipe:3:down . "move to scratchpad")
+ (swipe:3:up . "scratchpad show")))
+
+(define %sway-default-keybindings
+ `(($mod+Return . "exec $term")
+ ($mod+Shift+q . "kill")
+ ($mod+d . "exec $menu")
+ ($mod+Shift+c . "reload")
+ ($mod+Shift+e
+ . ,#~(string-append
+ "exec " #$sway "/bin/swaynag -t warning -m 'You pressed the exit "
+ "shortcut. Do you really want to exit sway? This will end your "
+ "Wayland session.' -B 'Yes, exit sway' '"
+ #$sway "/bin/swaymsg exit'"))
+ ($mod+$left . "focus left")
+ ($mod+$down . "focus down")
+ ($mod+$up . "focus up")
+ ($mod+$right . "focus right")
+ ($mod+Left . "focus left")
+ ($mod+Down . "focus down")
+ ($mod+Up . "focus up")
+ ($mod+Right . "focus right")
+ ($mod+Shift+$left . "move left")
+ ($mod+Shift+$down . "move down")
+ ($mod+Shift+$up . "move up")
+ ($mod+Shift+$right . "move right")
+ ($mod+Shift+Left . "move left")
+ ($mod+Shift+Down . "move down")
+ ($mod+Shift+Up . "move up")
+ ($mod+Shift+Right . "move right")
+ ($mod+1 . "workspace number 1")
+ ($mod+2 . "workspace number 2")
+ ($mod+3 . "workspace number 3")
+ ($mod+4 . "workspace number 4")
+ ($mod+5 . "workspace number 5")
+ ($mod+6 . "workspace number 6")
+ ($mod+7 . "workspace number 7")
+ ($mod+8 . "workspace number 8")
+ ($mod+9 . "workspace number 9")
+ ($mod+0 . "workspace number 10")
+ ($mod+Shift+1 . "move container to workspace number 1")
+ ($mod+Shift+2 . "move container to workspace number 2")
+ ($mod+Shift+3 . "move container to workspace number 3")
+ ($mod+Shift+4 . "move container to workspace number 4")
+ ($mod+Shift+5 . "move container to workspace number 5")
+ ($mod+Shift+6 . "move container to workspace number 6")
+ ($mod+Shift+7 . "move container to workspace number 7")
+ ($mod+Shift+8 . "move container to workspace number
This message was truncated. Download the full message here.
P
P
pelzflorian (Florian Pelz) wrote on 25 Sep 13:42 +0200
Re: [bug#72714] [PATCH v4] home: services: Add 'home-sway-service-type'.
(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)
87wmj0q7rh.fsf@pelzflorian.de
Arnaud Daby-Seesaram <ds-ac@nanein.fr> writes:
Toggle quote (13 lines)
> Hello Florian,
>
>> "pelzflorian (Florian Pelz)" <pelzflorian@pelzflorian.de> writes:
>>> I’m still looking at the details of sway, so I could myself push your
>>> patch with confidence to guix.git, but would also be happy if others
>>> pushed it
>> Nice, NB: it is also fine
>
> I meant: it is also fine if you prefer to wait a few weeks for someone
> else with commit access to comment/push this patch (as I do not want to
> put pressure on you, and you said that you preferred not to take
> responsibility for sway in a previous email).

Thank you. There’s no pressure on me, but I will be slow in my
investigation and responses.

"pelzflorian (Florian Pelz)" <pelzflorian@pelzflorian.de> writes:
Toggle quote (7 lines)
> Also note that the menu should default to wmenu instead of dmenu
> according to swaywm.org release notes for current sway 1.9. Both are in
> $(guix build sway)/etc/sway/config, but dmenu got used, but probably for
> compatibility only.
>
> wmenu should be the only menu.

Sorry, I had not tested this yet. Even though web searches point to
some obscure program called wmenu_path that must exist somewhere, it
seems your use of dmenu_path is what upstream uses. I do not really
understand this.

Regards,
Florian
L
L
Ludovic Courtès wrote on 30 Sep 22:07 +0200
Re: [bug#72714] [PATCH v6] home: services: Add 'home-sway-service-type'.
(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)
87zfno52ig.fsf@gnu.org
Hi Arnaud,

Arnaud Daby-Seesaram <ds-ac@nanein.fr> skribis:

Toggle quote (15 lines)
> * gnu/home/services/sway.scm: New file.
> (home-sway-service-type): New variable.
> (sway-configuration->file): New procedure.
> (sway-configuration): New configuration record.
> (sway-bar): New configuration record.
> (sway-output): New configuration record.
> (sway-input): New configuration record.
> (point): New configuration record.
> (sway-color): New configuration record.
> (sway-border-color): New configuration record.
> (sway-mode): New configuration record.
> (flatten): New procedure.
> * gnu/local.mk: Add gnu/home/services/sway.scm.
> * doc/guix.texi (Sway window manager): New node to document the above changes.

I don’t use Sway myself but it looks like a welcome addition.

I trust Hilton’s comment here so here are some more superficial
comments.

Toggle quote (4 lines)
> +The @code{(gnu home services sway)} module provides
> +@code{home-sway-service-type}, a home service to configure sway in a
> +declarative way.

To add more context:

“… to configure the @uref{https://github.com/swaywm/sway,Swaywindow
manager for Wayland} in a declarative way.”

Toggle quote (4 lines)
> +@quotation Note
> +This home service only sets up the configuration file and profile
> +packages for sway. It does @i{not} start sway in any way. If you want

s/sway/Sway/
s/@i/@emph/

Toggle quote (2 lines)
> +@defvar sway-configuration->file

Should be “@deffn {Procedure} sway-configuration->file config”.

Toggle quote (3 lines)
> +Here is an example of a service and its configuration that you could add
> +to the @code{services} field of your @code{home-environment}:

I would move the example right before “@quotation Note”.

Toggle quote (8 lines)
> +@item @code{always-execs} (default: @code{'()})
> +Programs to execute at startup time @i{and} after every configuration
> +reload. The value of this field is a list of strings or G-expressions.
> +
> +@item @code{execs} (default: @code{%sway-default-execs})
> +Programs to execute at startup time. The value of this field is a list
> +of strings or G-expressions.

Please avoid abbreviations. Maybe these fields could be called
‘startup+reload-programs’ and ‘startup-programs’?

Toggle quote (2 lines)
> +The default value, @code{%sway-default-execs}, executes @code{swayidle}

Likewise, @code{%sway-default-startup-programs}?

Toggle quote (11 lines)
> +@deftp {Data Type} sway-input
> +@code{sway-input} records describe input blocks (see@
> +@cite{sway-input(5)}). For example, the following snippet makes all
> +keyboards use a french layout, in which @kbd{capslock} has been remaped
> +to @kbd{ctrl}:
> +@lisp
> +(sway-input (identifier "type:keyboard")
> + (xkb-layout "fr")
> + (xkb-options '("ctrl:nocaps")))
> +@end lisp

Would it be possible here to reuse the <keyboard-layout> record
documented in

If it’s possible, that would provide a nicely consistent interface. If
there’s the need for an extra identifier, maybe you’ll still need
<sway-input>:

(sway-input (identifier "type:keyboard")
(layout (keyboard-layout "tr")))

WDYT?

Toggle quote (7 lines)
> +@lisp
> +(program-file
> + "sway-bar-status"
> + (with-imported-modules
> + (source-module-closure
> + '((ice-9 format) (srfi srfi-19)))

‘with-imported-modules’ can be removed here because (ice-9 format) and
(srfi srfi-19) are provided by Guile itself.

That’s it for me!

Could you send updated patches?

Thank you!

Ludo’.
A
A
Arnaud Daby-Seesaram wrote on 2 Oct 00:12 +0200
[PATCH] home: services: Add 'home-sway-service-type'.
(address . 72714@debbugs.gnu.org)
20241001221313.2490-1-ds-ac@nanein.fr
* gnu/home/services/sway.scm: New file.
(home-sway-service-type): New variable.
(sway-configuration->file): New procedure.
(sway-configuration): New configuration record.
(sway-bar): New configuration record.
(sway-output): New configuration record.
(sway-input): New configuration record.
(point): New configuration record.
(sway-color): New configuration record.
(sway-border-color): New configuration record.
(sway-mode): New configuration record.
(flatten): New procedure.
* gnu/local.mk: Add gnu/home/services/sway.scm.
* doc/guix.texi (Sway window manager): New node to document the above changes.
---
Hi all,

This version takes into account previous reviews (hoping that I did not
forget/break something). The modifications are mainly:

• fix a typo in the code: in the v6, execs was serialised in place of
always-execs,
• following your advice, I renamed abbreviations:
- bg → background
- execs → startup-programs
- always-execs → startup+reload-programs

• keyboard layouts are now specified with <keyboard-layout> records in
sway-input, as suggested. I have added a cross-reference to the
relevant section in the manual.
Note: (gnu home services sway) does not re-export keyboard-layout.
• the background field of sway-output now accepts pairs too, in order to
describe how the background should be displayed (fill the screen, at
the center of the screen, etc.)

• the list of default packages is simply (list sway)

• (flatten (map _ _)) with a homemade flatten is replaced by (flatmap _
_) with a homemade flatmap.

• the default terminal is now set to foot (as in the default config on
the sway 1.9)

• extra-content no longer allows file-append objects (which did not make
sense)

• new fields in sway-input

Best regards,

doc/guix.texi | 394 ++++++++++++++++++
gnu/home/services/sway.scm | 794 +++++++++++++++++++++++++++++++++++++
gnu/local.mk | 1 +
3 files changed, 1189 insertions(+)
create mode 100644 gnu/home/services/sway.scm

Toggle diff (528 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index 52e36e4354..f5911a19c6 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -130,6 +130,7 @@ Copyright @copyright{} 2024 Richard Sent@*
Copyright @copyright{} 2024 Dariqq@*
Copyright @copyright{} 2024 Denis 'GNUtoo' Carikli@*
Copyright @copyright{} 2024 Fabio Natali@*
+Copyright @copyright{} 2024 Arnaud Daby-Seesaram@*
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -460,6 +461,7 @@ Home Services
* Mail: Mail Home Services. Services for managing mail.
* Messaging: Messaging Home Services. Services for managing messaging.
* Media: Media Home Services. Services for managing media.
+* Sway: Sway window manager. Setting up the Sway configuration.
* Networking: Networking Home Services. Networking services.
* Miscellaneous: Miscellaneous Home Services. More services.
@@ -45196,6 +45198,7 @@ services)}.
* Mail: Mail Home Services. Services for managing mail.
* Messaging: Messaging Home Services. Services for managing messaging.
* Media: Media Home Services. Services for managing media.
+* Sway: Sway window manager. Setting up the Sway configuration.
* Networking: Networking Home Services. Networking services.
* Miscellaneous: Miscellaneous Home Services. More services.
@end menu
@@ -47110,6 +47113,397 @@ kodi} for more information.
@end table
@end deftp
+@node Sway window manager
+@subsection Sway window manager
+
+@cindex sway, Home Service
+@cindex sway, configuration
+The @code{(gnu home services sway)} module provides
+@code{home-sway-service-type}, a home service to configure the
+@uref{https://github.com/swaywm/sway,Sway window manager for Wayland} in
+a declarative way.
+
+Here is an example of a service and its configuration that you could add
+to the @code{services} field of your @code{home-environment}:
+
+@lisp
+(service home-sway-service-type
+ (sway-configuration
+ (gestures
+ '((swipe:3:down . "move to scratchpad")
+ (swipe:3:up . "scratchpad show")))
+ (outputs
+ (list (sway-output
+ (identifier '*)
+ (bg (file-append sway
+ "\
+/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png")))))))
+@end lisp
+
+The above example describes a Sway configuration in which
+@itemize
+@item
+all monitors use a particular wallpaper whose @file{.png} is provided by
+the @code{sway} package;
+@item
+swiping down (resp.@: up) with three fingers moves the active window to
+the scratchpad (resp.@: shows/hides the scratchpad).
+@end itemize
+
+@quotation Note
+This home service only sets up the configuration file and profile
+packages for Sway. It does @emph{not} start Sway in any way. If you
+want to do so, you might be interested in using
+@code{greetd-wlgreet-sway-session} instead.
+
+The function @code{sway-configuration->file} defined below can be used
+to provide the value for the @emph{optional} @code{sway-configuration}
+field of @code{greetd-wlgreet-sway-session}.
+@end quotation
+
+@deffn {Procedure} sway-configuration->file config
+This function takes a @code{sway-configuration} record (defined below),
+and returns a file-like object representing the serialized
+configuration.
+@end deffn
+
+@defvar home-sway-service-type
+This is a home service type to set up Sway. It takes care of:
+@itemize
+@item
+providing a @file{~/.config/sway/config} file,
+@item
+adding Sway-related packages to your profile.
+@end itemize
+@end defvar
+
+@deftp {Data Type} sway-configuration
+This configuration record describes the Sway configuration
+(see@ @cite{sway(5)}). Available fields are:
+
+@table @asis
+@item @code{variables} (default: @code{%sway-default-variables})
+The value of this field is an association list in which keys are symbols
+and values are either strings, G-expressions or file-append objects
+(@pxref{G-Expressions}).
+
+Example:
+@lisp
+(variables `((mod . "Mod4") ; string
+ (term ; file-append
+ . ,(file-append foot "/bin/foot"))
+ (term ; G-expression
+ . ,#~(string-append #$foot "/bin/foot"))))
+@end lisp
+
+@item @code{keybindings} (default: @code{%sway-default-keybindings})
+This field describes keybindings for the @emph{default} mode. The value
+is an association list: keys are symbols and values are either strings
+or G-expressions.
+
+The following snippet launches the terminal when pressing @kbd{$mod+t}
+and @kbd{$mod+Shift+t} (assuming that a variable @code{$term} is
+defined):
+@lisp
+`(($mod+t . ,#~(string-append "exec " #$foot "/bin/foot"))
+ ($mod+Shift+t . "exec $term"))
+@end lisp
+
+@item @code{gestures} (default: @code{%sway-default-gestures})
+Similar to the previous field, but for finger-gestures.
+
+The following snippet allows to navigate through workspaces by swiping
+right and left with three fingers:
+@lisp
+'((swipe:3:right . "workspace next_on_output")
+ (swipe:3:left . "workspace prev_on_output"))
+@end lisp
+
+@item @code{packages} (default: @code{%sway-default-packages})
+This field describes a list of packages to add to the user profile. At
+the moment, the default value only adds @code{sway} to the profile.
+
+@item @code{inputs} (default: @code{'()})
+List of @code{sway-input} configuration records (described below).
+
+@item @code{outputs} (default: @code{'()})
+List of @code{sway-output} configuration records (described below).
+
+@item @code{bar} (optional @code{sway-bar} record)
+Optional @code{sway-bar} record (described below) to configure a Sway
+bar.
+
+@item @code{modes} (default: @code{'()})
+Optional list of @code{sway-mode} records (described below) to add modes
+to the Sway configuration (@i{e.g.}@: the ``resize'' mode of the default
+Sway configuration).
+
+@item @code{startup+reload-programs} (default: @code{'()})
+Programs to execute at startup time @emph{and} after every configuration
+reload. The value of this field is a list of strings, G-expressions or
+file-append objects (@pxref{G-Expressions}).
+
+@item @code{startup-programs} (default: @code{%sway-default-execs})
+Programs to execute at startup time. As above, values of this field are
+a list of strings, G-expressions or file-append objects.
+
+The default value, @code{%sway-default-execs}, executes @code{swayidle}
+in order to lock the screen after 5@ minutes of inactivity (displaying a
+background distributed with Sway) and turn the screen off after 10@
+minutes of inactivity.
+
+@item @code{extra-content} (default: @code{'()})
+Lines to add to the configuration file. The value of this field is a
+list of strings or G-expressions.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-input
+@code{sway-input} records describe input blocks (see@
+@cite{sway-input(5)}). For example, the following snippet makes all
+keyboards use a french layout, in which @kbd{capslock} has been remaped
+to @kbd{ctrl}:
+@lisp
+(sway-input (identifier "type:keyboard")
+ (layout
+ (keyboard-layout "fr" #:options '("ctrl:nocaps"))))
+@end lisp
+
+Available fields for @code{sway-input} configuration records are:
+
+@table @asis
+@item @code{identifier} (default: @code{'*})
+Identifier of the input. The field accepts symbols and strings. If the
+@code{identifier} is a symbol, it is inserted as is; if it is a string,
+it will be quoted in the configuration file.
+
+
+@item @code{layout} (optional @code{<keyboard-layout>} record)
+Keyboard specific option. Field specifying the layout (possibly with
+options) to use for the input. The value must be a
+@code{<keyboard-layout>} record (@pxref{Keyboard Layout}).
+
+@quotation Note
+@code{(gnu home services sway)} does not re-export the
+@code{keyboard-layout} procedure.
+@end quotation
+
+
+@item @code{disable-while-typing} (optional boolean)
+If @code{#t} (resp.@: @code{#f}) enables (resp.@: disables) the
+``disable while typing'' option for this input.
+
+@item @code{disable-while-trackpointing} (optional boolean)
+If @code{#t} (resp.@: @code{#f}), enables (resp.@: disables) the
+``disable while track-pointing'' option for this input.
+
+@item @code{tap} (optional boolean)
+Enables or disables the ``tap'' option, which allows clicking by tapping
+on a touchpad.
+
+@item @code{extra-content} (default: @code{'()})
+Lines to add to the input block. The value of this field is a list
+whose elements can be either strings or G-expressions.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-output
+@code{sway-output} records describe Sway outputs
+(see@ @cite{sway-output(5)}). Available fields are:
+
+@table @asis
+@item @code{identifier} (default: @code{'*})
+Identifier of the monitor. The field accepts symbols and strings. If
+the @code{identifier} is a symbol, it is inserted as is; if it is a
+string, it will be quoted in the configuration file.
+
+@item @code{resolution} (optional string)
+This string defines the resolution of the monitor.
+
+@item @code{position} (optional)
+The (optional) value of this field must be a @code{point}.
+Example:
+@lisp
+(position
+ (point (x 1920)
+ (y 0)))
+@end lisp
+
+@item @code{background} (optional)
+The value of this field describes what wallpaper to use on this output.
+The field accepts the following types of values:
+@itemize
+@item
+a string,
+@item
+a G-expression,
+@item
+a file-append object,
+@item
+a pair. The first argument of this pair must be a string, a
+G-expression or a file-append object. The second element of the pair
+must be a symbol among @code{stretch}, @code{fill}, @code{fit},
+@code{center} and @code{tile}.
+@end itemize
+
+@quotation Note
+In order to use an SVG file, you must have @code{librsvg} in your
+profile (@i{e.g.}@: by adding it in the @code{packages} field of @code{sway-configuration}).
+@end quotation
+
+@item @code{extra-content} (default: @code{'()})
+List defining additional lines to add to the output configuration block.
+Elements of the list must be either strings or G-expressions.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-border-color
+
+@table @code
+@item border
+Color of the border.
+@item background
+Color of the background.
+@item text
+Color of the text.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-color
+@table @asis
+@item @code{background} (optional string)
+Background color of the bar.
+
+@item @code{statusline} (optional string)
+Text color of the status line.
+
+@item @code{focused-background} (optional string)
+Background color of the bar on the currently focused monitor.
+
+@item @code{focused-statusline} (optional string)
+Text color of the statusline on the currently focused monitor.
+
+@item @code{focused-workspace} (optional @code{sway-border-color})
+Color scheme for focused workspaces.
+
+@item @code{active-workspace} (optional @code{sway-border-color})
+Color scheme for active workspaces.
+
+@item @code{inactive-workspace} (optional @code{sway-border-color})
+Color scheme for inactive workspaces.
+
+@item @code{urgent-workspace} (optional @code{sway-border-color})
+Color scheme for workspaces containing ``urgent'' windows.
+
+@item @code{binding-mode} (optional @code{sway-border-color})
+Color scheme for the binding mode indicator.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-bar
+Describes the Sway bar (see@ @cite{sway-bar(5)}).
+
+@table @asis
+@item @code{identifier} (default: @code{'bar0})
+Identifier of the bar. The value must be a symbol.
+
+@item @code{position} (optional)
+Specify the position of the bar. Accepted values are @code{'top} or
+@code{'bottom}.
+
+@item @code{hidden-state} (optional)
+Specify the apparence of the bar when it is hidden. Accepted values are
+@code{'hide} or @code{'show}.
+
+@item @code{binding-mode-indicator} (optional)
+Boolean enabling or disabling the binding mode indicator.
+
+@item @code{colors} (optional)
+An optional @code{sway-color} configuration record.
+
+@item @code{status-command} (default: @code{%sway-status-command})
+This field accept strings, G-expressions and executable file-like
+values. The default value is a command (string) that prints the date
+and time every second.
+
+Each line printed on @code{stdout} by this command (or script) will be
+displayed on the status area of the bar.
+
+Below are a few examples using:
+@itemize
+@item
+a string: @code{"while date +'%Y-%m-%d %X'; do sleep 1; done"},
+@item
+a G-exp:
+@lisp
+#~(string-append "while "
+ #$coreutils "/bin/date"
+ " +'%Y-%m-%d %X'; do sleep 1; done")
+@end lisp
+@item
+an executable file:
+@lisp
+(program-file
+ "sway-bar-status"
+ #~(begin
+ (use-modules (ice-9 format)
+ (srfi srfi-19))
+ (let loop ()
+ (let* ((date (date->string
+ (current-date)
+ "~d/~m/~Y (~a) ~H:~M:~S")))
+ (format #t "~a~%~!" date)
+ (sleep 1)
+ (loop)))))
+@end lisp
+@end itemize
+
+@item @code{mouse-bindings} (default: @code{'()})
+This field accepts an associative list. Keys are integers describing
+mouse events. Values can either be strings or G-expressions.
+
+The module @code{(gnu home services sway)} exports constants
+@code{%ev-code-mouse-left}, @code{%ev-code-mouse-right} and
+@code{%ev-code-mouse-scroll-click} whose values are integers
+corresponding to left, right and scroll click respectively. For
+example, with @code{(mouse-bindings `((,%ev-code-mouse-left
+. ,#~(string-append "exec " #$st "/bin/st"))))}, left clicks in the
+status bar open the @code{st} terminal.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-mode
+Describes a Sway mode (see@ @cite{sway(5)}). For example, the following
+snippet defines a mockup of the resize mode of the default Sway
+configuration:
+@example
+(sway-mode
+ (mode-name "resize")
+ (keybindings
+ '(($left . "resize shrink width 10px")
+ ($right . "resize grow width 10px")
+ ($down . "resize grow height 10px")
+ ($up . "resize shrink height 10px")
+ (Return . "mode \"default\"")
+ (Escape . "mode \"default\""))))
+@end example
+
+@table @asis
+@item @code{mode-name} (default: @code{"default"})
+Name of the mode. This field accepts strings.
+
+@item @code{keybindings} (default: @code{'()})
+This field describes keybindings. The value is an association list:
+keys are symbols and values are either strings or G-expressions, as
+above.
+
+@item @code{mouse-bindings} (default: @code{'()})
+Ditto, but keys are mouse events (integers). Constants
+@code{%ev-code-mouse-*} described above can be used as helpers to define
+mouse bindings.
+@end table
+@end deftp
+
@node Networking Home Services
@subsection Networking Home Services
diff --git a/gnu/home/services/sway.scm b/gnu/home/services/sway.scm
new file mode 100644
index 0000000000..25cae56dae
--- /dev/null
+++ b/gnu/home/services/sway.scm
@@ -0,0 +1,794 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2024 Arnaud Daby-Seesaram <ds-ac@nanein.fr>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix 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 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix 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 GNU Guix. If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu home services sway)
+ #:use-module (guix modules)
+ #:use-module (guix gexp)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-26)
+ #:use-module (ice-9 popen)
+ #:use-module (ice-9 format)
+ #:use-module (ice-9 match)
+ #:use-module (guix packages)
+ #:use-module (gnu system keyboard)
+ #:use-module (gnu services configuration)
+ #:use-module (gnu home services)
+ #:use-module (gnu packages freedesktop)
+ #:use-module (gnu packages xdisorg)
+ #:use-module (gnu packages image)
+ #:use-module (gnu packages gnome)
+ #:use-module (gnu packages wm)
+ #:use-module (gnu packages emacs)
+ #:use-module (gnu packages linux)
+ #:use-module (gnu packages base)
+ #:use-module (gnu packages terminals)
+ #:use-module (gnu packages suckless)
+ #:use-module (gnu packages glib)
+ #:export (;; Event codes
+ %ev-code-mouse-left
+ %ev-code-mouse-right
+ %ev-code-mouse-scroll-click
+
+ ;; Configuration records.
+ sway-configuration
+ sway-bar
+ sway-output
+ sway-input
+ point
+ sway-color
+ sway-border-color
+ home-sway-service-type
+ sway-configuration->file
+ sway-mode
+
+ ;; Default values.
+ %sway-default-variables
+ %sway-default-gestures
+ %sway-default-keybindings
+ %sway-default-status-command
+ %sway-default-startup-programs
+ %sway-default-packages))
+
+;; Helper function.
+(define (flatmap f l)
+ (let loop ((lst (reverse l)) (acc '()))
+ (match lst
+ (() acc)
+ ((head . tail)
+ (let* ((h (f head))
+ (acc (append h acc)))
+ (loop tail acc))))))
+
+
+;;;
+;;; Default settings and useful constants.
+;;;
+
+(define %ev-code-mouse-left 272)
+(define %ev-code-mouse-right 273)
+(define %ev-code-mouse-scroll-click 274)
+
+(define %sway-default-packages
+ (list sway))
+
+(define %sway-default-variables
+ `((mod . "Mod4")
+ (left . "h")
+ (down . "j")
+ (up . "k")
+ (right . "l")
+ (term . ,(file-append foot "/bin/foot"))
+ (menu . ,#~(s
This message was truncated. Download the full message here.
A
A
Arnaud Daby-Seesaram wrote on 2 Oct 00:30 +0200
[PATCH v7] home: services: Add 'home-sway-service-type'.
(address . 72714@debbugs.gnu.org)
20241001223050.1203-1-ds-ac@nanein.fr
* gnu/home/services/sway.scm: New file.
(home-sway-service-type): New variable.
(sway-configuration->file): New procedure.
(sway-configuration): New configuration record.
(sway-bar): New configuration record.
(sway-output): New configuration record.
(sway-input): New configuration record.
(point): New configuration record.
(sway-color): New configuration record.
(sway-border-color): New configuration record.
(sway-mode): New configuration record.
(flatten): New procedure.
* gnu/local.mk: Add gnu/home/services/sway.scm.
* doc/guix.texi (Sway window manager): New node to document the above changes.
---
Sorry, I forgot to wrap a long line in guix.texi.

doc/guix.texi | 395 ++++++++++++++++++
gnu/home/services/sway.scm | 794 +++++++++++++++++++++++++++++++++++++
gnu/local.mk | 1 +
3 files changed, 1190 insertions(+)
create mode 100644 gnu/home/services/sway.scm

Toggle diff (558 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index 52e36e4354..8b86f57005 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -130,6 +130,7 @@ Copyright @copyright{} 2024 Richard Sent@*
Copyright @copyright{} 2024 Dariqq@*
Copyright @copyright{} 2024 Denis 'GNUtoo' Carikli@*
Copyright @copyright{} 2024 Fabio Natali@*
+Copyright @copyright{} 2024 Arnaud Daby-Seesaram@*
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -460,6 +461,7 @@ Home Services
* Mail: Mail Home Services. Services for managing mail.
* Messaging: Messaging Home Services. Services for managing messaging.
* Media: Media Home Services. Services for managing media.
+* Sway: Sway window manager. Setting up the Sway configuration.
* Networking: Networking Home Services. Networking services.
* Miscellaneous: Miscellaneous Home Services. More services.
@@ -45196,6 +45198,7 @@ services)}.
* Mail: Mail Home Services. Services for managing mail.
* Messaging: Messaging Home Services. Services for managing messaging.
* Media: Media Home Services. Services for managing media.
+* Sway: Sway window manager. Setting up the Sway configuration.
* Networking: Networking Home Services. Networking services.
* Miscellaneous: Miscellaneous Home Services. More services.
@end menu
@@ -47110,6 +47113,398 @@ kodi} for more information.
@end table
@end deftp
+@node Sway window manager
+@subsection Sway window manager
+
+@cindex sway, Home Service
+@cindex sway, configuration
+The @code{(gnu home services sway)} module provides
+@code{home-sway-service-type}, a home service to configure the
+@uref{https://github.com/swaywm/sway,Sway window manager for Wayland} in
+a declarative way.
+
+Here is an example of a service and its configuration that you could add
+to the @code{services} field of your @code{home-environment}:
+
+@lisp
+(service home-sway-service-type
+ (sway-configuration
+ (gestures
+ '((swipe:3:down . "move to scratchpad")
+ (swipe:3:up . "scratchpad show")))
+ (outputs
+ (list (sway-output
+ (identifier '*)
+ (bg (file-append sway
+ "\
+/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png")))))))
+@end lisp
+
+The above example describes a Sway configuration in which
+@itemize
+@item
+all monitors use a particular wallpaper whose @file{.png} is provided by
+the @code{sway} package;
+@item
+swiping down (resp.@: up) with three fingers moves the active window to
+the scratchpad (resp.@: shows/hides the scratchpad).
+@end itemize
+
+@quotation Note
+This home service only sets up the configuration file and profile
+packages for Sway. It does @emph{not} start Sway in any way. If you
+want to do so, you might be interested in using
+@code{greetd-wlgreet-sway-session} instead.
+
+The function @code{sway-configuration->file} defined below can be used
+to provide the value for the @emph{optional} @code{sway-configuration}
+field of @code{greetd-wlgreet-sway-session}.
+@end quotation
+
+@deffn {Procedure} sway-configuration->file config
+This function takes a @code{sway-configuration} record (defined below),
+and returns a file-like object representing the serialized
+configuration.
+@end deffn
+
+@defvar home-sway-service-type
+This is a home service type to set up Sway. It takes care of:
+@itemize
+@item
+providing a @file{~/.config/sway/config} file,
+@item
+adding Sway-related packages to your profile.
+@end itemize
+@end defvar
+
+@deftp {Data Type} sway-configuration
+This configuration record describes the Sway configuration
+(see@ @cite{sway(5)}). Available fields are:
+
+@table @asis
+@item @code{variables} (default: @code{%sway-default-variables})
+The value of this field is an association list in which keys are symbols
+and values are either strings, G-expressions or file-append objects
+(@pxref{G-Expressions}).
+
+Example:
+@lisp
+(variables `((mod . "Mod4") ; string
+ (term ; file-append
+ . ,(file-append foot "/bin/foot"))
+ (term ; G-expression
+ . ,#~(string-append #$foot "/bin/foot"))))
+@end lisp
+
+@item @code{keybindings} (default: @code{%sway-default-keybindings})
+This field describes keybindings for the @emph{default} mode. The value
+is an association list: keys are symbols and values are either strings
+or G-expressions.
+
+The following snippet launches the terminal when pressing @kbd{$mod+t}
+and @kbd{$mod+Shift+t} (assuming that a variable @code{$term} is
+defined):
+@lisp
+`(($mod+t . ,#~(string-append "exec " #$foot "/bin/foot"))
+ ($mod+Shift+t . "exec $term"))
+@end lisp
+
+@item @code{gestures} (default: @code{%sway-default-gestures})
+Similar to the previous field, but for finger-gestures.
+
+The following snippet allows to navigate through workspaces by swiping
+right and left with three fingers:
+@lisp
+'((swipe:3:right . "workspace next_on_output")
+ (swipe:3:left . "workspace prev_on_output"))
+@end lisp
+
+@item @code{packages} (default: @code{%sway-default-packages})
+This field describes a list of packages to add to the user profile. At
+the moment, the default value only adds @code{sway} to the profile.
+
+@item @code{inputs} (default: @code{'()})
+List of @code{sway-input} configuration records (described below).
+
+@item @code{outputs} (default: @code{'()})
+List of @code{sway-output} configuration records (described below).
+
+@item @code{bar} (optional @code{sway-bar} record)
+Optional @code{sway-bar} record (described below) to configure a Sway
+bar.
+
+@item @code{modes} (default: @code{'()})
+Optional list of @code{sway-mode} records (described below) to add modes
+to the Sway configuration (@i{e.g.}@: the ``resize'' mode of the default
+Sway configuration).
+
+@item @code{startup+reload-programs} (default: @code{'()})
+Programs to execute at startup time @emph{and} after every configuration
+reload. The value of this field is a list of strings, G-expressions or
+file-append objects (@pxref{G-Expressions}).
+
+@item @code{startup-programs} (default: @code{%sway-default-execs})
+Programs to execute at startup time. As above, values of this field are
+a list of strings, G-expressions or file-append objects.
+
+The default value, @code{%sway-default-execs}, executes @code{swayidle}
+in order to lock the screen after 5@ minutes of inactivity (displaying a
+background distributed with Sway) and turn the screen off after 10@
+minutes of inactivity.
+
+@item @code{extra-content} (default: @code{'()})
+Lines to add to the configuration file. The value of this field is a
+list of strings or G-expressions.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-input
+@code{sway-input} records describe input blocks (see@
+@cite{sway-input(5)}). For example, the following snippet makes all
+keyboards use a french layout, in which @kbd{capslock} has been remaped
+to @kbd{ctrl}:
+@lisp
+(sway-input (identifier "type:keyboard")
+ (layout
+ (keyboard-layout "fr" #:options '("ctrl:nocaps"))))
+@end lisp
+
+Available fields for @code{sway-input} configuration records are:
+
+@table @asis
+@item @code{identifier} (default: @code{'*})
+Identifier of the input. The field accepts symbols and strings. If the
+@code{identifier} is a symbol, it is inserted as is; if it is a string,
+it will be quoted in the configuration file.
+
+
+@item @code{layout} (optional @code{<keyboard-layout>} record)
+Keyboard specific option. Field specifying the layout (possibly with
+options) to use for the input. The value must be a
+@code{<keyboard-layout>} record (@pxref{Keyboard Layout}).
+
+@quotation Note
+@code{(gnu home services sway)} does not re-export the
+@code{keyboard-layout} procedure.
+@end quotation
+
+
+@item @code{disable-while-typing} (optional boolean)
+If @code{#t} (resp.@: @code{#f}) enables (resp.@: disables) the
+``disable while typing'' option for this input.
+
+@item @code{disable-while-trackpointing} (optional boolean)
+If @code{#t} (resp.@: @code{#f}), enables (resp.@: disables) the
+``disable while track-pointing'' option for this input.
+
+@item @code{tap} (optional boolean)
+Enables or disables the ``tap'' option, which allows clicking by tapping
+on a touchpad.
+
+@item @code{extra-content} (default: @code{'()})
+Lines to add to the input block. The value of this field is a list
+whose elements can be either strings or G-expressions.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-output
+@code{sway-output} records describe Sway outputs
+(see@ @cite{sway-output(5)}). Available fields are:
+
+@table @asis
+@item @code{identifier} (default: @code{'*})
+Identifier of the monitor. The field accepts symbols and strings. If
+the @code{identifier} is a symbol, it is inserted as is; if it is a
+string, it will be quoted in the configuration file.
+
+@item @code{resolution} (optional string)
+This string defines the resolution of the monitor.
+
+@item @code{position} (optional)
+The (optional) value of this field must be a @code{point}.
+Example:
+@lisp
+(position
+ (point (x 1920)
+ (y 0)))
+@end lisp
+
+@item @code{background} (optional)
+The value of this field describes what wallpaper to use on this output.
+The field accepts the following types of values:
+@itemize
+@item
+a string,
+@item
+a G-expression,
+@item
+a file-append object,
+@item
+a pair. The first argument of this pair must be a string, a
+G-expression or a file-append object. The second element of the pair
+must be a symbol among @code{stretch}, @code{fill}, @code{fit},
+@code{center} and @code{tile}.
+@end itemize
+
+@quotation Note
+In order to use an SVG file, you must have @code{librsvg} in your
+profile (@i{e.g.}@: by adding it in the @code{packages} field of
+@code{sway-configuration}).
+@end quotation
+
+@item @code{extra-content} (default: @code{'()})
+List defining additional lines to add to the output configuration block.
+Elements of the list must be either strings or G-expressions.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-border-color
+
+@table @code
+@item border
+Color of the border.
+@item background
+Color of the background.
+@item text
+Color of the text.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-color
+@table @asis
+@item @code{background} (optional string)
+Background color of the bar.
+
+@item @code{statusline} (optional string)
+Text color of the status line.
+
+@item @code{focused-background} (optional string)
+Background color of the bar on the currently focused monitor.
+
+@item @code{focused-statusline} (optional string)
+Text color of the statusline on the currently focused monitor.
+
+@item @code{focused-workspace} (optional @code{sway-border-color})
+Color scheme for focused workspaces.
+
+@item @code{active-workspace} (optional @code{sway-border-color})
+Color scheme for active workspaces.
+
+@item @code{inactive-workspace} (optional @code{sway-border-color})
+Color scheme for inactive workspaces.
+
+@item @code{urgent-workspace} (optional @code{sway-border-color})
+Color scheme for workspaces containing ``urgent'' windows.
+
+@item @code{binding-mode} (optional @code{sway-border-color})
+Color scheme for the binding mode indicator.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-bar
+Describes the Sway bar (see@ @cite{sway-bar(5)}).
+
+@table @asis
+@item @code{identifier} (default: @code{'bar0})
+Identifier of the bar. The value must be a symbol.
+
+@item @code{position} (optional)
+Specify the position of the bar. Accepted values are @code{'top} or
+@code{'bottom}.
+
+@item @code{hidden-state} (optional)
+Specify the apparence of the bar when it is hidden. Accepted values are
+@code{'hide} or @code{'show}.
+
+@item @code{binding-mode-indicator} (optional)
+Boolean enabling or disabling the binding mode indicator.
+
+@item @code{colors} (optional)
+An optional @code{sway-color} configuration record.
+
+@item @code{status-command} (default: @code{%sway-status-command})
+This field accept strings, G-expressions and executable file-like
+values. The default value is a command (string) that prints the date
+and time every second.
+
+Each line printed on @code{stdout} by this command (or script) will be
+displayed on the status area of the bar.
+
+Below are a few examples using:
+@itemize
+@item
+a string: @code{"while date +'%Y-%m-%d %X'; do sleep 1; done"},
+@item
+a G-exp:
+@lisp
+#~(string-append "while "
+ #$coreutils "/bin/date"
+ " +'%Y-%m-%d %X'; do sleep 1; done")
+@end lisp
+@item
+an executable file:
+@lisp
+(program-file
+ "sway-bar-status"
+ #~(begin
+ (use-modules (ice-9 format)
+ (srfi srfi-19))
+ (let loop ()
+ (let* ((date (date->string
+ (current-date)
+ "~d/~m/~Y (~a) ~H:~M:~S")))
+ (format #t "~a~%~!" date)
+ (sleep 1)
+ (loop)))))
+@end lisp
+@end itemize
+
+@item @code{mouse-bindings} (default: @code{'()})
+This field accepts an associative list. Keys are integers describing
+mouse events. Values can either be strings or G-expressions.
+
+The module @code{(gnu home services sway)} exports constants
+@code{%ev-code-mouse-left}, @code{%ev-code-mouse-right} and
+@code{%ev-code-mouse-scroll-click} whose values are integers
+corresponding to left, right and scroll click respectively. For
+example, with @code{(mouse-bindings `((,%ev-code-mouse-left
+. ,#~(string-append "exec " #$st "/bin/st"))))}, left clicks in the
+status bar open the @code{st} terminal.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-mode
+Describes a Sway mode (see@ @cite{sway(5)}). For example, the following
+snippet defines a mockup of the resize mode of the default Sway
+configuration:
+@example
+(sway-mode
+ (mode-name "resize")
+ (keybindings
+ '(($left . "resize shrink width 10px")
+ ($right . "resize grow width 10px")
+ ($down . "resize grow height 10px")
+ ($up . "resize shrink height 10px")
+ (Return . "mode \"default\"")
+ (Escape . "mode \"default\""))))
+@end example
+
+@table @asis
+@item @code{mode-name} (default: @code{"default"})
+Name of the mode. This field accepts strings.
+
+@item @code{keybindings} (default: @code{'()})
+This field describes keybindings. The value is an association list:
+keys are symbols and values are either strings or G-expressions, as
+above.
+
+@item @code{mouse-bindings} (default: @code{'()})
+Ditto, but keys are mouse events (integers). Constants
+@code{%ev-code-mouse-*} described above can be used as helpers to define
+mouse bindings.
+@end table
+@end deftp
+
@node Networking Home Services
@subsection Networking Home Services
diff --git a/gnu/home/services/sway.scm b/gnu/home/services/sway.scm
new file mode 100644
index 0000000000..25cae56dae
--- /dev/null
+++ b/gnu/home/services/sway.scm
@@ -0,0 +1,794 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2024 Arnaud Daby-Seesaram <ds-ac@nanein.fr>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix 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 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix 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 GNU Guix. If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu home services sway)
+ #:use-module (guix modules)
+ #:use-module (guix gexp)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-26)
+ #:use-module (ice-9 popen)
+ #:use-module (ice-9 format)
+ #:use-module (ice-9 match)
+ #:use-module (guix packages)
+ #:use-module (gnu system keyboard)
+ #:use-module (gnu services configuration)
+ #:use-module (gnu home services)
+ #:use-module (gnu packages freedesktop)
+ #:use-module (gnu packages xdisorg)
+ #:use-module (gnu packages image)
+ #:use-module (gnu packages gnome)
+ #:use-module (gnu packages wm)
+ #:use-module (gnu packages emacs)
+ #:use-module (gnu packages linux)
+ #:use-module (gnu packages base)
+ #:use-module (gnu packages terminals)
+ #:use-module (gnu packages suckless)
+ #:use-module (gnu packages glib)
+ #:export (;; Event codes
+ %ev-code-mouse-left
+ %ev-code-mouse-right
+ %ev-code-mouse-scroll-click
+
+ ;; Configuration records.
+ sway-configuration
+ sway-bar
+ sway-output
+ sway-input
+ point
+ sway-color
+ sway-border-color
+ home-sway-service-type
+ sway-configuration->file
+ sway-mode
+
+ ;; Default values.
+ %sway-default-variables
+ %sway-default-gestures
+ %sway-default-keybindings
+ %sway-default-status-command
+ %sway-default-startup-programs
+ %sway-default-packages))
+
+;; Helper function.
+(define (flatmap f l)
+ (let loop ((lst (reverse l)) (acc '()))
+ (match lst
+ (() acc)
+ ((head . tail)
+ (let* ((h (f head))
+ (acc (append h acc)))
+ (loop tail acc))))))
+
+
+;;;
+;;; Default settings and useful constants.
+;;;
+
+(define %ev-code-mouse-left 272)
+(define %ev-code-mouse-right 273)
+(define %ev-code-mouse-scroll-click 274)
+
+(define %sway-default-packages
+ (list sway))
+
+(define %sway-default-variables
+ `((mod . "Mod4")
+ (left . "h")
+ (down . "j")
+ (up . "k")
+ (right . "l")
+ (term . ,(file-append foot "/bin/foot"))
+ (menu . ,#~(string-append
+ #$dmenu "/bin/dmenu_path | \\\n "
+ #$wmenu "/bin/wmenu | \\\n "
+ #$findutils "/bin/xargs \\\n "
+ #$sway "/bin/swaymsg exec --"))))
+
+(define %sway-default-gestures
+ '((swipe:3:right . "workspace next_on_output")
+ (swipe:3:left . "workspace prev_on_output")
+ (swipe:3:down . "move to scratchpad")
+ (swipe:3:up . "scratchpad show")))
+
+(define %sway-default-keybindings
+ `(($mod+Return . "exec $term")
+ ($mod+Shift+q . "kill")
+ ($mod+d . "exec $menu")
+ ($mod+Shift+c . "reload")
+ ($mod+Shift+e
+ . ,#~(string-append
+ "exec " #$sway "/bin/swaynag -t warning -m \\\n "
+ "'You pressed the exit shortcut. Do you really want to exit sway?"
+ " This will end your Wayland session.' \\\n "
+ "-B 'Yes, exit sway' \\\n '"
+ #$sway "/bin/swaymsg exit'"))
+ ($mod+$left . "focus left")
+ ($mod+$down . "focus down")
+ ($mod+$up . "focus up")
+ ($mod+$right . "focus right")
+ ($mod+Left . "focus left")
+ ($mod+Do
This message was truncated. Download the full message here.
P
P
pelzflorian (Florian Pelz) wrote on 2 Oct 16:08 +0200
Re: [PATCH] home: services: Add 'home-sway-service-type'.
(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)
878qv6tx5i.fsf@pelzflorian.de
Hi Arnaud. I still have not tested nor reviewed all features, but
some comments:

Arnaud Daby-Seesaram writes:
Toggle quote (13 lines)
> +(define %sway-default-variables
> + `((mod . "Mod4")
> + (left . "h")
> + (down . "j")
> + (up . "k")
> + (right . "l")
> + (term . ,(file-append foot "/bin/foot"))
> + (menu . ,#~(string-append
> + #$dmenu "/bin/dmenu_path | \\\n "
> + #$wmenu "/bin/wmenu | \\\n "
> + #$findutils "/bin/xargs \\\n "
> + #$sway "/bin/swaymsg exec --"))))

After I added new packages to home-environment’s packages field,
dmenu_path does not list newly installed packages for me, because it
is a shell script which needs a program called stest in PATH.

Now the wmenu_path I talked about earlier appears to be an invention
by the OpenBSD people that does not need stest [1].

Perhaps for more hackability, we could deviate from upstream and put in
a call to guile with a Scheme script in a computed-file that opens a
pipe to/from wmenu and does the same as dmenu_path without cache only on
~/.guix-home/profile/bin.

Or change the dmenu_path program with `substitute' to use the absolute
file-name of stest.


Toggle quote (17 lines)
> +Here is an example of a service and its configuration that you could add
> +to the @code{services} field of your @code{home-environment}:
> +
> +@lisp
> +(service home-sway-service-type
> + (sway-configuration
> + (gestures
> + '((swipe:3:down . "move to scratchpad")
> + (swipe:3:up . "scratchpad show")))
> + (outputs
> + (list (sway-output
> + (identifier '*)
> + (bg (file-append sway
> + "\
> +/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png")))))))
> +@end lisp

There is no bg anymore.


Toggle quote (7 lines)
> + (add-line-if "position" position
> + #:serializer
> + (lambda (p)
> + (string-append (number->string (point-x p))
> + " "
> + (number->string (point-x p)))))

A
A
Arnaud Daby-Seesaram wrote on 2 Oct 22:49 +0200
(name . pelzflorian (Florian Pelz))(address . pelzflorian@pelzflorian.de)
87ttdu9qmo.fsf@nanein.fr
Hi Florian,

"pelzflorian (Florian Pelz)" <pelzflorian@pelzflorian.de> writes:
Toggle quote (26 lines)
> Arnaud Daby-Seesaram writes:
>> +(define %sway-default-variables
>> + `((mod . "Mod4")
>> + (left . "h")
>> + (down . "j")
>> + (up . "k")
>> + (right . "l")
>> + (term . ,(file-append foot "/bin/foot"))
>> + (menu . ,#~(string-append
>> + #$dmenu "/bin/dmenu_path | \\\n "
>> + #$wmenu "/bin/wmenu | \\\n "
>> + #$findutils "/bin/xargs \\\n "
>> + #$sway "/bin/swaymsg exec --"))))
>
> After I added new packages to home-environment’s packages field,
> dmenu_path does not list newly installed packages for me, because it
> is a shell script which needs a program called stest in PATH.
>
> Now the wmenu_path I talked about earlier appears to be an invention
> by the OpenBSD people that does not need stest [1].
>
> Perhaps for more hackability, we could deviate from upstream and put in
> a call to guile with a Scheme script in a computed-file that opens a
> pipe to/from wmenu and does the same as dmenu_path without cache only on
> ~/.guix-home/profile/bin.

Yes indeed. Do you think that the Guile script should replace all of
"$menu", or just the dmenu_path part?

On this topic, do you know if there is a built-in way to write
`find -maxdepth 1 ...' in Guile (without calling `readdir' manually)?

Toggle quote (2 lines)
> only on ~/.guix-home/profile/bin.

What is the rationale for restricting the menu to this directory (and
not all directories in
(filter directory-exists? (string-split (getenv "PATH") #\:))
?

Toggle quote (3 lines)
> Or change the dmenu_path program with `substitute' to use the absolute
> file-name of stest.

I think that the Guile script might be simpler.

By `substitute', do you mean in the package definition? This does not
seem necessary, as people installing dmenu have stest in their profile.


"pelzflorian (Florian Pelz)" <pelzflorian@pelzflorian.de> writes:
Toggle quote (4 lines)
> There is no bg anymore.
> [...]
> Should be point-y.

The point-issue was introduced in the v6. I apologise for those issues
that I bring in new patches... Thank you for catching them!

In my local files, I have also switched from using `open-output-file' to
`call-with-output-file'¹ and reduced the number of redundant calls to
`make-string'.
¹: in previous patches, I never called
`close-port'.

"pelzflorian (Florian Pelz)" <pelzflorian@pelzflorian.de> writes:
Toggle quote (3 lines)
> Hi Arnaud. I still have not tested nor reviewed all features, but
> some comments:

Do you want me to send a v8 with the above fixes, or should I wait until
we change the content of the "$menu" variable?


Best regards,

--
Arnaud
-----BEGIN PGP SIGNATURE-----

iQJEBAEBCgAuFiEEMgqfJ4U0fby1t860ojLKXoMTiAwFAmb9sfAQHGRzLWFjQG5h
bmVpbi5mcgAKCRCiMspegxOIDEgOD/9+4WPKHxyKSNdj7PIzPDluIpfEVYONcYeP
UXYtnDx1hxuSMollWcHLn3XOrwthCymKnd+O0Q/+pXQdKMA/v1Jz2SCwg0mG3U1o
fbAAq7DXtzrB6g7WLSPsFNHAIzwYuFVtH2zzzeahTI1KnM+/yi9qwDfL/S6rhMKr
wcZaH8OT9kbzBnje0fACYa3o4xASz3wfskSRQIeP9O9NaWLyQsYdDq5V2hQccOM0
YbmdmtA338ASW6UCFTRG6vjQZ1JzAzT2PNJEmw6a+fgy/i7IpIfVUoVLwZ61Muu+
AlF71idH2LQBNTmD1I8cLDefSZs7ByMCxYAmAzPUwpYll1FQ6JCTv6urpgAp1HLz
E8P1HA/iSh5tS4xzB7Y2y0ClpMdvhzSuOQX3SZsHVB8T2OD4qSx3Lb8vB/GGxpWu
LStwp/myLpIp7BSzV3DGSaE2FuAIkwpJt9SkOHWw8elUQbwkzBCM1sRbiEmtf4yS
haZqK87sTIEj/yRRN0eegBql9/9qnpLP5fwlfa7SgKOZ4wdO5nLjeYP/KvTlaxEW
YL7/EOmukgFQrOlZqQEQb2xZaP0KvPHEQ3h0JT+e2NujwlOpjntM94S9JsGM7grW
sp9QztF49oJ0qBxWmyHhhUgRojtYM3dSnGIDbIZVJ8imI1sJgQuQdulNPAjKfhpa
wWHGLIy5Sg==
=uBH9
-----END PGP SIGNATURE-----

P
P
pelzflorian (Florian Pelz) wrote on 3 Oct 14:41 +0200
(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)
875xq9we7n.fsf@pelzflorian.de
Hello Arnaud.

Arnaud Daby-Seesaram <ds-ac@nanein.fr> writes:
Toggle quote (10 lines)
> "pelzflorian (Florian Pelz)" <pelzflorian@pelzflorian.de> writes:
>> Perhaps for more hackability, we could deviate from upstream and put in
>> a call to guile with a Scheme script in a computed-file that opens a
>> pipe to/from wmenu and does the same as dmenu_path without cache only on
>> ~/.guix-home/profile/bin.
>
> Yes indeed. Do you think that the Guile script should replace all of
> "$menu", or just the dmenu_path part?
>

All of "$menu", because it looks nicer? But I should not imply that
such deviation from upstream were necessary for getting your patch in.

Basically my issue was that dmenu_path did not work.

Indeed stest is part of the dmenu package, so when dmenu is installed to
the profile, dmenu_path would work. So a more upstream conformant
solution would be to just add the dmenu package to sway’s packages.

However, dmenu_path’s cache means that if we used dmenu_path like
upstream, it would never recognize changes to the installed packages.
OpenBSD opted for wmenu_path which is like dmenu_path without cache
and a guile script seems more appropriate for Guix’ defaults.


Toggle quote (3 lines)
> On this topic, do you know if there is a built-in way to write
> `find -maxdepth 1 ...' in Guile (without calling `readdir' manually)?

scandir from the (ice-9 ftw) module, I think.


Toggle quote (8 lines)
>> only on ~/.guix-home/profile/bin.
>
> What is the rationale for restricting the menu to this directory (and
> not all directories in
> (filter directory-exists? (string-split (getenv "PATH") #\:))
> ?
>

All my graphical applications are in the home profile and non-graphical
programs will not be used and clutter wmenu. Do others put graphical
apps in the system profile? Perhaps so. But then non-graphical
coreutils would be in the wmenu as well. Hmm I am not sure and would be
fine with either.


Toggle quote (7 lines)
>> Or change the dmenu_path program with `substitute' to use the absolute
>> file-name of stest.
>
> I think that the Guile script might be simpler.
>
> By `substitute', do you mean in the package definition?

Yes, the dmenu package definition.

Toggle quote (4 lines)
> This does not
> seem necessary, as people installing dmenu have stest in their profile.
>

If dmenu were installed in the sway-packages, substitute would not be needed.


Toggle quote (3 lines)
> Do you want me to send a v8 with the above fixes, or should I wait until
> we change the content of the "$menu" variable?

It can wait.

Regards,
Florian
A
A
Arnaud Daby-Seesaram wrote on 3 Oct 22:53 +0200
(name . pelzflorian (Florian Pelz))(address . pelzflorian@pelzflorian.de)
877caoewmh.fsf@nanein.fr
Hello Florian,

"pelzflorian (Florian Pelz)" <pelzflorian@pelzflorian.de> writes:
Toggle quote (14 lines)
> Arnaud Daby-Seesaram <ds-ac@nanein.fr> writes:
>> "pelzflorian (Florian Pelz)" <pelzflorian@pelzflorian.de> writes:
>>> Perhaps for more hackability, we could deviate from upstream and put in
>>> a call to guile with a Scheme script in a computed-file that opens a
>>> pipe to/from wmenu and does the same as dmenu_path without cache only on
>>> ~/.guix-home/profile/bin.
>>
>> Yes indeed. Do you think that the Guile script should replace all of
>> "$menu", or just the dmenu_path part?
>>
>
> All of "$menu", because it looks nicer? But I should not imply that
> such deviation from upstream were necessary for getting your patch in.

No worries. I think that finding a better solution now would be better
(and should not delay this issue for too long). It would avoid opening
a second issue and delaying/forgetting the cache problem.

Toggle quote (11 lines)
> Basically my issue was that dmenu_path did not work.
>
> Indeed stest is part of the dmenu package, so when dmenu is installed to
> the profile, dmenu_path would work. So a more upstream conformant
> solution would be to just add the dmenu package to sway’s packages.
>
> However, dmenu_path’s cache means that if we used dmenu_path like
> upstream, it would never recognize changes to the installed packages.
> OpenBSD opted for wmenu_path which is like dmenu_path without cache
> and a guile script seems more appropriate for Guix’ defaults.

Yes, adding dmenu would work (minus your second point). However, to
rely on both wmenu and dmenu feels a little weird, especially since the
latter is only used for a bash script.
It seems that Sway recently switched[1] to a utility called wmenu-run
(C program shipped with the last version of wmenu) to get rid of their
dependency on dmenu.



Toggle quote (13 lines)
>>> only on ~/.guix-home/profile/bin.
>>
>> What is the rationale for restricting the menu to this directory (and
>> not all directories in
>> (filter directory-exists? (string-split (getenv "PATH") #\:))
>> ?
>>
> All my graphical applications are in the home profile and non-graphical
> programs will not be used and clutter wmenu. Do others put graphical
> apps in the system profile? Perhaps so. But then non-graphical
> coreutils would be in the wmenu as well. Hmm I am not sure and would be
> fine with either.

Yes, this is a good point. I also agree that using a single script for
all of the menu would make it clearer and more maintainable.

For both these reasons, here is a draft proposal for a script that could
replace the current content of "$menu". As suggested, it uses `scandir'
and only focuses on packages of the "home profile".

Toggle snippet (37 lines)
(define sway-menu
(computed-file
"sway-menu.scm"
#~(begin
(use-modules (ice-9 receive)
(ice-9 rdelim)
(ice-9 ftw)
(guix build utils))

(define (directory->files dir)
(define (executable-file? f)
;; Cf. `(@@ (guix build utils) executable-file?)' for an
;; explanation of `(zero? ...)'.
(and=> (stat f)
(lambda (s)
(not (or (zero? (logand (stat:mode s) #o100))
(eq? (stat:type s) 'directory))))))
(with-directory-excursion dir
(scandir "." executable-file?)))

(let ((path (string-append (getenv "HOME")
"/.guix-home/profile/bin"))
(wmenu #$(file-append wmenu "/bin/wmenu"))
(swaymsg #$(file-append sway "/bin/swaymsg")))
(receive (from to pid)
((@@ (ice-9 popen) open-process) OPEN_BOTH wmenu)
(for-each
(lambda (c) (format to "~a~%" c))
(directory->files path))
(close to)
(let ((choice (read-line from)))
(close from)
(waitpid pid)
(execl swaymsg swaymsg "exec"
(string-append path "/" choice))))))))

WDYT?


Best regards,

--
Arnaud
-----BEGIN PGP SIGNATURE-----

iQJEBAEBCgAuFiEEMgqfJ4U0fby1t860ojLKXoMTiAwFAmb/BFYQHGRzLWFjQG5h
bmVpbi5mcgAKCRCiMspegxOIDKpJD/wOCO7McVLaBLs01FSVtEcdNK8QPL6AfBxY
xesl/oc/hLeLXwIW7d79dXzRgf3MfMhPKHSBLU/9Mstqwf8H1tQLmVRKEoML/6Lt
vuvNbEM6l9nHIgWVbPM9NShYc9OTNaomzX4GYZPm8nz7+P8YEQ38h2exOJIFmV/Q
dai0U3Y0nYsc71PiggR/yZXo+qOPjSTEzS8sPROsvSr5Cjiotwj45WX7S5xPhC+7
Udrv8t95v16FJbHceSAPwvoG3aIMUGp8iUaocBK1n5TpKgZSuIA6vOfaDwCgJCTP
0LxPmAyKsLMGR5EWo62Exabi76JkL4/kC3sx593fPehV8RcbfXAP64Nco0edihOO
K9frfA9B/p6LCy3ClnkklE2dtTqB0J/9P2dykByQUn5WsKGead4/9pAOPRGJurvK
xHY/eryWtauAjVwO1C/7JOzej8kSL+0gs8xUQEtYWW2lchurdtp8hd49PbI96gSB
QFGrydu57DFaVl7KxyHhOCCA93ozC1l415pclkUtGiLCWUeJ71qbEXARVMhUnG3q
8nqVCh/kCZOSoyXEvMeeJh0qJMh8jIevIxANDyjcU017PeLI2TCLM+jN6laELVGn
UNTFdogVC6lT5ebH6HWrD7WylXi2QZIeSuXxiD9hXIgKeOCuh+K058OCA7v0q74+
Xn8E7phxuw==
=44NG
-----END PGP SIGNATURE-----

P
P
pelzflorian (Florian Pelz) wrote on 4 Oct 22:17 +0200
(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)
87jzenr5bj.fsf@pelzflorian.de
Hello Arnaud. I like a lot your sway-menu.scm. For testing, I’ve
changed

(define sway-menu
(computed-file
"sway-menu.scm"

to

(define sway-menu
(scheme-file
"sway-menu.scm"

to use it like this:

(sway-configuration
(variables
`((menu . ,#~(string-append
"guile " #$sway-menu))

Sorry for having proposed compiled-file previously. At first I had
thought a compiled sway-menu.go would be appropriate, created in a
computed-file, which invokes `guild compile` on the .scm code, but
apparently this is not useful. I do not know enough here and
gnu/services/shepherd.scm does it in the scm->go procedure.

Anyway, some feedback:

Toggle quote (5 lines)
> (define (directory->files dir)
> (define (executable-file? f)
> ;; Cf. `(@@ (guix build utils) executable-file?)' for an
> ;; explanation of `(zero? ...)'.

This is a comment anyway, but one @ in (@ (guix build utils)
executable-file?) would be enough, since the executable-file?
predicate is exported.


Toggle quote (3 lines)
> (and=> (stat f)
> (lambda (s)

To reduce clutter in the wmenu suggestions more, I’d prefer

(and=> (and (not (eq? (string-ref f 0) #\.))
(stat f))
(lambda (s)


Toggle quote (12 lines)
> (not (or (zero? (logand (stat:mode s) #o100))
> (eq? (stat:type s) 'directory))))))
> (with-directory-excursion dir
> (scandir "." executable-file?)))
>
> (let ((path (string-append (getenv "HOME")
> "/.guix-home/profile/bin"))
> (wmenu #$(file-append wmenu "/bin/wmenu"))
> (swaymsg #$(file-append sway "/bin/swaymsg")))
> (receive (from to pid)
> ((@@ (ice-9 popen) open-process) OPEN_BOTH wmenu)

Better use @ instead of @@.


Toggle quote (10 lines)
> (for-each
> (lambda (c) (format to "~a~%" c))
> (directory->files path))
> (close to)
> (let ((choice (read-line from)))
> (close from)
> (waitpid pid)
> (execl swaymsg swaymsg "exec"
> (string-append path "/" choice))))))))

Even though I like to get suggestions only for
~/.guix-home/profile/bin, if you do not prepend path,

(execl swaymsg swaymsg "exec"
choice)))))))

then it will remain possible to write shell commands in wmenu such as

guix shell weston -- weston-flower

to run apps without installing them.

Thank you greatly, this will definitely become my menu and in my
opinion it is the best default.

Since you told me about wmenu-run, I also locally updated wmenu [1]
and tested the menu config

(menu . ,#~(string-append
#$wmenu "/bin/wmenu-run"))

which would also work, but in my opinion the suggestions are better
when tied to .guix-home/profile. The wmenu-run does not use exec but
a protocol called XDG_ACTIVATION_TOKEN. But I do not see an advantage
to it. It behaves like always.

I’d welcome if you, Arnaud, sent a patch calling your sway-menu script.

Also I’d be happy if more careful commiters would push it; I prefer to
restrict my commits to translation updates.

Also one more thing, in the commit message, you meant to write
flatmap instead of flatten.

Regards,
Florian

[1]
Toggle diff (24 lines)
diff --git a/gnu/packages/wm.scm b/gnu/packages/wm.scm
index 38cb8cc717..9615054841 100644
--- a/gnu/packages/wm.scm
+++ b/gnu/packages/wm.scm
@@ -1865,16 +1865,16 @@ (define-public wl-mirror
(define-public wmenu
(package
(name "wmenu")
- (version "0.1.7")
+ (version "0.1.9")
(source (origin
(method git-fetch)
(uri (git-reference
(url "https://git.sr.ht/~adnano/wmenu")
- (commit version)))
+ (commit "12b8f83be447379eded03c6109fe944945cd48aa")))
(file-name (git-file-name name version))
(sha256
(base32
- "0wjn68r5cx4zvw7sby6sk2ip5h4fn0jbgb1nasm9nsgjpv63pnpm"))))
+ "06fgvss3grihm3a1g6pj99rvjq2y2p496gkr2ahcnia7vn0wpc6y"))))
(build-system meson-build-system)
(native-inputs (append (if (%current-target-system)
;; for wayland-scanner
A
A
Arnaud Daby-Seesaram wrote on 5 Oct 19:02 +0200
(name . pelzflorian (Florian Pelz))(address . pelzflorian@pelzflorian.de)
877camv5yk.fsf@nanein.fr
Hello Florian,

Toggle quote (5 lines)
> I’d welcome if you, Arnaud, sent a patch calling your sway-menu script.
>
> Also I’d be happy if more careful commiters would push it; I prefer to
> restrict my commits to translation updates.

I will proof-read and re-test the whole patch soon, hoping to avoid
additional careless bugs on my end.

Also: given that you assisted me quite a lot, do you want me to add a
line in the commit message to express that you helped me write the patch
(such as "This patch was co-authored with Florian Pelz.", as in Guix
commit 9371cf2138711ea7305951d82c5cf0b36ac4d6f1)?

I will send a v8 as soon as I have both seen your answer and proof-read
the patch.
NB: I think that the v8 can be the last version of the patch. Thank you
for your help and for your patience :)!


Toggle quote (2 lines)
> Sorry for having proposed compiled-file previously.

No problem. I actually meant `program-file' instead of `computed-file'
(which was incorrectly used in my previous email). This way, the
lowered object in the store will be executable, allowing to define the
menu directly like this¹:

Toggle snippet (5 lines)
(define %sway-default-variables
`([...]
(menu . ,sway-menu)))

¹: In the next version of the patch, I allow any file-like object in
`string-ish' instead of file-append objects only, so that Sway
variables can be bound to anything that can be lowered into a file
(in additions to strings and G-expressions).


Toggle quote (5 lines)
> At first I had thought a compiled sway-menu.go would be appropriate,
> created in a computed-file, which invokes `guild compile` on the .scm
> code, but apparently this is not useful. I do not know enough here
> and gnu/services/shepherd.scm does it in the scm->go procedure.

Thank you for the pointer, `scm->go' is an interesting function.
I experimented and bit and was able to compile the menu to byte-code
using a similar function. However, I do not know a way to compile to
native code in Guile. Hence, I will stick to `program-file'.


Toggle quote (10 lines)
> Anyway, some feedback:
>
>> (define (directory->files dir)
>> (define (executable-file? f)
>> ;; Cf. `(@@ (guix build utils) executable-file?)' for an
>> ;; explanation of `(zero? ...)'.
>
> This is a comment anyway, but one @ in (@ (guix build utils)
> executable-file?) would be enough, since the executable-file?
> predicate is exported.
Thx, fixed.

Toggle quote (7 lines)
>> (lambda (s)
>
> To reduce clutter in the wmenu suggestions more, I’d prefer
>
> (and=> (and (not (eq? (string-ref f 0) #\.))
> (stat f))
> (lambda (s)
Indeed, this is better.

Toggle quote (13 lines)
>> (not (or (zero? (logand (stat:mode s) #o100))
>> (eq? (stat:type s) 'directory))))))
>> (with-directory-excursion dir
>> (scandir "." executable-file?)))
>>
>> (let ((path (string-append (getenv "HOME")
>> "/.guix-home/profile/bin"))
>> (wmenu #$(file-append wmenu "/bin/wmenu"))
>> (swaymsg #$(file-append sway "/bin/swaymsg")))
>> (receive (from to pid)
>> ((@@ (ice-9 popen) open-process) OPEN_BOTH wmenu)
>
> Better use @ instead of @@.
Unfortunately, `open-process' is not exported in `(ice-9 popen)', so I
kept @@.


Toggle quote (15 lines)
>> (for-each
>> (lambda (c) (format to "~a~%" c))
>> (directory->files path))
>> (close to)
>> (let ((choice (read-line from)))
>> (close from)
>> (waitpid pid)
>> (execl swaymsg swaymsg "exec"
>> (string-append path "/" choice))))))))
>
> Even though I like to get suggestions only for
> ~/.guix-home/profile/bin, if you do not prepend path, [...]
> then it will remain possible to write shell commands in wmenu [...]
> to run apps without installing them.

Yes; I removed the string-append here. (As ~/.guix-home/profile/bin is
supposed to be in the path, this should work properly).


Toggle quote (11 lines)
> Since you told me about wmenu-run, I also locally updated wmenu [1]
> and tested the menu config
>
> (menu . ,#~(string-append
> #$wmenu "/bin/wmenu-run"))
>
> which would also work, but in my opinion the suggestions are better
> when tied to .guix-home/profile. The wmenu-run does not use exec but
> a protocol called XDG_ACTIVATION_TOKEN. But I do not see an advantage
> to it. It behaves like always.

It is nice that this works too.
NB: if you want, you can use `(file-append pkg "stuff")' instead of
`#~(string-append #$pkg "stuff")'.

I do not know much about the XDG_ACTIVATION stuff; only that it has to
do with focused clients on Wayland IIRC. In my menu, I use `swaymsg
exec -- [command]', which takes care of a few things as well, as
explained below.

Toggle snippet (3 lines)
Note: pass the final command to swaymsg so that the resulting window can
be opened on the original workspace that the command was run on.
Source: commit c3353bb27317d294a91a8accec9a554ea392de04 of Sway. It
explains why the menu is piped to 'swaymg exec --'. (I have added the
"--" argument in the v8).

Toggle quote (2 lines)
> Also one more thing, in the commit message, you meant to write
> flatmap instead of flatten.
Indeed, thx.


Best regards,

--
Arnaud
-----BEGIN PGP SIGNATURE-----

iQJEBAEBCgAuFiEEMgqfJ4U0fby1t860ojLKXoMTiAwFAmcBcRQQHGRzLWFjQG5h
bmVpbi5mcgAKCRCiMspegxOIDC/AEACVkEc2PL7Q9LsaegS955SdM5QxwazAEe9F
n9Q/DsZ85Yk36IzGHIWc0T4Z/BySv2X9waQhjRYDsLSZAQzDSl1Skf5KhHlKPbrV
JwpMG6t4DN0dHMetz1wS+tjsRr7F4f1kNKGtXWO/ZYxfUP3M3jm2RT7IFr0547aL
nWv5dna5L3mL3Funq7J06Batqj5+flPRaBjJBSRZq723TTmgEgeVC5R809YIaod9
MAu1eFsl5+8h2OHUlJSMAZE0WLWcOi7u9SZTImm5kP7mhDD3uzCOBp/rIgfslgoj
tVqjeaCEOA54BEoNbiGV2sVTziD01gMwg++f0CwXO/BCgyEGZNIveVEXSprfo2DZ
G5k8X8Vh1fBhmRtXBFbaVKQ2iI8ubQbl7Odz39YnONBlfHybW0U1atu8yQfx0s05
MpjwWpzwHChRuFtTuq4iHXdrIavC5CblqBVltSX4EyaY0kxErmixe61IKgJ1J17d
oAkVtSEI5A6DeNgAOOofMdpT+tMQtqb0zUuQNYa+Ef47U24r4+4m+QtDYiM4pGIX
8Y1wIGDSTr/zNy6vtEp/4BmXTr0E1jZduCzXrsrZTjqtG8QpqkLDNVkWKcvyi9eD
XNN5gAW1m01pDhAbiig9F2aBH9JZQEj7+Hp6rrTcT+tR2YAKbRuFsWwVRsx7z8Id
OBjuBhM9Iw==
=hS73
-----END PGP SIGNATURE-----

P
P
pelzflorian (Florian Pelz) wrote on 6 Oct 10:15 +0200
(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)
8734l94pga.fsf@pelzflorian.de
Thank you Arnaud for this mountain of work.

Arnaud Daby-Seesaram <ds-ac@nanein.fr> writes:
Toggle quote (4 lines)
> Also: given that you assisted me quite a lot, do you want me to add a
> line in the commit message to express that you helped me write the
> patch

Not for my review; this would be unusual.

Normally scm->go is probably unneeded here, because guile will find the compiled
.go file. However program-file seems to add --no-auto-compile. Not
sure now.

Toggle quote (2 lines)
> NB: I think that the v8 can be the last version of the patch.

Otherwise yes, though I would prefer if another committer read it
again and pushed it.

Another more thing. I try (bar (sway-bar)), but it prints an empty bar
configuration to .config/sway/config. In patch 6, you added
no-serialization. Did this break it?

Regards,
Florian
A
A
Arnaud Daby-Seesaram wrote on 6 Oct 11:05 +0200
(name . pelzflorian (Florian Pelz))(address . pelzflorian@pelzflorian.de)
87wmily52c.fsf@nanein.fr
Hi Florian,

"pelzflorian (Florian Pelz)" <pelzflorian@pelzflorian.de> writes:
Toggle quote (1 lines)
> Thank you Arnaud for this mountain of work.
With pleasure :).

Toggle quote (6 lines)
> Arnaud Daby-Seesaram <ds-ac@nanein.fr> writes:
>> Also: given that you assisted me quite a lot, do you want me to add a
>> line in the commit message to express that you helped me write the
>> patch
>
> Not for my review; this would be unusual.
Noted.

Toggle quote (3 lines)
> Normally scm->go is probably unneeded here, because guile will find the compiled
> .go file. However program-file seems to add --no-auto-compile. Not
> sure now.
I do not know why the flag --no-auto-compile is passed either.

Toggle quote (4 lines)
> Another more thing. I try (bar (sway-bar)), but it prints an empty bar
> configuration to .config/sway/config. In patch 6, you added
> no-serialization. Did this break it?

Hmmm, I am not sure.
It is normal that `(sway-bar)' is an empty bar configuration (as all bar
fields are now optional or empty by default). However, no configuration
block should appear in the serialised configuration in this case.

Maybe you need to pass --fresh-auto-compile to Guile when executing your
test scripts (so that it does not trust its cache). I realised once
that when updating the module `(gnu home services sway)', my test files
would not be recompiled and old serialisation functions were used.

In v6, `serialize-bar' looks like

Toggle snippet (6 lines)
(add-block* "bar [bar name]"
[possibly empty list L1]
[...]
[possibly empty list Ln])

Thus, if all lists `Li' are empty, this should not add any line to the
configuration file. (Except for the header "# Bar configuration.[...]",
as it is added in the main serialisation function).

In my current version of the patch, the header is also removed if
nothing follows. Currently (on my local files), `(sway-configuration
(bar (sway-bar)))' is serialised into the following:

Toggle snippet (22 lines)
####################################
### Auto-generated configuration ###
####################################
# DO NOT EDIT MANUALLY.

# Variables.
############
[ ... default variables ... ]

# Keybindings.
##############
[ ... default keybindings ...]

# Gestures.
###########
[ ... default gestures ...]

# Programs to execute (at startup).
###################################
[ ... default startup programs ...]

and `(sway-configuration (bar (sway-bar (hidden-state 'show))))' is
serialised into:

Toggle snippet (28 lines)
####################################
### Auto-generated configuration ###
####################################
# DO NOT EDIT MANUALLY.

# Variables.
############
[ ... ]

# Bar configuration.
####################
bar bar0 {
hidden_state show
}

# Keybindings.
##############
[ ... ]

# Gestures.
###########
[ ... ]

# Programs to execute (at startup).
###################################
[ ... ]

So at least, the v8 should behave as expected.


Best regards,

--
Arnaud
-----BEGIN PGP SIGNATURE-----

iQJEBAEBCgAuFiEEMgqfJ4U0fby1t860ojLKXoMTiAwFAmcCUtwQHGRzLWFjQG5h
bmVpbi5mcgAKCRCiMspegxOIDCjBD/9+bPkvTbIt6eF8km+cT0erkoF2EFdJ2x1a
/CC/1y/cDHnZXOYlIZi5FC7I8Mg3uURful7ExtS1Q0pDcMtOrX8rbZwTvb/fRneB
UtfISHkrPDnLHkUiEkbpVbByCmu2Z15Y4Uts5JPLufpX09pUkfI4ez7p71RUGxV5
MaRWvnN1O18ZnXxqWosLGyJbFm0yX7qE8L3S7qkE60yrbF6f4KdCrocNavGMC0Jf
+so3i/lTK791LBZ6WJRGsKiVCiX9oPqhaDB69AZ8EuPBbxdDWs8ifDwgwfensqBT
+7YGr6uO7sa1Vegy5bS5iQkT/bwF2hICQH0Y6U1Sapx3TDRqjy7Q3AWD99R8Pkt+
J7NyMJnKcQVY6SVtKynlcccoq+Lrm99zH3lRzJEn/dknv+epTAwgR4bsePUPD4SA
qFFxmRN4F5zp6Zwhjss79iK5AyTo3DSiNp0jpgB/lYw4LaBXuYNq8VsA75m6UtQN
EkZgp+9fIGJsQatbFYLAxA04RoOtTTOCznS0WHLBDRujeOKpe0jRnALn/RBrrflU
Jhdb8L1ZdwwFJAeNgsBZ2PRCCwfzdEtUbsVFrZtkrB0fObS2REXyW4V2z/HzpxTk
guDc20B2W3hNq8hQNaJKspVtGK7po60EM6EuUaw9F/37T07jm/aJQl8biCVukpK8
IN1Rqq1FEw==
=8x6o
-----END PGP SIGNATURE-----

P
P
pelzflorian (Florian Pelz) wrote on 6 Oct 11:51 +0200
(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)
87r08ta7az.fsf@pelzflorian.de
Arnaud Daby-Seesaram <ds-ac@nanein.fr> writes:
Toggle quote (6 lines)
>> Normally scm->go is probably unneeded here, because guile will find the compiled
>> .go file. However program-file seems to add --no-auto-compile. Not
>> sure now.
> I do not know why the flag --no-auto-compile is passed either.
>

I am not sure if program-file or scheme-file should be preferred.

Toggle quote (8 lines)
>> Another more thing. I try (bar (sway-bar)), but it prints an empty bar
>> configuration to .config/sway/config. In patch 6, you added
>> no-serialization. Did this break it?
>
> Hmmm, I am not sure.
> It is normal that `(sway-bar)' is an empty bar configuration (as all bar
> fields are now optional or empty by default).

Ooops, the identifier is not written, of course.

(bar (sway-bar
(position 'top)))

is fine. Not sure what defaults are best.

Arnaud Daby-Seesaram <ds-ac@nanein.fr> writes:
Toggle quote (8 lines)
>>> (receive (from to pid)
>>> ((@@ (ice-9 popen) open-process) OPEN_BOTH wmenu)
>>
>> Better use @ instead of @@.
> Unfortunately, `open-process' is not exported in `(ice-9 popen)', so I
> kept @@.
>

Not sure if exported open-pipe* would be better. open-process is
checked in guile tests, but not exported, that is right. But maybe a
red flag not to use it.

Toggle quote (4 lines)
> It is nice that this works too.
> NB: if you want, you can use `(file-append pkg "stuff")' instead of
> `#~(string-append #$pkg "stuff")'.

Oops yes.

Regards,
Florian
A
A
Arnaud Daby-Seesaram wrote on 6 Oct 12:44 +0200
(name . pelzflorian (Florian Pelz))(address . pelzflorian@pelzflorian.de)
87set9y0hz.fsf@nanein.fr
Hi,

"pelzflorian (Florian Pelz)" <pelzflorian@pelzflorian.de> writes:
Toggle quote (9 lines)
> Arnaud Daby-Seesaram <ds-ac@nanein.fr> writes:
>>> Normally scm->go is probably unneeded here, because guile will find the compiled
>>> .go file. However program-file seems to add --no-auto-compile. Not
>>> sure now.
>> I do not know why the flag --no-auto-compile is passed either.
>>
>
> I am not sure if program-file or scheme-file should be preferred.

I think that in our use case, program-file is better, because it does
not require to call Guile explicitly in the Sway configuration (all we
care about is that the serialised script "behaves like a menu program").


Toggle quote (15 lines)
>>> Another more thing. I try (bar (sway-bar)), but it prints an empty bar
>>> configuration to .config/sway/config. In patch 6, you added
>>> no-serialization. Did this break it?
>>
>> Hmmm, I am not sure.
>> It is normal that `(sway-bar)' is an empty bar configuration (as all bar
>> fields are now optional or empty by default).
>
> Ooops, the identifier is not written, of course.
>
> (bar (sway-bar
> (position 'top)))
>
> is fine. Not sure what defaults are best.

Yes, this is arbitrary in my code. Rationale behind my choice:

At first, I wanted to make the default value match that of the default
Sway configuration file. However, this would force some fields to be
mandatory (namely status-command, colors and position). As users may
not want to specify these fields in their Sway configuration,
I preferred to make everything optional.

Toggle quote (13 lines)
> Arnaud Daby-Seesaram <ds-ac@nanein.fr> writes:
>>>> (receive (from to pid)
>>>> ((@@ (ice-9 popen) open-process) OPEN_BOTH wmenu)
>>>
>>> Better use @ instead of @@.
>> Unfortunately, `open-process' is not exported in `(ice-9 popen)', so I
>> kept @@.
>>
>
> Not sure if exported open-pipe* would be better. open-process is
> checked in guile tests, but not exported, that is right. But maybe a
> red flag not to use it.

I first tried to use (open-pipe wmenu OPEN_BOTH). However, I needed
to close the port to wmenu before reading its output. I do not know how
to do that with `open-pipe'.


Best,

--
Arnaud
-----BEGIN PGP SIGNATURE-----

iQJEBAEBCgAuFiEEMgqfJ4U0fby1t860ojLKXoMTiAwFAmcCafgQHGRzLWFjQG5h
bmVpbi5mcgAKCRCiMspegxOIDOQGD/0eBMu1zXYKMPgzz6z5WjjGqYy9kcoTOgEX
a6blPNGMR4VvypjQEZ3omNNJLCJOy7TF1I/lFwURSldBZCQBUV9niRfzMJRWhkbS
4zb7z269Q1otirbeBG64JtqA8p7eQcAEQg8chxREW+vIA9QquGpz0eKG9pklhGS2
A8BShbIFxTMBQrGnqvQvDYTcyC/see1RykC5+/5+GY9LUWRFtZR4ouBV76EKOLld
UueY7b8jZgpbBRx8/n5658i7YCbCQhJ3FnFoYw1mNgYoY2INj/wO9ImnDnXkbSV1
dlA9GBTb+FIfV2Rfsw0HuAU6bElft0a7IlkIgvWqDYzvA9EELWrjewso8BDmVCvA
BWJ/f34hJi1jN4pgQVJ6Sv5MkWUIZo/G2JX1HQZnV/BJ4xCLywH1yBI+ur3OwePS
GX9Hm3iUQCiEegTCi0wePQ9sfkIF1wx5NsVBkpoZ2uT7MnWEnUbDUi/FEzwdABCs
iJzCA3brRJ/mAxYSoRcIlvMWDZv2o0/SvXtfs3SwTrl3jfbTEeopLa/U1vwg2Wme
bCGgs57lPhdwws605QzmKOfEd9cDnOsHIPGFdW8NPD409kVmWWcA/QclYp8P8Rn9
Kfhk7+SZNqX08nq+AAb9sG87GdHkq3ATIgtsFOG19RlnHunfjg4JPG89xHvwklsT
brRS1MHRdA==
=jTAE
-----END PGP SIGNATURE-----

P
P
pelzflorian (Florian Pelz) wrote on 8 Oct 18:39 +0200
(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)
87cyka1rda.fsf@pelzflorian.de
Hello Arnaud. Please excuse the long delay.

Arnaud Daby-Seesaram <ds-ac@nanein.fr> writes:
Toggle quote (7 lines)
> "pelzflorian (Florian Pelz)" <pelzflorian@pelzflorian.de> writes:
>> I am not sure if program-file or scheme-file should be preferred.
>
> I think that in our use case, program-file is better, because it does
> not require to call Guile explicitly in the Sway configuration (all we
> care about is that the serialised script "behaves like a menu program").

Not sure, because program-file calls guile with --no-auto-compile.
Maybe someone else has an opinion. Also it does not really matter.


Toggle quote (17 lines)
>>>> Another more thing. I try (bar (sway-bar)), but it prints an empty bar
>>>> configuration to .config/sway/config. In patch 6, you added
>>>> no-serialization. Did this break it?
>[…]
>> (bar (sway-bar
>> (position 'top)))
>>
>> is fine. Not sure what defaults are best.
>
> Yes, this is arbitrary in my code. Rationale behind my choice:
>
> At first, I wanted to make the default value match that of the default
> Sway configuration file. However, this would force some fields to be
> mandatory (namely status-command, colors and position). As users may
> not want to specify these fields in their Sway configuration,
> I preferred to make everything optional.

I agree to better keep the sway-bar record simple. Maybe a more
complete sway-bar should be the default value for bar rather than
optional, because it is what upstream does, although then I would
disagree with Hilton (?) and actually I prefer no bar.


Toggle quote (20 lines)
>> Arnaud Daby-Seesaram <ds-ac@nanein.fr> writes:
>>>>> (receive (from to pid)
>>>>> ((@@ (ice-9 popen) open-process) OPEN_BOTH wmenu)
>>>>
>>>> Better use @ instead of @@.
>>> Unfortunately, `open-process' is not exported in `(ice-9 popen)', so I
>>> kept @@.
>>>
>>
>> Not sure if exported open-pipe* would be better. open-process is
>> checked in guile tests, but not exported, that is right. But maybe a
>> red flag not to use it.
>
> I first tried to use (open-pipe wmenu OPEN_BOTH). However, I needed
> to close the port to wmenu before reading its output. I do not know how
> to do that with `open-pipe'.
>
>
> Best,

In vain I tried rewriting code to use open-pipe* until I looked at the
Toggle quote (11 lines)
> static void read_items(struct menu *menu) {
> char buf[sizeof menu->input];
> while (fgets(buf, sizeof buf, stdin)) {
> char *p = strchr(buf, '\n');
> if (p) {
> *p = '\0';
> }
> menu_add_item(menu, strdup(buf), false);
> }
> }

Well, I guess the port must be closed or wmenu does not leave the while
loop. No other way. But perhaps use pipeline from (ice-9 popen), which
is public, unlike open-process.
Toggle diff (38 lines)
diff --git a/home-configuration.scm b/home-configuration.scm
index b961f84..c7eed63 100644
--- a/home-configuration.scm
+++ b/home-configuration.scm
@@ -41,10 +41,12 @@
(scheme-file
"sway-menu.scm"
#~(begin
- (use-modules (ice-9 receive)
+ (use-modules (ice-9 popen)
+ (ice-9 receive)
(ice-9 rdelim)
(ice-9 ftw)
- (guix build utils))
+ (guix build utils)
+ (srfi srfi-1))
(define (directory->files dir)
(define (executable-file? f)
@@ -62,15 +64,15 @@
"/.guix-home/profile/bin"))
(wmenu #$(file-append wmenu "/bin/wmenu"))
(swaymsg #$(file-append sway "/bin/swaymsg")))
- (receive (from to pid)
- ((@@ (ice-9 popen) open-process) OPEN_BOTH wmenu)
+ (receive (from to pids)
+ (pipeline `((,wmenu)))
(for-each
(lambda (c) (format to "~a~%" c))
(directory->files path))
(close to)
(let ((choice (read-line from)))
(close from)
- (waitpid pid)
+ (waitpid (first pids))
(execl swaymsg swaymsg "exec"
;(string-append path "/" choice)
choice)))))))
Could you send v8?

Regards,
Florian
A
A
Arnaud Daby-Seesaram wrote on 9 Oct 00:33 +0200
[PATCH v8] home: services: Add 'home-sway-service-type'.
(address . 72714@debbugs.gnu.org)
20241008223645.19674-1-ds-ac@nanein.fr
* gnu/home/services/sway.scm: New file.
(home-sway-service-type): New variable.
(sway-configuration->file): New procedure.
(sway-configuration): New configuration record.
(sway-bar): New configuration record.
(sway-output): New configuration record.
(sway-input): New configuration record.
(point): New configuration record.
(sway-color): New configuration record.
(sway-border-color): New configuration record.
(sway-mode): New configuration record.
(flatmap): New procedure.
* gnu/local.mk: Add gnu/home/services/sway.scm.
* doc/guix.texi (Sway window manager): New node to document the above changes.
---
Hello Florian,

Please find below the v8 of the patch.

Main changes since the v7 and our last emails :

• I no longer call make-string once per line,

• I serialize the tap field of input (I forgot it before),

• I have added the resize mode of Sway in the default modes,

• I have swapped the sections "default values" and "definition of
configuration records" in sway.scm so that I could define
%sway-default-modes,

• I have proof-read the code and documentation,

• I have re-tested the code on example configurations (and have
hopefully caught all remaining small bugs/oversight).


Toggle quote (2 lines)
> Please excuse the long delay.

No worries; it has only been two days :).

Toggle quote (4 lines)
> Well, I guess the port must be closed or wmenu does not leave the
> while loop. No other way. But perhaps use pipeline from (ice-9
> popen), which is public, unlike open-process.

As suggested, I now use `pipeline'. The menu script also makes sure that
the output of wmenu is not null before trying to execute it.


Best regards,

doc/guix.texi | 406 +++++++++++++++++
gnu/home/services/sway.scm | 878 +++++++++++++++++++++++++++++++++++++
gnu/local.mk | 1 +
3 files changed, 1285 insertions(+)
create mode 100644 gnu/home/services/sway.scm

Toggle diff (524 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index 52e36e4354..127219d25f 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -130,6 +130,7 @@ Copyright @copyright{} 2024 Richard Sent@*
Copyright @copyright{} 2024 Dariqq@*
Copyright @copyright{} 2024 Denis 'GNUtoo' Carikli@*
Copyright @copyright{} 2024 Fabio Natali@*
+Copyright @copyright{} 2024 Arnaud Daby-Seesaram@*
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -460,6 +461,7 @@ Home Services
* Mail: Mail Home Services. Services for managing mail.
* Messaging: Messaging Home Services. Services for managing messaging.
* Media: Media Home Services. Services for managing media.
+* Sway: Sway window manager. Setting up the Sway configuration.
* Networking: Networking Home Services. Networking services.
* Miscellaneous: Miscellaneous Home Services. More services.
@@ -45196,6 +45198,7 @@ services)}.
* Mail: Mail Home Services. Services for managing mail.
* Messaging: Messaging Home Services. Services for managing messaging.
* Media: Media Home Services. Services for managing media.
+* Sway: Sway window manager. Setting up the Sway configuration.
* Networking: Networking Home Services. Networking services.
* Miscellaneous: Miscellaneous Home Services. More services.
@end menu
@@ -47110,6 +47113,409 @@ kodi} for more information.
@end table
@end deftp
+@node Sway window manager
+@subsection Sway window manager
+
+@cindex sway, Home Service
+@cindex sway, configuration
+The @code{(gnu home services sway)} module provides
+@code{home-sway-service-type}, a home service to configure the
+@uref{https://github.com/swaywm/sway,Sway window manager for Wayland} in
+a declarative way.
+
+Here is an example of a service and its configuration that you could add
+to the @code{services} field of your @code{home-environment}:
+
+@lisp
+(service home-sway-service-type
+ (sway-configuration
+ (gestures
+ '((swipe:3:down . "move to scratchpad")
+ (swipe:3:up . "scratchpad show")))
+ (outputs
+ (list (sway-output
+ (identifier '*)
+ (background (file-append sway
+ "\
+/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png")))))))
+@end lisp
+
+The above example describes a Sway configuration in which
+@itemize
+@item
+all monitors use a particular wallpaper whose @file{.png} is provided by
+the @code{sway} package;
+@item
+swiping down (resp.@: up) with three fingers moves the active window to
+the scratchpad (resp.@: shows/hides the scratchpad).
+@end itemize
+
+@quotation Note
+This home service only sets up the configuration file and profile
+packages for Sway. It does @emph{not} start Sway in any way. If you
+want to do so, you might be interested in using
+@code{greetd-wlgreet-sway-session} instead.
+
+The function @code{sway-configuration->file} defined below can be used
+to provide the value for the @emph{optional} @code{sway-configuration}
+field of @code{greetd-wlgreet-sway-session}.
+@end quotation
+
+@deffn {Procedure} sway-configuration->file config
+This function takes one argument @code{config}, which must be a
+@code{sway-configuration} record (defined below), and returns a
+file-like object representing the serialized configuration.
+@end deffn
+
+@defvar home-sway-service-type
+This is a home service type to set up Sway. It takes care of:
+@itemize
+@item
+providing a @file{~/.config/sway/config} file,
+@item
+adding Sway-related packages to your profile.
+@end itemize
+@end defvar
+
+@deftp {Data Type} sway-configuration
+This configuration record describes the Sway configuration
+(see@ @cite{sway(5)}). Available fields are:
+
+@table @asis
+@item @code{variables} (default: @code{%sway-default-variables})
+The value of this field is an association list in which keys are symbols
+and values are either strings, G-expressions or file-like objects
+(@pxref{G-Expressions}).
+
+Example:
+@lisp
+(variables `((mod . "Mod4") ; string
+ (term ; file-append
+ . ,(file-append foot "/bin/foot"))
+ (Term ; G-expression
+ . ,#~(string-append #$foot "/bin/foot"))))
+@end lisp
+
+@quotation Note
+Default keybindings assume the existence of variables named @code{$mod},
+@code{$left}, @code{$right}, @code{$up} and @code{$down}. If you choose
+not to define these variables, make sure to remove keybindings referring
+to them.
+@end quotation
+
+@item @code{keybindings} (default: @code{%sway-default-keybindings})
+This field describes keybindings for the @emph{default} mode. The value
+is an association list: keys are symbols and values are either strings
+or G-expressions.
+
+The following snippet launches the terminal when pressing @kbd{$mod+t}
+and @kbd{$mod+Shift+t} (assuming that a variable @code{$term} is
+defined):
+@lisp
+`(($mod+t . ,#~(string-append "exec " #$foot "/bin/foot"))
+ ($mod+Shift+t . "exec $term"))
+@end lisp
+
+@item @code{gestures} (default: @code{%sway-default-gestures})
+Similar to the previous field, but for finger-gestures.
+
+The following snippet allows to navigate through workspaces by swiping
+right and left with three fingers:
+@lisp
+'((swipe:3:right . "workspace next_on_output")
+ (swipe:3:left . "workspace prev_on_output"))
+@end lisp
+
+@item @code{packages} (default: @code{%sway-default-packages})
+This field describes a list of packages to add to the user profile. At
+the moment, the default value only adds @code{sway} to the profile.
+
+@item @code{inputs} (default: @code{'()})
+List of @code{sway-input} configuration records (described below).
+
+@item @code{outputs} (default: @code{'()})
+List of @code{sway-output} configuration records (described below).
+
+@item @code{bar} (optional @code{sway-bar} record)
+Optional @code{sway-bar} record (described below) to configure a Sway
+bar.
+
+@item @code{modes} (default: @code{%sway-default-modes})
+List of @code{sway-mode} records (described below) to add modes to the
+Sway configuration. The default value @code{%sway-default-modes} adds
+the ``resize'' mode of the default Sway configuration (as described
+below).
+
+@item @code{startup+reload-programs} (default: @code{'()})
+Programs to execute at startup time @emph{and} after every configuration
+reload. The value of this field is a list of strings, G-expressions or
+file-append objects (@pxref{G-Expressions}).
+
+@item @code{startup-programs} (default: @code{%sway-default-execs})
+Programs to execute at startup time. As above, values of this field are
+a list of strings, G-expressions or file-append objects.
+
+The default value, @code{%sway-default-execs}, executes @code{swayidle}
+in order to lock the screen after 5@ minutes of inactivity (displaying a
+background distributed with Sway) and turn the screen off after 10@
+minutes of inactivity.
+
+@item @code{extra-content} (default: @code{'()})
+Lines to add to the configuration file. The value of this field is a
+list of strings or G-expressions.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-input
+@code{sway-input} records describe input blocks (see@
+@cite{sway-input(5)}). For example, the following snippet makes all
+keyboards use a french layout, in which @kbd{capslock} has been remaped
+to @kbd{ctrl}:
+@lisp
+(sway-input (identifier "type:keyboard")
+ (layout
+ (keyboard-layout "fr" #:options '("ctrl:nocaps"))))
+@end lisp
+
+Available fields for @code{sway-input} configuration records are:
+
+@table @asis
+@item @code{identifier} (default: @code{'*})
+Identifier of the input. The field accepts symbols and strings. If the
+@code{identifier} is a symbol, it is inserted as is; if it is a string,
+it will be quoted in the configuration file.
+
+@item @code{layout} (optional @code{<keyboard-layout>} record)
+Keyboard specific option. Field specifying the layout to use for the
+input. The value must be a @code{<keyboard-layout>} record
+(@pxref{Keyboard Layout}).
+
+@quotation Note
+@code{(gnu home services sway)} does not re-export the
+@code{keyboard-layout} procedure.
+@end quotation
+
+@item @code{disable-while-typing} (optional boolean)
+If @code{#t} (resp.@: @code{#f}) enables (resp.@: disables) the
+``disable while typing'' option for this input.
+
+@item @code{disable-while-trackpointing} (optional boolean)
+If @code{#t} (resp.@: @code{#f}), enables (resp.@: disables) the
+``disable while track-pointing'' option for this input.
+
+@item @code{tap} (optional boolean)
+Enables or disables the ``tap'' option, which allows clicking by tapping
+on a touchpad.
+
+@item @code{extra-content} (default: @code{'()})
+Lines to add to the input block. The value of this field must a list
+whose elements are either strings or G-expressions.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-output
+@code{sway-output} records describe Sway outputs (see@
+@cite{sway-output(5)}). Available fields are:
+
+@table @asis
+@item @code{identifier} (default: @code{'*})
+Identifier of the monitor. The field accepts symbols and strings. If
+the @code{identifier} is a symbol, it is inserted as is; if it is a
+string, it will be quoted in the configuration file.
+
+@item @code{resolution} (optional string)
+This string defines the resolution of the monitor.
+
+@item @code{position} (optional)
+The (optional) value of this field must be a @code{point}.
+Example:
+@lisp
+(position
+ (point (x 1920)
+ (y 0)))
+@end lisp
+
+@item @code{background} (optional)
+The value of this field describes what wallpaper to use on this output.
+The field accepts the following types of values:
+@itemize
+@item
+a string,
+@item
+a G-expression,
+@item
+a file-like object,
+@item
+a pair. The first argument of this pair must be a string, a
+G-expression or a file-like object. The second element describes how
+the wallpaper will be displayed. It must be a symbol among
+@code{stretch}, @code{fill}, @code{fit}, @code{center} and @code{tile}.
+
+If the second element is not specified (@i{i.e.}@: when the value not a
+pair), the @code{fill} mode will be used.
+@end itemize
+
+@quotation Note
+In order to use an SVG file, you must have @code{librsvg} in your
+profile (@i{e.g.}@: by adding it in the @code{packages} field of
+@code{sway-configuration}).
+@end quotation
+
+@item @code{extra-content} (default: @code{'()})
+List defining additional lines to add to the output configuration block.
+Elements of the list must be either strings or G-expressions.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-border-color
+@table @code
+@item border
+Color of the border.
+@item background
+Color of the background.
+@item text
+Color of the text.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-color
+@table @asis
+@item @code{background} (optional string)
+Background color of the bar.
+
+@item @code{statusline} (optional string)
+Text color of the status line.
+
+@item @code{focused-background} (optional string)
+Background color of the bar on the currently focused monitor.
+
+@item @code{focused-statusline} (optional string)
+Text color of the statusline on the currently focused monitor.
+
+@item @code{focused-workspace} (optional @code{sway-border-color})
+Color scheme for focused workspaces.
+
+@item @code{active-workspace} (optional @code{sway-border-color})
+Color scheme for active workspaces.
+
+@item @code{inactive-workspace} (optional @code{sway-border-color})
+Color scheme for inactive workspaces.
+
+@item @code{urgent-workspace} (optional @code{sway-border-color})
+Color scheme for workspaces containing ``urgent windows''.
+
+@item @code{binding-mode} (optional @code{sway-border-color})
+Color scheme for the binding mode indicator.
+@end table
+@end deftp
+
+@deftp {Data Type} sway-bar
+Describes the Sway bar (see@ @cite{sway-bar(5)}).
+
+@table @asis
+@item @code{identifier} (default: @code{'bar0})
+Identifier of the bar. The value must be a symbol.
+
+@item @code{position} (optional)
+Specify the position of the bar. Accepted values are @code{'top} or
+@code{'bottom}.
+
+@item @code{hidden-state} (optional)
+Specify the apparence of the bar when it is hidden. Accepted values are
+@code{'hide} or @code{'show}.
+
+@item @code{binding-mode-indicator} (optional)
+Boolean enabling or disabling the binding mode indicator.
+
+@item @code{colors} (optional)
+An optional @code{sway-color} configuration record.
+
+@item @code{status-command} (default: @code{%sway-status-command})
+This field accept strings, G-expressions and executable file-like
+values. The default value is a command (string) that prints the date
+and time every second.
+
+Each line printed on @code{stdout} by this command (or script) will be
+displayed on the status area of the bar.
+
+Below are a few examples using:
+@itemize
+@item
+a string: @code{"while date +'%Y-%m-%d %X'; do sleep 1; done"},
+@item
+a G-exp:
+@lisp
+#~(string-append "while "
+ #$coreutils "/bin/date"
+ " +'%Y-%m-%d %X'; do sleep 1; done")
+@end lisp
+@item
+an executable file:
+@lisp
+(program-file
+ "sway-bar-status"
+ #~(begin
+ (use-modules (ice-9 format)
+ (srfi srfi-19))
+ (let loop ()
+ (let* ((date (date->string
+ (current-date)
+ "~d/~m/~Y (~a) • ~H:~M:~S")))
+ (format #t "~a~%~!" date)
+ (sleep 1)
+ (loop)))))
+@end lisp
+@end itemize
+
+@item @code{mouse-bindings} (default: @code{'()})
+This field accepts an associative list. Keys are integers describing
+mouse events. Values can either be strings or G-expressions.
+
+The module @code{(gnu home services sway)} exports constants
+@code{%ev-code-mouse-left}, @code{%ev-code-mouse-right} and
+@code{%ev-code-mouse-scroll-click} whose values are integers
+corresponding to left, right and scroll click respectively. For
+example, with @code{(mouse-bindings `((,%ev-code-mouse-left . "exec
+$term")))}, left clicks in the status bar open the terminal (assuming
+that the variable @code{$term} is bound to a terminal).
+@end table
+@end deftp
+
+@deftp {Data Type} sway-mode
+Describes a Sway mode (see@ @cite{sway(5)}). For example, the following
+snippet defines the resize mode of the default Sway configuration:
+@example
+(sway-mode
+ (mode-name "resize")
+ (keybindings
+ '(($left . "resize shrink width 10px")
+ ($right . "resize grow width 10px")
+ ($down . "resize grow height 10px")
+ ($up . "resize shrink height 10px")
+ (Left . "resize shrink width 10px")
+ (Right . "resize grow width 10px")
+ (Down . "resize grow height 10px")
+ (Up . "resize shrink height 10px")
+ (Return . "mode \"default\"")
+ (Escape . "mode \"default\""))))
+@end example
+
+@table @asis
+@item @code{mode-name} (default: @code{"default"})
+Name of the mode. This field accepts strings.
+
+@item @code{keybindings} (default: @code{'()})
+This field describes keybindings. The value is an association list:
+keys are symbols and values are either strings or G-expressions, as
+above.
+
+@item @code{mouse-bindings} (default: @code{'()})
+Ditto, but keys are mouse events (integers). Constants
+@code{%ev-code-mouse-*} described above can be used as helpers to define
+mouse bindings.
+@end table
+@end deftp
+
@node Networking Home Services
@subsection Networking Home Services
diff --git a/gnu/home/services/sway.scm b/gnu/home/services/sway.scm
new file mode 100644
index 0000000000..9401c80400
--- /dev/null
+++ b/gnu/home/services/sway.scm
@@ -0,0 +1,878 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2024 Arnaud Daby-Seesaram <ds-ac@nanein.fr>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix 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 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix 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 GNU Guix. If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu home services sway)
+ #:use-module (guix modules)
+ #:use-module (guix gexp)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-26)
+ #:use-module (ice-9 popen)
+ #:use-module (ice-9 format)
+ #:use-module (ice-9 match)
+ #:use-module (guix packages)
+ #:use-module (gnu system keyboard)
+ #:use-module (gnu services configuration)
+ #:use-module (gnu home services)
+ #:use-module (gnu packages wm)
+ #:use-module (gnu packages terminals)
+ #:export (;; Event codes
+ %ev-code-mouse-left
+ %ev-code-mouse-right
+ %ev-code-mouse-scroll-click
+
+ ;; Configuration records.
+ sway-configuration
+ sway-bar
+ sway-output
+ sway-input
+ point
+ sway-color
+ sway-border-color
+ home-sway-service-type
+ sway-configuration->file
+ sway-mode
+
+ ;; Default values.
+ %sway-default-variables
+ %sway-default-gestures
+ %sway-default-modes
+ %sway-default-keybindings
+ %sway-default-status-command
+ %sway-default-startup-programs
+ %sway-default-packages))
+
+;; Helper function.
+(define (flatmap f l)
+ (let loop ((lst (reverse l)) (acc '()))
+ (match lst
+ (() acc)
+ ((head . tail)
+ (let* ((h (f head))
+ (acc (append h acc)))
+ (loop tail acc))))))
+
+
+;;;
+;;; Definition of configurations.
+;;;
+
+(define (string-ish? s)
+ (or (gexp? s)
+ (file-like? s)
+ (string? s)))
+
+(define (string-or-gexp? s)
+ (or
This message was truncated. Download the full message here.
P
P
pelzflorian (Florian Pelz) wrote on 12 Oct 15:11 +0200
(name . Arnaud Daby-Seesaram)(address . ds-ac@nanein.fr)
87iktx79er.fsf@pelzflorian.de
Pushed as b64f7984a5e2aba04df72a92f0044e423efe77c6,
Change-Id: I880261570c5afdb795f2ce18bac2b9a5c898677f
with tiny changes.
Attachment: diff
I also reindented the commit message and put a line break because the
last line did not fit on my terminal.

Thank you greatly!

Regards,
Florian
Closed
?
Your comment

This issue is archived.

To comment on this conversation send an email to 72714@debbugs.gnu.org

To respond to this issue using the mumi CLI, first switch to it
mumi current 72714
Then, you may apply the latest patchset in this issue (with sign off)
mumi am -- -s
Or, compose a reply to this issue
mumi compose
Or, send patches to this issue
mumi send-email *.patch