Re: A simple battery level alert mcron job for your Guix, v2

2019-07-31 Thread Ricardo Wurmus


Maxim Cournoyer  writes:

> The following mcron job accomplish this.  I've implemented it in Guile
> Scheme this time around and was puzzled that I had to use program-file
> to make it work, otherwise srfi-26's cut would error on undefined symbol
> '<>'.
>
> The problem was that passing the code as a lambda would have the syntax
> imported not a the top level, which is the only valid place to
> define/import syntax definitions, per the Guile manual.  Using
> `program-file' works around that, by placing the logic at the top level
> of a standalone script, while allowing you to define everything at the
> level of your Guix config file.

Ah, thanks for investigating this.  When you first asked about this I
was really quite puzzled.

>(let* ((input-pipe (open-pipe* OPEN_READ
>   #$(file-append acpi "/bin/acpi")))
>   (output (get-string-all input-pipe))
>   (m (string-match "Discharging, ([0-9]+)%" output))
>   (level (and=> m (compose string->number
>(cut match:substring <> 1)
>  (when (and=> level (cut <= <> %min-level))
>(format #t "warning: Battery level is low (~a%)~%" level)
>(invoke #$(file-append beep "/bin/beep") "-r5")))

Perhaps and-let* (SRFI 2) would be of interest here.

-- 
Ricardo




Re: A simple battery level alert mcron job for your Guix, v2

2019-07-31 Thread Maxim Cournoyer
Hello again,

The previously posted battery level alert job had a very annoying
limitation: it would keep beeping until the level of the battery would
have recovered above the defined limit.

We can do much better by stopping the noise as soon as the AC cable has
been plugged in.

The following mcron job accomplish this.  I've implemented it in Guile
Scheme this time around and was puzzled that I had to use program-file
to make it work, otherwise srfi-26's cut would error on undefined symbol
'<>'.

The problem was that passing the code as a lambda would have the syntax
imported not a the top level, which is the only valid place to
define/import syntax definitions, per the Guile manual.  Using
`program-file' works around that, by placing the logic at the top level
of a standalone script, while allowing you to define everything at the
level of your Guix config file.

Here's the new job definition, including an easy way to test it:

#+BEGIN_SRC scheme
(use-modules (gnu packages linux)
 (gnu packages terminals)
 (guix build utils)
 (guix derivations)
 (guix gexp)
 (guix modules)
 (guix store)
 (guix ui))

;;; Helper to build a derivation easily.
(define (build-drv drv)
  (with-store store
(let* ((drv (run-with-store store drv))
   (success? (build-derivations store (list drv
  (when (not success?)
(error "Build failed."))
  (derivation->output-path drv

(define %battery-alert-job
  ;; Beep the system when the battery reaches %MIN-LEVEL or less
  ;; battery percent.
  (program-file
   "battery-alert.scm"
   (with-imported-modules (source-module-closure
   '((guix build utils)))
 #~(begin
 (define %min-level 20)
 (use-modules (guix build utils)
  (ice-9 popen)
  (ice-9 regex)
  (ice-9 textual-ports)
  (srfi srfi-26))
 (setenv "LC_ALL" "C")
 (let* ((input-pipe (open-pipe* OPEN_READ
#$(file-append acpi "/bin/acpi")))
(output (get-string-all input-pipe))
(m (string-match "Discharging, ([0-9]+)%" output))
(level (and=> m (compose string->number
 (cut match:substring <> 1)
   (when (and=> level (cut <= <> %min-level))
 (format #t "warning: Battery level is low (~a%)~%" level)
 (invoke #$(file-append beep "/bin/beep") "-r5")))

;;; Test job
(invoke (build-drv (lower-object %battery-alert-job)))
#+END_SRC

I'll send a patch to document the use of program-file for this use case,
along with this example.

Maxim