diff options
| author | Arnaud Daby-Seesaram <ds-ac@nanein.fr> | 2024-10-09 00:33:41 +0200 |
|---|---|---|
| committer | Florian Pelz <pelzflorian@pelzflorian.de> | 2024-10-12 14:26:01 +0200 |
| commit | b64f7984a5e2aba04df72a92f0044e423efe77c6 (patch) | |
| tree | 6f7dd897f6924757ec9663935e2913443ba91c86 | |
| parent | b9ec6251bee8e4e500eb9291087fbf2018aca113 (diff) | |
home: services: Add 'home-sway-service-type'.
* 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.
Signed-off-by: Florian Pelz <pelzflorian@pelzflorian.de>
Change-Id: I880261570c5afdb795f2ce18bac2b9a5c898677f
| -rw-r--r-- | doc/guix.texi | 406 | ||||
| -rw-r--r-- | gnu/home/services/sway.scm | 870 | ||||
| -rw-r--r-- | gnu/local.mk | 1 |
3 files changed, 1277 insertions, 0 deletions
diff --git a/doc/guix.texi b/doc/guix.texi index 8f3b8ef6cdd..ddbff8bc235 100644 --- a/doc/guix.texi +++ b/doc/guix.texi | |||
| @@ -130,6 +130,7 @@ Copyright @copyright{} 2024 Richard Sent@* | |||
| 130 | Copyright @copyright{} 2024 Dariqq@* | 130 | Copyright @copyright{} 2024 Dariqq@* |
| 131 | Copyright @copyright{} 2024 Denis 'GNUtoo' Carikli@* | 131 | Copyright @copyright{} 2024 Denis 'GNUtoo' Carikli@* |
| 132 | Copyright @copyright{} 2024 Fabio Natali@* | 132 | Copyright @copyright{} 2024 Fabio Natali@* |
| 133 | Copyright @copyright{} 2024 Arnaud Daby-Seesaram@* | ||
| 133 | 134 | ||
| 134 | Permission is granted to copy, distribute and/or modify this document | 135 | Permission is granted to copy, distribute and/or modify this document |
| 135 | under the terms of the GNU Free Documentation License, Version 1.3 or | 136 | under the terms of the GNU Free Documentation License, Version 1.3 or |
| @@ -460,6 +461,7 @@ Home Services | |||
| 460 | * Mail: Mail Home Services. Services for managing mail. | 461 | * Mail: Mail Home Services. Services for managing mail. |
| 461 | * Messaging: Messaging Home Services. Services for managing messaging. | 462 | * Messaging: Messaging Home Services. Services for managing messaging. |
| 462 | * Media: Media Home Services. Services for managing media. | 463 | * Media: Media Home Services. Services for managing media. |
| 464 | * Sway: Sway window manager. Setting up the Sway configuration. | ||
| 463 | * Networking: Networking Home Services. Networking services. | 465 | * Networking: Networking Home Services. Networking services. |
| 464 | * Miscellaneous: Miscellaneous Home Services. More services. | 466 | * Miscellaneous: Miscellaneous Home Services. More services. |
| 465 | 467 | ||
| @@ -45210,6 +45212,7 @@ services)}. | |||
| 45210 | * Mail: Mail Home Services. Services for managing mail. | 45212 | * Mail: Mail Home Services. Services for managing mail. |
| 45211 | * Messaging: Messaging Home Services. Services for managing messaging. | 45213 | * Messaging: Messaging Home Services. Services for managing messaging. |
| 45212 | * Media: Media Home Services. Services for managing media. | 45214 | * Media: Media Home Services. Services for managing media. |
| 45215 | * Sway: Sway window manager. Setting up the Sway configuration. | ||
| 45213 | * Networking: Networking Home Services. Networking services. | 45216 | * Networking: Networking Home Services. Networking services. |
| 45214 | * Miscellaneous: Miscellaneous Home Services. More services. | 45217 | * Miscellaneous: Miscellaneous Home Services. More services. |
| 45215 | @end menu | 45218 | @end menu |
| @@ -47124,6 +47127,409 @@ kodi} for more information. | |||
| 47124 | @end table | 47127 | @end table |
| 47125 | @end deftp | 47128 | @end deftp |
| 47126 | 47129 | ||
| 47130 | @node Sway window manager | ||
| 47131 | @subsection Sway window manager | ||
| 47132 | |||
| 47133 | @cindex sway, Home Service | ||
| 47134 | @cindex sway, configuration | ||
| 47135 | The @code{(gnu home services sway)} module provides | ||
| 47136 | @code{home-sway-service-type}, a home service to configure the | ||
| 47137 | @uref{https://github.com/swaywm/sway,Sway window manager for Wayland} in | ||
| 47138 | a declarative way. | ||
| 47139 | |||
| 47140 | Here is an example of a service and its configuration that you could add | ||
| 47141 | to the @code{services} field of your @code{home-environment}: | ||
| 47142 | |||
| 47143 | @lisp | ||
| 47144 | (service home-sway-service-type | ||
| 47145 | (sway-configuration | ||
| 47146 | (gestures | ||
| 47147 | '((swipe:3:down . "move to scratchpad") | ||
| 47148 | (swipe:3:up . "scratchpad show"))) | ||
| 47149 | (outputs | ||
| 47150 | (list (sway-output | ||
| 47151 | (identifier '*) | ||
| 47152 | (background (file-append sway | ||
| 47153 | "\ | ||
| 47154 | /share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png"))))))) | ||
| 47155 | @end lisp | ||
| 47156 | |||
| 47157 | The above example describes a Sway configuration in which | ||
| 47158 | @itemize | ||
| 47159 | @item | ||
| 47160 | all monitors use a particular wallpaper whose @file{.png} is provided by | ||
| 47161 | the @code{sway} package; | ||
| 47162 | @item | ||
| 47163 | swiping down (resp.@: up) with three fingers moves the active window to | ||
| 47164 | the scratchpad (resp.@: shows/hides the scratchpad). | ||
| 47165 | @end itemize | ||
| 47166 | |||
| 47167 | @quotation Note | ||
| 47168 | This home service only sets up the configuration file and profile | ||
| 47169 | packages for Sway. It does @emph{not} start Sway in any way. If you | ||
| 47170 | want to do so, you might be interested in using | ||
| 47171 | @code{greetd-wlgreet-sway-session} instead. | ||
| 47172 | |||
| 47173 | The proceedure @code{sway-configuration->file} defined below can be used | ||
| 47174 | to provide the value for the @emph{optional} @code{sway-configuration} | ||
| 47175 | field of @code{greetd-wlgreet-sway-session}. | ||
| 47176 | @end quotation | ||
| 47177 | |||
| 47178 | @deffn {Procedure} sway-configuration->file config | ||
| 47179 | This procedure takes one argument @code{config}, which must be a | ||
| 47180 | @code{sway-configuration} record (defined below), and returns a | ||
| 47181 | file-like object representing the serialized configuration. | ||
| 47182 | @end deffn | ||
| 47183 | |||
| 47184 | @defvar home-sway-service-type | ||
| 47185 | This is a home service type to set up Sway. It takes care of: | ||
| 47186 | @itemize | ||
| 47187 | @item | ||
| 47188 | providing a @file{~/.config/sway/config} file, | ||
| 47189 | @item | ||
| 47190 | adding Sway-related packages to your profile. | ||
| 47191 | @end itemize | ||
| 47192 | @end defvar | ||
| 47193 | |||
| 47194 | @deftp {Data Type} sway-configuration | ||
| 47195 | This configuration record describes the Sway configuration | ||
| 47196 | (see@ @cite{sway(5)}). Available fields are: | ||
| 47197 | |||
| 47198 | @table @asis | ||
| 47199 | @item @code{variables} (default: @code{%sway-default-variables}) | ||
| 47200 | The value of this field is an association list in which keys are symbols | ||
| 47201 | and values are either strings, G-expressions or file-like objects | ||
| 47202 | (@pxref{G-Expressions}). | ||
| 47203 | |||
| 47204 | Example: | ||
| 47205 | @lisp | ||
| 47206 | (variables `((mod . "Mod4") ; string | ||
| 47207 | (term ; file-append | ||
| 47208 | . ,(file-append foot "/bin/foot")) | ||
| 47209 | (Term ; G-expression | ||
| 47210 | . ,#~(string-append #$foot "/bin/foot")))) | ||
| 47211 | @end lisp | ||
| 47212 | |||
| 47213 | @quotation Note | ||
| 47214 | Default keybindings assume the existence of variables named @code{$mod}, | ||
| 47215 | @code{$left}, @code{$right}, @code{$up} and @code{$down}. If you choose | ||
| 47216 | not to define these variables, make sure to remove keybindings referring | ||
| 47217 | to them. | ||
| 47218 | @end quotation | ||
| 47219 | |||
| 47220 | @item @code{keybindings} (default: @code{%sway-default-keybindings}) | ||
| 47221 | This field describes keybindings for the @emph{default} mode. The value | ||
| 47222 | is an association list: keys are symbols and values are either strings | ||
| 47223 | or G-expressions. | ||
| 47224 | |||
| 47225 | The following snippet launches the terminal when pressing @kbd{$mod+t} | ||
| 47226 | and @kbd{$mod+Shift+t} (assuming that a variable @code{$term} is | ||
| 47227 | defined): | ||
| 47228 | @lisp | ||
| 47229 | `(($mod+t . ,#~(string-append "exec " #$foot "/bin/foot")) | ||
| 47230 | ($mod+Shift+t . "exec $term")) | ||
| 47231 | @end lisp | ||
| 47232 | |||
| 47233 | @item @code{gestures} (default: @code{%sway-default-gestures}) | ||
| 47234 | Similar to the previous field, but for finger-gestures. | ||
| 47235 | |||
| 47236 | The following snippet allows to navigate through workspaces by swiping | ||
| 47237 | right and left with three fingers: | ||
| 47238 | @lisp | ||
| 47239 | '((swipe:3:right . "workspace next_on_output") | ||
| 47240 | (swipe:3:left . "workspace prev_on_output")) | ||
| 47241 | @end lisp | ||
| 47242 | |||
| 47243 | @item @code{packages} (default: @code{%sway-default-packages}) | ||
| 47244 | This field describes a list of packages to add to the user profile. At | ||
| 47245 | the moment, the default value only adds @code{sway} to the profile. | ||
| 47246 | |||
| 47247 | @item @code{inputs} (default: @code{'()}) | ||
| 47248 | List of @code{sway-input} configuration records (described below). | ||
| 47249 | |||
| 47250 | @item @code{outputs} (default: @code{'()}) | ||
| 47251 | List of @code{sway-output} configuration records (described below). | ||
| 47252 | |||
| 47253 | @item @code{bar} (optional @code{sway-bar} record) | ||
| 47254 | Optional @code{sway-bar} record (described below) to configure a Sway | ||
| 47255 | bar. | ||
| 47256 | |||
| 47257 | @item @code{modes} (default: @code{%sway-default-modes}) | ||
| 47258 | List of @code{sway-mode} records (described below) to add modes to the | ||
| 47259 | Sway configuration. The default value @code{%sway-default-modes} adds | ||
| 47260 | the ``resize'' mode of the default Sway configuration (as described | ||
| 47261 | below). | ||
| 47262 | |||
| 47263 | @item @code{startup+reload-programs} (default: @code{'()}) | ||
| 47264 | Programs to execute at startup time @emph{and} after every configuration | ||
| 47265 | reload. The value of this field is a list of strings, G-expressions or | ||
| 47266 | file-like objects (@pxref{G-Expressions}). | ||
| 47267 | |||
| 47268 | @item @code{startup-programs} (default: @code{%sway-default-execs}) | ||
| 47269 | Programs to execute at startup time. As above, values of this field are | ||
| 47270 | a list of strings, G-expressions or file-like objects. | ||
| 47271 | |||
| 47272 | The default value, @code{%sway-default-execs}, executes @code{swayidle} | ||
| 47273 | in order to lock the screen after 5@ minutes of inactivity (displaying a | ||
| 47274 | background distributed with Sway) and turn the screen off after 10@ | ||
| 47275 | minutes of inactivity. | ||
| 47276 | |||
| 47277 | @item @code{extra-content} (default: @code{'()}) | ||
| 47278 | Lines to add to the configuration file. The value of this field is a | ||
| 47279 | list of strings or G-expressions. | ||
| 47280 | @end table | ||
| 47281 | @end deftp | ||
| 47282 | |||
| 47283 | @deftp {Data Type} sway-input | ||
| 47284 | @code{sway-input} records describe input blocks (see@ | ||
| 47285 | @cite{sway-input(5)}). For example, the following snippet makes all | ||
| 47286 | keyboards use a French layout, in which @kbd{capslock} has been remapped | ||
| 47287 | to @kbd{ctrl}: | ||
| 47288 | @lisp | ||
| 47289 | (sway-input (identifier "type:keyboard") | ||
| 47290 | (layout | ||
| 47291 | (keyboard-layout "fr" #:options '("ctrl:nocaps")))) | ||
| 47292 | @end lisp | ||
| 47293 | |||
| 47294 | Available fields for @code{sway-input} configuration records are: | ||
| 47295 | |||
| 47296 | @table @asis | ||
| 47297 | @item @code{identifier} (default: @code{'*}) | ||
| 47298 | Identifier of the input. The field accepts symbols and strings. If the | ||
| 47299 | @code{identifier} is a symbol, it is inserted as is; if it is a string, | ||
| 47300 | it will be quoted in the configuration file. | ||
| 47301 | |||
| 47302 | @item @code{layout} (optional @code{<keyboard-layout>} record) | ||
| 47303 | Keyboard specific option. Field specifying the layout to use for the | ||
| 47304 | input. The value must be a @code{<keyboard-layout>} record | ||
| 47305 | (@pxref{Keyboard Layout}). | ||
| 47306 | |||
| 47307 | @quotation Note | ||
| 47308 | @code{(gnu home services sway)} does not re-export the | ||
| 47309 | @code{keyboard-layout} procedure. | ||
| 47310 | @end quotation | ||
| 47311 | |||
| 47312 | @item @code{disable-while-typing} (optional boolean) | ||
| 47313 | If @code{#t} (resp.@: @code{#f}) enables (resp.@: disables) the | ||
| 47314 | ``disable while typing'' option for this input. | ||
| 47315 | |||
| 47316 | @item @code{disable-while-trackpointing} (optional boolean) | ||
| 47317 | If @code{#t} (resp.@: @code{#f}), enables (resp.@: disables) the | ||
| 47318 | ``disable while track-pointing'' option for this input. | ||
| 47319 | |||
| 47320 | @item @code{tap} (optional boolean) | ||
| 47321 | Enables or disables the ``tap'' option, which allows clicking by tapping | ||
| 47322 | on a touchpad. | ||
| 47323 | |||
| 47324 | @item @code{extra-content} (default: @code{'()}) | ||
| 47325 | Lines to add to the input block. The value of this field must a list | ||
| 47326 | whose elements are either strings or G-expressions. | ||
| 47327 | @end table | ||
| 47328 | @end deftp | ||
| 47329 | |||
| 47330 | @deftp {Data Type} sway-output | ||
| 47331 | @code{sway-output} records describe Sway outputs (see@ | ||
| 47332 | @cite{sway-output(5)}). Available fields are: | ||
| 47333 | |||
| 47334 | @table @asis | ||
| 47335 | @item @code{identifier} (default: @code{'*}) | ||
| 47336 | Identifier of the monitor. The field accepts symbols and strings. If | ||
| 47337 | the @code{identifier} is a symbol, it is inserted as is; if it is a | ||
| 47338 | string, it will be quoted in the configuration file. | ||
| 47339 | |||
| 47340 | @item @code{resolution} (optional string) | ||
| 47341 | This string defines the resolution of the monitor. | ||
| 47342 | |||
| 47343 | @item @code{position} (optional) | ||
| 47344 | The (optional) value of this field must be a @code{point}. | ||
| 47345 | Example: | ||
| 47346 | @lisp | ||
| 47347 | (position | ||
| 47348 | (point (x 1920) | ||
| 47349 | (y 0))) | ||
| 47350 | @end lisp | ||
| 47351 | |||
| 47352 | @item @code{background} (optional) | ||
| 47353 | The value of this field describes what wallpaper to use on this output. | ||
| 47354 | The field accepts the following types of values: | ||
| 47355 | @itemize | ||
| 47356 | @item | ||
| 47357 | a string, | ||
| 47358 | @item | ||
| 47359 | a G-expression, | ||
| 47360 | @item | ||
| 47361 | a file-like object, | ||
| 47362 | @item | ||
| 47363 | a pair. The first argument of this pair must be a string, a | ||
| 47364 | G-expression or a file-like object. The second element describes how | ||
| 47365 | the wallpaper will be displayed. It must be a symbol among | ||
| 47366 | @code{stretch}, @code{fill}, @code{fit}, @code{center} and @code{tile}. | ||
| 47367 | |||
| 47368 | If the second element is not specified (@i{i.e.}@: when the value is not | ||
| 47369 | a pair), the @code{fill} mode will be used. | ||
| 47370 | @end itemize | ||
| 47371 | |||
| 47372 | @quotation Note | ||
| 47373 | In order to use an SVG file, you must have @code{librsvg} in your | ||
| 47374 | profile (@i{e.g.}@: by adding it in the @code{packages} field of | ||
| 47375 | @code{sway-configuration}). | ||
| 47376 | @end quotation | ||
| 47377 | |||
| 47378 | @item @code{extra-content} (default: @code{'()}) | ||
| 47379 | List defining additional lines to add to the output configuration block. | ||
| 47380 | Elements of the list must be either strings or G-expressions. | ||
| 47381 | @end table | ||
| 47382 | @end deftp | ||
| 47383 | |||
| 47384 | @deftp {Data Type} sway-border-color | ||
| 47385 | @table @code | ||
| 47386 | @item border | ||
| 47387 | Color of the border. | ||
| 47388 | @item background | ||
| 47389 | Color of the background. | ||
| 47390 | @item text | ||
| 47391 | Color of the text. | ||
| 47392 | @end table | ||
| 47393 | @end deftp | ||
| 47394 | |||
| 47395 | @deftp {Data Type} sway-color | ||
| 47396 | @table @asis | ||
| 47397 | @item @code{background} (optional string) | ||
| 47398 | Background color of the bar. | ||
| 47399 | |||
| 47400 | @item @code{statusline} (optional string) | ||
| 47401 | Text color of the status line. | ||
| 47402 | |||
| 47403 | @item @code{focused-background} (optional string) | ||
| 47404 | Background color of the bar on the currently focused monitor. | ||
| 47405 | |||
| 47406 | @item @code{focused-statusline} (optional string) | ||
| 47407 | Text color of the statusline on the currently focused monitor. | ||
| 47408 | |||
| 47409 | @item @code{focused-workspace} (optional @code{sway-border-color}) | ||
| 47410 | Color scheme for focused workspaces. | ||
| 47411 | |||
| 47412 | @item @code{active-workspace} (optional @code{sway-border-color}) | ||
| 47413 | Color scheme for active workspaces. | ||
| 47414 | |||
| 47415 | @item @code{inactive-workspace} (optional @code{sway-border-color}) | ||
| 47416 | Color scheme for inactive workspaces. | ||
| 47417 | |||
| 47418 | @item @code{urgent-workspace} (optional @code{sway-border-color}) | ||
| 47419 | Color scheme for workspaces containing ``urgent windows''. | ||
| 47420 | |||
| 47421 | @item @code{binding-mode} (optional @code{sway-border-color}) | ||
| 47422 | Color scheme for the binding mode indicator. | ||
| 47423 | @end table | ||
| 47424 | @end deftp | ||
| 47425 | |||
| 47426 | @deftp {Data Type} sway-bar | ||
| 47427 | Describes the Sway bar (see@ @cite{sway-bar(5)}). | ||
| 47428 | |||
| 47429 | @table @asis | ||
| 47430 | @item @code{identifier} (default: @code{'bar0}) | ||
| 47431 | Identifier of the bar. The value must be a symbol. | ||
| 47432 | |||
| 47433 | @item @code{position} (optional) | ||
| 47434 | Specify the position of the bar. Accepted values are @code{'top} or | ||
| 47435 | @code{'bottom}. | ||
| 47436 | |||
| 47437 | @item @code{hidden-state} (optional) | ||
| 47438 | Specify the apparence of the bar when it is hidden. Accepted values are | ||
| 47439 | @code{'hide} or @code{'show}. | ||
| 47440 | |||
| 47441 | @item @code{binding-mode-indicator} (optional) | ||
| 47442 | Boolean enabling or disabling the binding mode indicator. | ||
| 47443 | |||
| 47444 | @item @code{colors} (optional) | ||
| 47445 | An optional @code{sway-color} configuration record. | ||
| 47446 | |||
| 47447 | @item @code{status-command} (optional) | ||
| 47448 | This field accept strings, G-expressions and executable file-like | ||
| 47449 | values. The default value is a command (string) that prints the date | ||
| 47450 | and time every second. | ||
| 47451 | |||
| 47452 | Each line printed on @code{stdout} by this command (or script) will be | ||
| 47453 | displayed on the status area of the bar. | ||
| 47454 | |||
| 47455 | Below are a few examples using: | ||
| 47456 | @itemize | ||
| 47457 | @item | ||
| 47458 | a string: @code{"while date +'%Y-%m-%d %X'; do sleep 1; done"}, | ||
| 47459 | @item | ||
| 47460 | a G-exp: | ||
| 47461 | @lisp | ||
| 47462 | #~(string-append "while " | ||
| 47463 | #$coreutils "/bin/date" | ||
| 47464 | " +'%Y-%m-%d %X'; do sleep 1; done") | ||
| 47465 | @end lisp | ||
| 47466 | @item | ||
| 47467 | an executable file: | ||
| 47468 | @lisp | ||
| 47469 | (program-file | ||
| 47470 | "sway-bar-status" | ||
| 47471 | #~(begin | ||
| 47472 | (use-modules (ice-9 format) | ||
| 47473 | (srfi srfi-19)) | ||
| 47474 | (let loop () | ||
| 47475 | (let* ((date (date->string | ||
| 47476 | (current-date) | ||
| 47477 | "~d/~m/~Y (~a) • ~H:~M:~S"))) | ||
| 47478 | (format #t "~a~%~!" date) | ||
| 47479 | (sleep 1) | ||
| 47480 | (loop))))) | ||
| 47481 | @end lisp | ||
| 47482 | @end itemize | ||
| 47483 | |||
| 47484 | @item @code{mouse-bindings} (default: @code{'()}) | ||
| 47485 | This field accepts an associative list. Keys are integers describing | ||
| 47486 | mouse events. Values can either be strings or G-expressions. | ||
| 47487 | |||
| 47488 | The module @code{(gnu home services sway)} exports constants | ||
| 47489 | @code{%ev-code-mouse-left}, @code{%ev-code-mouse-right} and | ||
| 47490 | @code{%ev-code-mouse-scroll-click} whose values are integers | ||
| 47491 | corresponding to left, right and scroll click respectively. For | ||
| 47492 | example, with @code{(mouse-bindings `((,%ev-code-mouse-left . "exec | ||
| 47493 | $term")))}, left clicks in the status bar open the terminal (assuming | ||
| 47494 | that the variable @code{$term} is bound to a terminal). | ||
| 47495 | @end table | ||
| 47496 | @end deftp | ||
| 47497 | |||
| 47498 | @deftp {Data Type} sway-mode | ||
| 47499 | Describes a Sway mode (see@ @cite{sway(5)}). For example, the following | ||
| 47500 | snippet defines the resize mode of the default Sway configuration: | ||
| 47501 | @example | ||
| 47502 | (sway-mode | ||
| 47503 | (mode-name "resize") | ||
| 47504 | (keybindings | ||
| 47505 | '(($left . "resize shrink width 10px") | ||
| 47506 | ($right . "resize grow width 10px") | ||
| 47507 | ($down . "resize grow height 10px") | ||
| 47508 | ($up . "resize shrink height 10px") | ||
| 47509 | (Left . "resize shrink width 10px") | ||
| 47510 | (Right . "resize grow width 10px") | ||
| 47511 | (Down . "resize grow height 10px") | ||
| 47512 | (Up . "resize shrink height 10px") | ||
| 47513 | (Return . "mode \"default\"") | ||
| 47514 | (Escape . "mode \"default\"")))) | ||
| 47515 | @end example | ||
| 47516 | |||
| 47517 | @table @asis | ||
| 47518 | @item @code{mode-name} (default: @code{"default"}) | ||
| 47519 | Name of the mode. This field accepts strings. | ||
| 47520 | |||
| 47521 | @item @code{keybindings} (default: @code{'()}) | ||
| 47522 | This field describes keybindings. The value is an association list: | ||
| 47523 | keys are symbols and values are either strings or G-expressions, as | ||
| 47524 | above. | ||
| 47525 | |||
| 47526 | @item @code{mouse-bindings} (default: @code{'()}) | ||
| 47527 | Ditto, but keys are mouse events (integers). Constants | ||
| 47528 | @code{%ev-code-mouse-*} described above can be used as helpers to define | ||
| 47529 | mouse bindings. | ||
| 47530 | @end table | ||
| 47531 | @end deftp | ||
| 47532 | |||
| 47127 | @node Networking Home Services | 47533 | @node Networking Home Services |
| 47128 | @subsection Networking Home Services | 47534 | @subsection Networking Home Services |
| 47129 | 47535 | ||
diff --git a/gnu/home/services/sway.scm b/gnu/home/services/sway.scm new file mode 100644 index 00000000000..0e1a2d57b2a --- /dev/null +++ b/gnu/home/services/sway.scm | |||
| @@ -0,0 +1,870 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | ||
| 2 | ;;; Copyright © 2024 Arnaud Daby-Seesaram <ds-ac@nanein.fr> | ||
| 3 | ;;; | ||
| 4 | ;;; This file is part of GNU Guix. | ||
| 5 | ;;; | ||
| 6 | ;;; GNU Guix is free software; you can redistribute it and/or modify it | ||
| 7 | ;;; under the terms of the GNU General Public License as published by | ||
| 8 | ;;; the Free Software Foundation; either version 3 of the License, or (at | ||
| 9 | ;;; your option) any later version. | ||
| 10 | ;;; | ||
| 11 | ;;; GNU Guix is distributed in the hope that it will be useful, but | ||
| 12 | ;;; WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | ;;; GNU General Public License for more details. | ||
| 15 | ;;; | ||
| 16 | ;;; You should have received a copy of the GNU General Public License | ||
| 17 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. | ||
| 18 | |||
| 19 | (define-module (gnu home services sway) | ||
| 20 | #:use-module (guix modules) | ||
| 21 | #:use-module (guix gexp) | ||
| 22 | #:use-module (srfi srfi-1) | ||
| 23 | #:use-module (ice-9 match) | ||
| 24 | #:use-module (guix packages) | ||
| 25 | #:use-module (gnu system keyboard) | ||
| 26 | #:use-module (gnu services configuration) | ||
| 27 | #:use-module (gnu home services) | ||
| 28 | #:use-module (gnu packages wm) | ||
| 29 | #:use-module (gnu packages terminals) | ||
| 30 | #:export (;; Event codes | ||
| 31 | %ev-code-mouse-left | ||
| 32 | %ev-code-mouse-right | ||
| 33 | %ev-code-mouse-scroll-click | ||
| 34 | |||
| 35 | ;; Configuration records. | ||
| 36 | sway-configuration | ||
| 37 | sway-bar | ||
| 38 | sway-output | ||
| 39 | sway-input | ||
| 40 | point | ||
| 41 | sway-color | ||
| 42 | sway-border-color | ||
| 43 | home-sway-service-type | ||
| 44 | sway-configuration->file | ||
| 45 | sway-mode | ||
| 46 | |||
| 47 | ;; Default values. | ||
| 48 | %sway-default-variables | ||
| 49 | %sway-default-gestures | ||
| 50 | %sway-default-modes | ||
| 51 | %sway-default-keybindings | ||
| 52 | %sway-default-startup-programs | ||
| 53 | %sway-default-packages)) | ||
| 54 | |||
| 55 | ;; Helper function. | ||
| 56 | (define (flatmap f l) | ||
| 57 | (let loop ((lst (reverse l)) (acc '())) | ||
| 58 | (match lst | ||
| 59 | (() acc) | ||
| 60 | ((head . tail) | ||
| 61 | (let* ((h (f head)) | ||
| 62 | (acc (append h acc))) | ||
| 63 | (loop tail acc)))))) | ||
| 64 | |||
| 65 | |||
| 66 | ;;; | ||
| 67 | ;;; Definition of configurations. | ||
| 68 | ;;; | ||
| 69 | |||
| 70 | (define (string-ish? s) | ||
| 71 | (or (gexp? s) | ||
| 72 | (file-like? s) | ||
| 73 | (string? s))) | ||
| 74 | |||
| 75 | (define (string-or-gexp? s) | ||
| 76 | (or (gexp? s) | ||
| 77 | (string? s))) | ||
| 78 | |||
| 79 | (define (list-of-string-ish? lst) | ||
| 80 | (every string-ish? lst)) | ||
| 81 | |||
| 82 | (define (list-of-packages? lst) | ||
| 83 | (every package? lst)) | ||
| 84 | |||
| 85 | (define (bar-position? p) | ||
| 86 | (member p '(top bottom))) | ||
| 87 | |||
| 88 | (define (hidden-state? st) | ||
| 89 | (member st '(hide show))) | ||
| 90 | |||
| 91 | (define (string-or-symbol? s) | ||
| 92 | (or (string? s) | ||
| 93 | (symbol? s))) | ||
| 94 | |||
| 95 | (define (strings? lst) | ||
| 96 | (every string? lst)) | ||
| 97 | |||
| 98 | (define (extra-content? extra) | ||
| 99 | (every string-or-gexp? extra)) | ||
| 100 | |||
| 101 | (define (make-alist-predicate key? val?) | ||
| 102 | (lambda (lst) | ||
| 103 | (every | ||
| 104 | (lambda (item) | ||
| 105 | (match item | ||
| 106 | ((k . v) | ||
| 107 | (and (key? k) | ||
| 108 | (val? v))) | ||
| 109 | (_ #f))) | ||
| 110 | lst))) | ||
| 111 | |||
| 112 | (define bindings? | ||
| 113 | (make-alist-predicate symbol? string-or-gexp?)) | ||
| 114 | |||
| 115 | (define mouse-bindings? | ||
| 116 | (make-alist-predicate integer? string-or-gexp?)) | ||
| 117 | |||
| 118 | (define (variables? lst) | ||
| 119 | (make-alist-predicate symbol? string-ish?)) | ||
| 120 | |||
| 121 | (define-maybe string (no-serialization)) | ||
| 122 | (define-maybe strings (no-serialization)) | ||
| 123 | (define-maybe boolean (no-serialization)) | ||
| 124 | (define-maybe keyboard-layout (no-serialization)) | ||
| 125 | |||
| 126 | (define-configuration/no-serialization sway-input | ||
| 127 | (identifier | ||
| 128 | (string-or-symbol '*) | ||
| 129 | "Identifier of the input.") | ||
| 130 | (layout | ||
| 131 | maybe-keyboard-layout | ||
| 132 | "Keyboard layout of the input.") | ||
| 133 | (disable-while-typing | ||
| 134 | maybe-boolean | ||
| 135 | "If `#t', disable the input while typing; if `#f' do not.") | ||
| 136 | (disable-while-trackpointing | ||
| 137 | maybe-boolean | ||
| 138 | "If `#t', disable the input while using a trackpoint; if `#f' do not.") | ||
| 139 | (tap | ||
| 140 | maybe-boolean | ||
| 141 | "Enable or disable tap.") | ||
| 142 | (extra-content | ||
| 143 | (extra-content '()) | ||
| 144 | "Lines to add at the end of the configuration file.")) | ||
| 145 | |||
| 146 | (define (sway-inputs? lst) | ||
| 147 | (every sway-input? lst)) | ||
| 148 | |||
| 149 | (define-configuration/no-serialization sway-border-color | ||
| 150 | (border | ||
| 151 | string | ||
| 152 | "Border color.") | ||
| 153 | (background | ||
| 154 | string | ||
| 155 | "Background color.") | ||
| 156 | (text | ||
| 157 | string | ||
| 158 | "Text color.")) | ||
| 159 | |||
| 160 | (define-maybe sway-border-color (no-serialization)) | ||
| 161 | |||
| 162 | (define-configuration/no-serialization sway-color | ||
| 163 | (background | ||
| 164 | maybe-string | ||
| 165 | "Background color of the bar.") | ||
| 166 | (statusline | ||
| 167 | maybe-string | ||
| 168 | "Text color of the status line.") | ||
| 169 | (focused-background | ||
| 170 | maybe-string | ||
| 171 | "Background color of the bar on the currently focused monitor.") | ||
| 172 | (focused-statusline | ||
| 173 | maybe-string | ||
| 174 | "Text color of the statusline on the currently focused monitor.") | ||
| 175 | (focused-workspace | ||
| 176 | maybe-sway-border-color | ||
| 177 | "Color scheme for focused workspaces.") | ||
| 178 | (active-workspace | ||
| 179 | maybe-sway-border-color | ||
| 180 | "Color scheme for active workspaces.") | ||
| 181 | (inactive-workspace | ||
| 182 | maybe-sway-border-color | ||
| 183 | "Color scheme for inactive workspaces.") | ||
| 184 | (urgent-workspace | ||
| 185 | maybe-sway-border-color | ||
| 186 | "Color scheme for workspaces containing `urgent' windows.") | ||
| 187 | (binding-mode | ||
| 188 | maybe-sway-border-color | ||
| 189 | "Color scheme for the binding mode indicator.")) | ||
| 190 | |||
| 191 | (define-maybe sway-color (no-serialization)) | ||
| 192 | |||
| 193 | (define (status-command? c) | ||
| 194 | (or (string? c) | ||
| 195 | (file-like? c) | ||
| 196 | (gexp? c))) | ||
| 197 | |||
| 198 | (define-maybe bar-position (no-serialization)) | ||
| 199 | (define-maybe hidden-state (no-serialization)) | ||
| 200 | (define-maybe status-command (no-serialization)) | ||
| 201 | |||
| 202 | (define-configuration/no-serialization sway-bar | ||
| 203 | (identifier | ||
| 204 | (symbol 'bar0) | ||
| 205 | "Identifier of the bar.") | ||
| 206 | (position | ||
| 207 | maybe-bar-position | ||
| 208 | "Position of the bar.") | ||
| 209 | (hidden-state | ||
| 210 | maybe-hidden-state | ||
| 211 | "Hidden state.") | ||
| 212 | (binding-mode-indicator | ||
| 213 | maybe-boolean | ||
| 214 | "Binding indicator.") | ||
| 215 | (colors | ||
| 216 | maybe-sway-color | ||
| 217 | "Color palette of the bar.") | ||
| 218 | (status-command | ||
| 219 | maybe-status-command | ||
| 220 | "Status command.") | ||
| 221 | (mouse-bindings | ||
| 222 | (mouse-bindings '()) | ||
| 223 | "Actions triggered by mouse events.") | ||
| 224 | (extra-content | ||
| 225 | (extra-content '()) | ||
| 226 | "Extra configuration lines.")) | ||
| 227 | |||
| 228 | (define-maybe sway-bar (no-serialization)) | ||
| 229 | |||
| 230 | (define-configuration/no-serialization point | ||
| 231 | (x integer "X coordinate.") | ||
| 232 | (y integer "Y coordinate.")) | ||
| 233 | |||
| 234 | (define-maybe point (no-serialization)) | ||
| 235 | |||
| 236 | (define (background? bg) | ||
| 237 | (or (string-ish? bg) | ||
| 238 | (and (pair? bg) | ||
| 239 | (string-ish? (car bg)) | ||
| 240 | (member (cdr bg) '(stretch fill fit center tile))))) | ||
| 241 | |||
| 242 | (define-maybe background (no-serialization)) | ||
| 243 | |||
| 244 | (define-configuration/no-serialization sway-output | ||
| 245 | (identifier | ||
| 246 | (string-or-symbol '*) | ||
| 247 | "Identifier of the output.") | ||
| 248 | (resolution | ||
| 249 | maybe-string | ||
| 250 | "Mode of the monitor.") | ||
| 251 | (position | ||
| 252 | maybe-point | ||
| 253 | "Position of the monitor.") | ||
| 254 | (background | ||
| 255 | maybe-background | ||
| 256 | "Background image.") | ||
| 257 | (extra-content | ||
| 258 | (extra-content '()) | ||
| 259 | "Extra lines.")) | ||
| 260 | |||
| 261 | (define (sway-outputs? lst) | ||
| 262 | (every sway-output? lst)) | ||
| 263 | |||
| 264 | (define-configuration/no-serialization sway-mode | ||
| 265 | (mode-name | ||
| 266 | (string "default") | ||
| 267 | "Name of the mode.") | ||
| 268 | (keybindings | ||
| 269 | (bindings '()) | ||
| 270 | "Keybindings.") | ||
| 271 | (mouse-bindings | ||
| 272 | (mouse-bindings '()) | ||
| 273 | "Mouse bindings.")) | ||
| 274 | |||
| 275 | (define (sway-modes? lst) | ||
| 276 | (every sway-mode? lst)) | ||
| 277 | |||
| 278 | (define-configuration/no-serialization sway-configuration | ||
| 279 | (keybindings | ||
| 280 | (bindings %sway-default-keybindings) | ||
| 281 | "Keybindings.") | ||
| 282 | (gestures | ||
| 283 | (bindings %sway-default-gestures) | ||
| 284 | "Gestures.") | ||
| 285 | (packages | ||
| 286 | (list-of-packages | ||
| 287 | %sway-default-packages) | ||
| 288 | "List of packages to add to the profile.") | ||
| 289 | (variables | ||
| 290 | (variables %sway-default-variables) | ||
| 291 | "Variables declared at the beginning of the file.") | ||
| 292 | (inputs | ||
| 293 | (sway-inputs '()) | ||
| 294 | "Inputs.") | ||
| 295 | (outputs | ||
| 296 | (sway-outputs '()) | ||
| 297 | "Outputs.") | ||
| 298 | (bar | ||
| 299 | maybe-sway-bar | ||
| 300 | "Bar configuration.") | ||
| 301 | (modes | ||
| 302 | (sway-modes %sway-default-modes) | ||
| 303 | "Additional modes.") | ||
| 304 | (startup+reload-programs | ||
| 305 | (list-of-string-ish '()) | ||
| 306 | "Programs to execute at startup time.") | ||
| 307 | (startup-programs | ||
| 308 | (list-of-string-ish %sway-default-startup-programs) | ||
| 309 | "Programs to execute at startup time.") | ||
| 310 | (extra-content | ||
| 311 | (extra-content '()) | ||
| 312 | "Lines to add at the end of the configuration file.")) | ||
| 313 | |||
| 314 | |||
| 315 | ;;; | ||
| 316 | ;;; Default settings and useful constants. | ||
| 317 | ;;; | ||
| 318 | |||
| 319 | (define sway-menu | ||
| 320 | (program-file | ||
| 321 | "sway-menu.scm" | ||
| 322 | (with-imported-modules | ||
| 323 | (source-module-closure '((guix build utils))) | ||
| 324 | #~(begin | ||
| 325 | (use-modules (ice-9 ftw) | ||
| 326 | (ice-9 popen) | ||
| 327 | (ice-9 receive) | ||
| 328 | (ice-9 rdelim) | ||
| 329 | (guix build utils) | ||
| 330 | (srfi srfi-1)) | ||
| 331 | |||
| 332 | (define (directory->files dir) | ||
| 333 | (define (executable-file? f) | ||
| 334 | ;; Cf. `(@ (guix build utils) executable-file?)' for an | ||
| 335 | ;; explanation of `(zero? ...)'. | ||
| 336 | (and=> (and (not (eq? (string-ref f 0) #\.)) | ||
| 337 | (stat f)) | ||
| 338 | (lambda (s) | ||
| 339 | (not (or | ||
| 340 | (zero? (logand (stat:mode s) #o100)) | ||
| 341 | (eq? (stat:type s) 'directory)))))) | ||
| 342 | (with-directory-excursion dir | ||
| 343 | (scandir "." executable-file?))) | ||
| 344 | |||
| 345 | (let ((path (string-append (getenv "HOME") | ||
| 346 | "/.guix-home/profile/bin")) | ||
| 347 | (wmenu #$(file-append wmenu "/bin/wmenu")) | ||
| 348 | (swaymsg #$(file-append sway "/bin/swaymsg"))) | ||
| 349 | (receive (from to pids) | ||
| 350 | (pipeline `((,wmenu))) | ||
| 351 | (for-each | ||
| 352 | (lambda (c) (format to "~a~%" c)) | ||
| 353 | (directory->files path)) | ||
| 354 | (close to) | ||
| 355 | (let ((choice (read-line from))) | ||
| 356 | (close from) | ||
| 357 | (waitpid (first pids)) | ||
| 358 | (when (string? choice) ;do not attempt to launch if no choice | ||
| 359 | ;was given (e.g. if Escape is pressed in | ||
| 360 | ;wmenu). | ||
| 361 | (execl swaymsg swaymsg "exec" "--" | ||
| 362 | choice))))))))) | ||
| 363 | |||
| 364 | (define %ev-code-mouse-left 272) | ||
| 365 | (define %ev-code-mouse-right 273) | ||
| 366 | (define %ev-code-mouse-scroll-click 274) | ||
| 367 | |||
| 368 | (define %sway-default-modes | ||
| 369 | (list (sway-mode | ||
| 370 | (mode-name "resize") | ||
| 371 | (keybindings | ||
| 372 | '(($left . "resize shrink width 10px") | ||
| 373 | ($down . "resize grow height 10px") | ||
| 374 | ($up . "resize shrink height 10px") | ||
| 375 | ($right . "resize grow width 10px") | ||
| 376 | (Left . "resize shrink width 10px") | ||
| 377 | (Down . "resize grow height 10px") | ||
| 378 | (Up . "resize shrink height 10px") | ||
| 379 | (Right . "resize grow width 10px") | ||
| 380 | (Return . "mode \"default\"") | ||
| 381 | (Escape . "mode \"default\"")))))) | ||
| 382 | |||
| 383 | (define %sway-default-packages | ||
| 384 | (list sway)) | ||
| 385 | |||
| 386 | (define %sway-default-variables | ||
| 387 | `((mod . "Mod4") | ||
| 388 | (left . "h") | ||
| 389 | (down . "j") | ||
| 390 | (up . "k") | ||
| 391 | (right . "l") | ||
| 392 | (term . ,(file-append foot "/bin/foot")) | ||
| 393 | (menu . ,sway-menu))) | ||
| 394 | |||
| 395 | (define %sway-default-gestures | ||
| 396 | '((swipe:3:right . "workspace next_on_output") | ||
| 397 | (swipe:3:left . "workspace prev_on_output") | ||
| 398 | (swipe:3:down . "move to scratchpad") | ||
| 399 | (swipe:3:up . "scratchpad show"))) | ||
| 400 | |||
| 401 | (define %sway-default-keybindings | ||
| 402 | `(($mod+Return . "exec $term") | ||
| 403 | ($mod+Shift+q . "kill") | ||
| 404 | ($mod+d . "exec $menu") | ||
| 405 | ($mod+Shift+c . "reload") | ||
| 406 | ($mod+Shift+e | ||
| 407 | . ,#~(string-append | ||
| 408 | "exec " #$sway "/bin/swaynag -t warning -m \\\n " | ||
| 409 | "'You pressed the exit shortcut. Do you really want to exit sway?" | ||
| 410 | " This will end your Wayland session.' \\\n " | ||
| 411 | "-B 'Yes, exit sway' \\\n '" | ||
| 412 | #$sway "/bin/swaymsg exit'")) | ||
| 413 | ($mod+$left . "focus left") | ||
| 414 | ($mod+$down . "focus down") | ||
| 415 | ($mod+$up . "focus up") | ||
| 416 | ($mod+$right . "focus right") | ||
| 417 | ($mod+Left . "focus left") | ||
| 418 | ($mod+Down . "focus down") | ||
| 419 | ($mod+Up . "focus up") | ||
| 420 | ($mod+Right . "focus right") | ||
| 421 | ($mod+Shift+$left . "move left") | ||
| 422 | ($mod+Shift+$down . "move down") | ||
| 423 | ($mod+Shift+$up . "move up") | ||
| 424 | ($mod+Shift+$right . "move right") | ||
| 425 | ($mod+Shift+Left . "move left") | ||
| 426 | ($mod+Shift+Down . "move down") | ||
| 427 | ($mod+Shift+Up . "move up") | ||
| 428 | ($mod+Shift+Right . "move right") | ||
| 429 | ($mod+1 . "workspace number 1") | ||
| 430 | ($mod+2 . "workspace number 2") | ||
| 431 | ($mod+3 . "workspace number 3") | ||
| 432 | ($mod+4 . "workspace number 4") | ||
| 433 | ($mod+5 . "workspace number 5") | ||
| 434 | ($mod+6 . "workspace number 6") | ||
| 435 | ($mod+7 . "workspace number 7") | ||
| 436 | ($mod+8 . "workspace number 8") | ||
| 437 | ($mod+9 . "workspace number 9") | ||
| 438 | ($mod+0 . "workspace number 10") | ||
| 439 | ($mod+Shift+1 . "move container to workspace number 1") | ||
| 440 | ($mod+Shift+2 . "move container to workspace number 2") | ||
| 441 | ($mod+Shift+3 . "move container to workspace number 3") | ||
| 442 | ($mod+Shift+4 . "move container to workspace number 4") | ||
| 443 | ($mod+Shift+5 . "move container to workspace number 5") | ||
| 444 | ($mod+Shift+6 . "move container to workspace number 6") | ||
| 445 | ($mod+Shift+7 . "move container to workspace number 7") | ||
| 446 | ($mod+Shift+8 . "move container to workspace number 8") | ||
| 447 | ($mod+Shift+9 . "move container to workspace number 9") | ||
| 448 | ($mod+Shift+0 . "move container to workspace number 10") | ||
| 449 | ($mod+b . "splith") | ||
| 450 | ($mod+v . "splitv") | ||
| 451 | ($mod+s . "layout stacking") | ||
| 452 | ($mod+w . "layout tabbed") | ||
| 453 | ($mod+e . "layout toggle split") | ||
| 454 | ($mod+f . "fullscreen") | ||
| 455 | ($mod+Shift+space . "floating toggle") | ||
| 456 | ($mod+space . "focus mode_toggle") | ||
| 457 | ($mod+a . "focus parent") | ||
| 458 | ($mod+Shift+minus . "move scratchpad") | ||
| 459 | ($mod+minus . "scratchpad show") | ||
| 460 | ($mod+r . "mode \"resize\""))) | ||
| 461 | |||
| 462 | (define %sway-default-startup-programs | ||
| 463 | (list | ||
| 464 | #~(string-append | ||
| 465 | #$swayidle "/bin/swayidle -w \\\n " | ||
| 466 | ;; 300: lock screen. | ||
| 467 | "timeout 300 '" #$swaylock "/bin/swaylock " | ||
| 468 | "--indicator-radius 75 \\\n " | ||
| 469 | "-i " #$sway | ||
| 470 | "/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png \\\n " | ||
| 471 | "-f -c 000000' \\\n " | ||
| 472 | ;; 600: lock + screen off. | ||
| 473 | "timeout 600 '" #$sway "/bin/swaymsg \"output * power off\"' \\\n " | ||
| 474 | ;; Resume + sleep. | ||
| 475 | "resume '" #$sway "/bin/swaymsg \"output * power on\"' \\\n " | ||
| 476 | "before-sleep '" #$swaylock "/bin/swaylock -f -c 000000'"))) | ||
| 477 | |||
| 478 | |||
| 479 | ;;; | ||
| 480 | ;;; Serialization functions. | ||
| 481 | ;;; | ||
| 482 | |||
| 483 | ;; The main serialization code is defined in `sway-configuration->file' below. | ||
| 484 | ;; In this function, the configuration is seen as a list of lines and blocks. | ||
| 485 | ;; | ||
| 486 | ;; The other serialization functions of this files are helpers that will build | ||
| 487 | ;; the above list. Each function either returns a list, or elements that will | ||
| 488 | ;; be put in one. The elements of these lists will either be: | ||
| 489 | ;; - strings, | ||
| 490 | ;; In this case, the string is seen as a line to add to the configuraiton | ||
| 491 | ;; file. | ||
| 492 | ;; - a pair (cons 'begin-block string), | ||
| 493 | ;; In this case, a line "string {" is added to the configuration file, and | ||
| 494 | ;; the indentation level is increased by four. | ||
| 495 | ;; - the symbol 'end-block. | ||
| 496 | ;; In which case the indentation level is decreased by four, and the current | ||
| 497 | ;; configuration block is closed (with the line "}"). | ||
| 498 | |||
| 499 | ;; A few helper functions: | ||
| 500 | |||
| 501 | (define* (add-line-if field value | ||
| 502 | #:key (serializer %unset-value) | ||
| 503 | (suffix %unset-value)) | ||
| 504 | (if (eq? %unset-value value) | ||
| 505 | %unset-value | ||
| 506 | #~(string-append #$field " " | ||
| 507 | #$(if (eq? serializer %unset-value) | ||
| 508 | value | ||
| 509 | (serializer value)) | ||
| 510 | #$(if (eq? suffix %unset-value) | ||
| 511 | "" | ||
| 512 | suffix)))) | ||
| 513 | |||
| 514 | (define (add-block name content) | ||
| 515 | (let ((content (filter | ||
| 516 | (lambda (elt) (not (eq? elt %unset-value))) | ||
| 517 | content))) | ||
| 518 | (if (equal? content '()) | ||
| 519 | '() | ||
| 520 | (append | ||
| 521 | (list #~(cons 'begin-block #$name)) | ||
| 522 | content | ||
| 523 | (list #~'end-block))))) | ||
| 524 | |||
| 525 | (define-syntax add-block* | ||
| 526 | (syntax-rules () | ||
| 527 | ((add-block* name elt ...) | ||
| 528 | (add-block name (append elt ...))))) | ||
| 529 | |||
| 530 | ;; Serialization functions: | ||
| 531 | |||
| 532 | (define (box str) | ||
| 533 | (let* ((len (string-length str)) | ||
| 534 | (line (make-string (+ 8 len) #\#))) | ||
| 535 | (list | ||
| 536 | line | ||
| 537 | (string-append "### " str " ###") | ||
| 538 | line))) | ||
| 539 | |||
| 540 | (define (with-heading str lst) | ||
| 541 | (define (heading str) | ||
| 542 | (let* ((len (string-length str)) | ||
| 543 | (line (make-string (+ 2 len) #\#))) | ||
| 544 | (list | ||
| 545 | "" ;add an empty line before the configuration section. | ||
| 546 | (string-append "# " str) | ||
| 547 | line))) | ||
| 548 | (if (equal? lst '()) | ||
| 549 | '() ;if the configuration block is empty, do not add the heading. | ||
| 550 | (append (heading str) lst))) | ||
| 551 | |||
| 552 | (define-inlinable (serialize-boolean-yn b) | ||
| 553 | (if b "yes" "no")) | ||
| 554 | (define-inlinable (serialize-boolean-ed b) | ||
| 555 | (if b "enable" "disable")) | ||
| 556 | |||
| 557 | (define-inlinable (serialize-binding binder key value) | ||
| 558 | #~(string-append #$binder #$key " " #$value)) | ||
| 559 | |||
| 560 | (define (serialize-mouse-binding var) | ||
| 561 | (let* ((ev (car var)) | ||
| 562 | (ev-code (number->string ev)) | ||
| 563 | (command (cdr var))) | ||
| 564 | (serialize-binding "bindcode " ev-code command))) | ||
| 565 | |||
| 566 | (define (serialize-keybinding var) | ||
| 567 | (let ((name (symbol->string (car var))) | ||
| 568 | (value (cdr var))) | ||
| 569 | (serialize-binding "bindsym " name value))) | ||
| 570 | |||
| 571 | (define (serialize-gesture var) | ||
| 572 | (let ((name (symbol->string (car var))) | ||
| 573 | (value (cdr var))) | ||
| 574 | (serialize-binding "bindgesture " name value))) | ||
| 575 | |||
| 576 | (define (serialize-variable var) | ||
| 577 | (let ((name (symbol->string (car var))) | ||
| 578 | (value (cdr var))) | ||
| 579 | (serialize-binding "set $" name value))) | ||
| 580 | |||
| 581 | (define (serialize-exec b) | ||
| 582 | (if b | ||
| 583 | (lambda (exe) | ||
| 584 | #~(string-append "exec_always " #$exe)) | ||
| 585 | (lambda (exe) | ||
| 586 | #~(string-append "exec " #$exe)))) | ||
| 587 | |||
| 588 | (define (serialize-output out) | ||
| 589 | (let* ((pre-ident (sway-output-identifier out)) | ||
| 590 | (ident (if (symbol? pre-ident) | ||
| 591 | (symbol->string pre-ident) | ||
| 592 | (string-append "\"" pre-ident "\""))) | ||
| 593 | (background (let ((bg (sway-output-background out))) | ||
| 594 | (if (pair? bg) | ||
| 595 | bg | ||
| 596 | (cons bg 'fill)))) | ||
| 597 | (resolution (sway-output-resolution out)) | ||
| 598 | (position (sway-output-position out)) | ||
| 599 | (extra-content (sway-output-extra-content out))) | ||
| 600 | (add-block | ||
| 601 | (string-append "output " ident) | ||
| 602 | (cons* | ||
| 603 | ;; Optional elements. | ||
| 604 | (add-line-if "bg" (car background) | ||
| 605 | #:suffix | ||
| 606 | (string-append " " (symbol->string (cdr background)))) | ||
| 607 | (add-line-if "resolution" resolution) | ||
| 608 | (add-line-if "position" position | ||
| 609 | #:serializer | ||
| 610 | (lambda (p) | ||
| 611 | (string-append (number->string (point-x p)) | ||
| 612 | " " | ||
| 613 | (number->string (point-y p))))) | ||
| 614 | ;; Extra-content: inlined as-is. | ||
| 615 | extra-content)))) | ||
| 616 | |||
| 617 | (define (serialize-input input) | ||
| 618 | (define-inlinable (fetch-arg layout acc) | ||
| 619 | (if (eq? layout %unset-value) | ||
| 620 | %unset-value | ||
| 621 | (acc layout))) | ||
| 622 | |||
| 623 | (define-inlinable (unfalse f) | ||
| 624 | (lambda (arg) | ||
| 625 | (let ((res (f arg))) | ||
| 626 | (if res res %unset-value)))) | ||
| 627 | |||
| 628 | (define-inlinable (unnil f) | ||
| 629 | (lambda (arg) | ||
| 630 | (let ((res (f arg))) | ||
| 631 | (if (nil? res) %unset-value res)))) | ||
| 632 | |||
| 633 | (let* ((pre-ident (sway-input-identifier input)) | ||
| 634 | (ident (if (symbol? pre-ident) | ||
| 635 | (symbol->string pre-ident) | ||
| 636 | (string-append "\"" pre-ident "\""))) | ||
| 637 | |||
| 638 | ;; unpack the `layout' field. | ||
| 639 | (layout (sway-input-layout input)) | ||
| 640 | (xkb-layout (fetch-arg layout keyboard-layout-name)) | ||
| 641 | (xkb-variant (fetch-arg layout (unfalse keyboard-layout-variant))) | ||
| 642 | (xkb-model (fetch-arg layout (unfalse keyboard-layout-model))) | ||
| 643 | (xkb-options (fetch-arg layout (unnil keyboard-layout-options))) | ||
| 644 | |||
| 645 | (tap (sway-input-tap input)) | ||
| 646 | (dwt (sway-input-disable-while-typing input)) | ||
| 647 | (dwtp (sway-input-disable-while-trackpointing input)) | ||
| 648 | (extra-content (sway-input-extra-content input))) | ||
| 649 | (add-block | ||
| 650 | (string-append "input " ident) | ||
| 651 | (cons* | ||
| 652 | ;; Optional. | ||
| 653 | (add-line-if "xkb_layout" xkb-layout) | ||
| 654 | (add-line-if "xkb_model" xkb-model) | ||
| 655 | (add-line-if "xkb_variant" xkb-variant) | ||
| 656 | (add-line-if "xkb_options" xkb-options | ||
| 657 | #:serializer (lambda (l) (string-join l ","))) | ||
| 658 | (add-line-if "dwt" dwt | ||
| 659 | #:serializer serialize-boolean-ed) | ||
| 660 | (add-line-if "dwtp" dwtp | ||
| 661 | #:serializer serialize-boolean-ed) | ||
| 662 | (add-line-if "tap" tap | ||
| 663 | #:serializer serialize-boolean-ed) | ||
| 664 | ;; extra-content inlined as-is. | ||
| 665 | extra-content)))) | ||
| 666 | |||
| 667 | (define (serialize-colors colors) | ||
| 668 | (define (border-serializer val) | ||
| 669 | (string-append (sway-border-color-border val) | ||
| 670 | " " (sway-border-color-background val) | ||
| 671 | " " (sway-border-color-text val))) | ||
| 672 | (if (eq? %unset-value colors) | ||
| 673 | '() | ||
| 674 | (let ((background (sway-color-background colors)) | ||
| 675 | (statusline (sway-color-statusline colors)) | ||
| 676 | (focused-background (sway-color-focused-background colors)) | ||
| 677 | (focused-statusline (sway-color-focused-statusline colors)) | ||
| 678 | (focused-workspace (sway-color-focused-workspace colors)) | ||
| 679 | (active-workspace (sway-color-active-workspace colors)) | ||
| 680 | (inactive-workspace (sway-color-inactive-workspace colors)) | ||
| 681 | (urgent-workspace (sway-color-urgent-workspace colors)) | ||
| 682 | (binding-mode (sway-color-binding-mode colors))) | ||
| 683 | (add-block | ||
| 684 | "colors" | ||
| 685 | (list | ||
| 686 | (add-line-if "background" background) | ||
| 687 | (add-line-if "statusline" statusline) | ||
| 688 | (add-line-if "focused_background" focused-background) | ||
| 689 | (add-line-if "focused_statusline" focused-statusline) | ||
| 690 | (add-line-if "focused_workspace" focused-workspace | ||
| 691 | #:serializer border-serializer) | ||
| 692 | (add-line-if "active_workspace" active-workspace | ||
| 693 | #:serializer border-serializer) | ||
| 694 | (add-line-if "inactive_workspace" inactive-workspace | ||
| 695 | #:serializer border-serializer) | ||
| 696 | (add-line-if "urgent_workspace" urgent-workspace | ||
| 697 | #:serializer border-serializer) | ||
| 698 | (add-line-if "binding_mode" binding-mode | ||
| 699 | #:serializer border-serializer)))))) | ||
| 700 | |||
| 701 | (define (serialize-mode mode) | ||
| 702 | (let ((name (sway-mode-mode-name mode)) | ||
| 703 | (keys (sway-mode-keybindings mode)) | ||
| 704 | (clicks (sway-mode-mouse-bindings mode))) | ||
| 705 | (add-block* | ||
| 706 | (string-append "mode \"" name "\"") | ||
| 707 | (map serialize-keybinding keys) | ||
| 708 | (map serialize-mouse-binding clicks)))) | ||
| 709 | |||
| 710 | (define (serialize-bar bar) | ||
| 711 | (define serialize-symbol | ||
| 712 | symbol->string) | ||
| 713 | |||
| 714 | (let ((identifier (symbol->string (sway-bar-identifier bar))) | ||
| 715 | (position (sway-bar-position bar)) | ||
| 716 | (hidden-state (sway-bar-hidden-state bar)) | ||
| 717 | (status-command (sway-bar-status-command bar)) | ||
| 718 | (binding-mode-indicator (sway-bar-binding-mode-indicator bar)) | ||
| 719 | (mouse-bindings (sway-bar-mouse-bindings bar)) | ||
| 720 | (extra-content (sway-bar-extra-content bar)) | ||
| 721 | (colors (sway-bar-colors bar))) | ||
| 722 | (add-block* | ||
| 723 | (string-append "bar " identifier) | ||
| 724 | |||
| 725 | (if (eq? colors %unset-value) | ||
| 726 | '() | ||
| 727 | (serialize-colors colors)) | ||
| 728 | (list | ||
| 729 | (add-line-if "position" position | ||
| 730 | #:serializer serialize-symbol) | ||
| 731 | (add-line-if "hidden_state" hidden-state | ||
| 732 | #:serializer serialize-symbol) | ||
| 733 | (add-line-if "status_command" status-command) | ||
| 734 | (add-line-if "binding_mode_indicator" binding-mode-indicator | ||
| 735 | #:serializer serialize-boolean-yn)) | ||
| 736 | ;; Mouse-bindings and extra-content | ||
| 737 | (map serialize-mouse-binding mouse-bindings) | ||
| 738 | extra-content))) | ||
| 739 | |||
| 740 | (define (sway-configuration->file conf) | ||
| 741 | (let* ((extra (sway-configuration-extra-content conf)) | ||
| 742 | (bar (sway-configuration-bar conf))) | ||
| 743 | (computed-file | ||
| 744 | "sway-config" | ||
| 745 | #~(begin | ||
| 746 | (use-modules (ice-9 format) (ice-9 match) | ||
| 747 | (srfi srfi-1)) | ||
| 748 | |||
| 749 | (call-with-output-file #$output | ||
| 750 | (lambda (port) | ||
| 751 | |||
| 752 | ;; Add the (indented) line "s" to the output file. | ||
| 753 | (define (line s) | ||
| 754 | (lambda (i) | ||
| 755 | (format port "~a~a~%" i s) | ||
| 756 | i)) | ||
| 757 | |||
| 758 | ;; Begin a block "name" and adjust the indentation. | ||
| 759 | (define (begin-block name) | ||
| 760 | (lambda (i) | ||
| 761 | (format port "~a~a {~%" i name) | ||
| 762 | (string-append " " i))) | ||
| 763 | |||
| 764 | ;; Ends an open block and adjust the indentation. | ||
| 765 | ;; Note: we must currently be in a configuration block. | ||
| 766 | ;; Otherwise, `string-drop' might fail. | ||
| 767 | (define (end-block) | ||
| 768 | (lambda (i) | ||
| 769 | (let ((i (string-drop i 4))) | ||
| 770 | (format port "~a}~%" i) | ||
| 771 | i))) | ||
| 772 | |||
| 773 | ;; Helper function. The configuration is represented as a list | ||
| 774 | ;; of actions (alter the indentation level, add a line, ...). | ||
| 775 | ;; This function recognises the action and calls the right | ||
| 776 | ;; function among those defined above. | ||
| 777 | (define (serializer-dispatch-m arg) | ||
| 778 | (match arg | ||
| 779 | ;; Special cases: | ||
| 780 | (('begin-block . str) (begin-block str)) | ||
| 781 | ('end-block (end-block)) | ||
| 782 | ;; Default case: `arg' is assumed to be a string. | ||
| 783 | (_ (line arg)))) | ||
| 784 | |||
| 785 | (define (serializer-dispatch elt i) | ||
| 786 | ((serializer-dispatch-m elt) i)) | ||
| 787 | |||
| 788 | (fold | ||
| 789 | ;; Dispatch function: depending on its argument, it will change | ||
| 790 | ;; the indentation level or add a line to the output file. | ||
| 791 | serializer-dispatch | ||
| 792 | |||
| 793 | ;; Initial indentation string. This string is prepended to | ||
| 794 | ;; lines before their serialization. | ||
| 795 | "" | ||
| 796 | ;; List of lines or indentation modifiers. | ||
| 797 | (list | ||
| 798 | ;; Header. | ||
| 799 | #$@(box "Auto-generated configuration") | ||
| 800 | "# DO NOT EDIT MANUALLY." | ||
| 801 | |||
| 802 | ;; Variables. | ||
| 803 | #$@(with-heading "Variables." | ||
| 804 | (map serialize-variable | ||
| 805 | (sway-configuration-variables conf))) | ||
| 806 | |||
| 807 | ;; Outputs. | ||
| 808 | #$@(with-heading "Outputs." | ||
| 809 | (flatmap serialize-output | ||
| 810 | (sway-configuration-outputs conf))) | ||
| 811 | |||
| 812 | ;; Inputs. | ||
| 813 | #$@(with-heading "Inputs." | ||
| 814 | (flatmap serialize-input | ||
| 815 | (sway-configuration-inputs conf))) | ||
| 816 | |||
| 817 | ;; Bar configuration: | ||
| 818 | ;; If the bar is unset, do not include anything. | ||
| 819 | #$@(if (eq? bar %unset-value) | ||
| 820 | '() | ||
| 821 | (with-heading "Bar configuration." | ||
| 822 | (serialize-bar bar))) | ||
| 823 | |||
| 824 | ;; Keybindings. | ||
| 825 | #$@(with-heading "Keybindings." | ||
| 826 | (map serialize-keybinding | ||
| 827 | (sway-configuration-keybindings conf))) | ||
| 828 | ;; Gestures. | ||
| 829 | #$@(with-heading "Gestures." | ||
| 830 | (map serialize-gesture | ||
| 831 | (sway-configuration-gestures conf))) | ||
| 832 | |||
| 833 | ;; Modes. | ||
| 834 | #$@(with-heading "Modes." | ||
| 835 | (flatmap serialize-mode | ||
| 836 | (sway-configuration-modes conf))) | ||
| 837 | |||
| 838 | ;; Startup-Programs. | ||
| 839 | #$@(with-heading | ||
| 840 | "Programs to execute (at startup)." | ||
| 841 | (map (serialize-exec #f) | ||
| 842 | (sway-configuration-startup-programs conf))) | ||
| 843 | ;; startup+reload-programs. | ||
| 844 | #$@(with-heading | ||
| 845 | "Programs to execute (at startup & after reload)." | ||
| 846 | (map (serialize-exec #t) | ||
| 847 | (sway-configuration-startup+reload-programs conf))) | ||
| 848 | |||
| 849 | ;; Extra-content. | ||
| 850 | #$@(with-heading "Extra-content" extra))))))))) | ||
| 851 | |||
| 852 | |||
| 853 | ;;; | ||
| 854 | ;;; Definition of the Home Service. | ||
| 855 | ;;; | ||
| 856 | |||
| 857 | (define (sway-configuration->files sway-conf) | ||
| 858 | `((".config/sway/config" ,(sway-configuration->file sway-conf)))) | ||
| 859 | |||
| 860 | (define home-sway-service-type | ||
| 861 | (service-type | ||
| 862 | (name 'home-sway-config) | ||
| 863 | (extensions | ||
| 864 | (list (service-extension home-files-service-type | ||
| 865 | sway-configuration->files) | ||
| 866 | (service-extension home-profile-service-type | ||
| 867 | sway-configuration-packages))) | ||
| 868 | (description "Configure Sway by providing a file | ||
| 869 | @file{~/.config/sway/config}.") | ||
| 870 | (default-value (sway-configuration)))) | ||
diff --git a/gnu/local.mk b/gnu/local.mk index 46a687c28eb..90e22f15675 100644 --- a/gnu/local.mk +++ b/gnu/local.mk | |||
| @@ -114,6 +114,7 @@ GNU_SYSTEM_MODULES = \ | |||
| 114 | %D%/home/services/shepherd.scm \ | 114 | %D%/home/services/shepherd.scm \ |
| 115 | %D%/home/services/sound.scm \ | 115 | %D%/home/services/sound.scm \ |
| 116 | %D%/home/services/ssh.scm \ | 116 | %D%/home/services/ssh.scm \ |
| 117 | %D%/home/services/sway.scm \ | ||
| 117 | %D%/home/services/syncthing.scm \ | 118 | %D%/home/services/syncthing.scm \ |
| 118 | %D%/home/services/mcron.scm \ | 119 | %D%/home/services/mcron.scm \ |
| 119 | %D%/home/services/utils.scm \ | 120 | %D%/home/services/utils.scm \ |
