~abcdw/rde-devel

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch
3 2

[PATCH] gnu: home-services: web-browsers: Add IceCat service.

Details
Message ID
<f806cb077cfa7b208a1f7e1eeb53b0afd57998d4.1620588922.git.public@yoctocell.xyz>
DKIM signature
pass
Download raw message
Patch: +193 -0
* gnu/home-services/web-browsers.scm: New file.
---
IceCat belongs to the (gnu packages gnuzilla) module, but I think it
makes more sense to put all the web browsers in the same module.

 gnu/home-services/web-browsers.scm | 193 +++++++++++++++++++++++++++++
 1 file changed, 193 insertions(+)
 create mode 100644 gnu/home-services/web-browsers.scm

diff --git a/gnu/home-services/web-browsers.scm b/gnu/home-services/web-browsers.scm
new file mode 100644
index 0000000..08a7417
--- /dev/null
+++ b/gnu/home-services/web-browsers.scm
@@ -0,0 +1,193 @@
(define-module (gnu home-services web-browsers)
  #:use-module (gnu home-services)
  #:use-module (gnu home-services-utils)
  #:use-module (gnu home-services files)
  #:use-module (gnu services configuration)
  #:use-module (gnu packages gnuzilla)
  #:use-module (guix packages)
  #:use-module (guix gexp)
  #:use-module (guix diagnostics)
  #:use-module (guix i18n)
  #:use-module (ice-9 match)
  #:use-module (srfi srfi-1)

  #:export (home-icecat-service-type
            icecat-configuration
            icecat-profile))

;;; Commentary:
;;;
;;; Web browser related services.
;;;
;;; Code:


;;;
;;; IceCat.
;;;
;;; (icecat-configuration
;;;    (profiles
;;;     (list (icecat-profile
;;;            (default? #t)
;;;            (name "default")
;;;            (id 0)
;;;            (settings '((browser.urlbar.shortcuts.history . #t)
;;;                        (browser.fullscreen.autohide . #t)))
;;;            (user-chrome "\
;;; #TabsToolbar { visibility: collapse !important; }")
;;;            (user-content "\
;;; :root{ scrollbar-width: none !important; }"))
;;;           (icecat-profile
;;;            (default? #f)
;;;            (name "github")
;;;            (id 1)
;;;            (settings '((browser.urlbar.shortcuts.bookmarks . #f)
;;;                        (browser.fullscreen.autohide . #t)))))))
;;;

(define %icecat-config-path "mozilla/icecat")
(define (listof-icecat-profile? val)
  (listof icecat-profile?))

(define-configuration icecat-profile
  (default?
    (boolean #f)
    "Whether or not this is the default profile for IceCat.")
  (name
   (string)
   "The name of this IceCat profile.  This name will show up in the
@uref{about:profiles} page, and it has to be unique for each
@code{icecat-profile}.")
  (id
   (integer)
   "The profile id assigned to this profile.  This has to be unique to
each @code{icecat-profile}.")
  (settings
   (alist '())
   "An association list of options to set in this profile.  These are
options you can see in the @uref{about:config} page.  The key of the
pair can be a string or a symbol, and the value can be a string,
symbol, boolean, or number.")
  (user-chrome
   (string "")
   "Custom user chrome CSS.  See @uref{https://www.userchrome.org/} for
details on how to customize the look and feel of IceCat.")
  (user-content
   (string "")
   "Custom user content CSS.")
  (no-serialization))

;; TODO: Extensions.
(define-configuration icecat-configuration
  (package
    (package icecat)
    "The IceCat package to use.")
  (profiles
   (listof-icecat-profile '())
   "List of IceCat profiles.")
  (no-serialization))

(define (icecat-profile-service config)
  (list (icecat-configuration-package config)))

(define (icecat-files-service config)
  (define (serialize-field key val)
    (let ((val (cond
                ((boolean? val) => boolean->true-or-false)
                (else val))))
      (format #f "user_pref(\"~a\", ~a);\n" key val)))

  (define (serialize-settings settings)
    (generic-serialize-alist string-append serialize-field settings))

  (define (check-duplicate-field field-name fields)
    (let loop ((acc '())
               (fields fields))
      (cond
       ((null? fields) #t)
       (else (let ((head (first fields)))
               (if (member head acc)
                   (raise (formatted-message
                           (G_ "`icecat-configuration' cannot contain \
`icecat-profile's with duplicate ~as: `~a'")
                           field-name head))
                   (loop (cons head acc) (rest fields))))))))

  (define (check-only-one-default defaults)
    (if (= (length (filter identity defaults)) 1)
        #t
        (raise (formatted-message
                (G_ "Only one `icecat-profile' in `icecat-configuration' can \
be the default profile.")))))

  ;; Return a list where the first element is a list of alists
  ;; representing the content of profiles.ini, and the rest of the
  ;; elements is a containing the content of the config files
  ;; (user.js, userChrome.css, userContent.css)
  (define (serialize-profiles profiles)
    (match profiles
      (($ <icecat-profile> location default? name id
                           settings user-chrome user-content)
       (let ((profile-path (if default? "default" name))
             (file-name (string-append "icecat-" name "-profile")))
         (filter
          (compose not null?)
          `(((,(format #f "Profile~a" id)
              ((default . ,(if default? 1 0))
               (is-relative . 1)
               (name . ,(string-capitalize name))
               (path . ,profile-path))))
            ,(optional (not (null? settings))
                       (list
                        (format #f "~a/~a/user.js"
                                %icecat-config-path profile-path)
                        (mixed-text-file
                         (string-append file-name "-settings")
                         (serialize-settings settings))))
            ,(optional (not (string=? user-chrome ""))
                       (list
                        (format #f "~a/~a/chrome/userChrome.css"
                                %icecat-config-path profile-path)
                        (mixed-text-file
                         (string-append file-name "-user-chrome")
                         user-chrome)))
            ,(optional (not (string=? user-content ""))
                       (list
                        (format #f "~a/~a/chrome/userContent.css"
                                %icecat-config-path profile-path)
                        (mixed-text-file
                         (string-append file-name "-user-content")
                         user-content)))))))))

  (match config
    (($ <icecat-configuration> location package profiles)
     (begin
       (check-only-one-default (map icecat-profile-default? profiles))
       (check-duplicate-field "name" (map icecat-profile-name profiles))
       (check-duplicate-field "id" (map icecat-profile-id profiles))
       (let* ((configs (map serialize-profiles profiles))
              (profile-ini (append '((General
                                      ((start-with-last-profile . 1))))
                                   (append-map first configs))))
         (define (serialize-field key val)
           (let ((val (cond
                       ((boolean? val) (if val 1 0))
                       (else val))))
             (format #f "~a=~a\n" (object->camel-case-string key 'upper) val)))
         `((,(format #f "~a/profiles.ini" %icecat-config-path)
            ,(mixed-text-file
              "icecat-profile-ini"
              (generic-serialize-ini-config
               #:serialize-field serialize-field
               #:fields profile-ini)))
           ,@(flatten (map rest configs))))))))

(define home-icecat-service-type
  (service-type (name 'home-icecat)
                (extensions
                 (list (service-extension
                        home-files-service-type
                        icecat-files-service)
                       (service-extension
                        home-profile-service-type
                        icecat-profile-service)))))

base-commit: ee8140d920f15aa68434b10617379d3a3bafd3e1
-- 
2.31.1
Details
Message ID
<87v97m7p4q.fsf@trop.in>
In-Reply-To
<f806cb077cfa7b208a1f7e1eeb53b0afd57998d4.1620588922.git.public@yoctocell.xyz> (view parent)
DKIM signature
missing
Download raw message
> * gnu/home-services/web-browsers.scm: New file.
> ---
> IceCat belongs to the (gnu packages gnuzilla) module, but I think it
> makes more sense to put all the web browsers in the same module.

Agree.

>  gnu/home-services/web-browsers.scm | 193 +++++++++++++++++++++++++++++
>  1 file changed, 193 insertions(+)
>  create mode 100644 gnu/home-services/web-browsers.scm

> diff --git a/gnu/home-services/web-browsers.scm b/gnu/home-services/web-browsers.scm
> new file mode 100644
> index 0000000..08a7417
> --- /dev/null
> +++ b/gnu/home-services/web-browsers.scm
> @@ -0,0 +1,193 @@
> +(define-module (gnu home-services web-browsers)
> +  #:use-module (gnu home-services)
> +  #:use-module (gnu home-services-utils)
> +  #:use-module (gnu home-services files)
> +  #:use-module (gnu services configuration)
> +  #:use-module (gnu packages gnuzilla)
> +  #:use-module (guix packages)
> +  #:use-module (guix gexp)
> +  #:use-module (guix diagnostics)
> +  #:use-module (guix i18n)
> +  #:use-module (ice-9 match)
> +  #:use-module (srfi srfi-1)
> +
> +  #:export (home-icecat-service-type
> +            icecat-configuration
> +            icecat-profile))

Should be home-icecat-configuration.
https://lists.sr.ht/~abcdw/rde-devel/%3C87y2cqifpx.fsf%40yoctocell.xyz%3E
Still not shure about icecat-profile.

> +
> +;;; Commentary:
> +;;;
> +;;; Web browser related services.
> +;;;
> +;;; Code:
> +
> +
> +;;;
> +;;; IceCat.
> +;;;
> +;;; (icecat-configuration
> +;;;    (profiles
> +;;;     (list (icecat-profile
> +;;;            (default? #t)
> +;;;            (name "default")
> +;;;            (id 0)
> +;;;            (settings '((browser.urlbar.shortcuts.history . #t)
> +;;;                        (browser.fullscreen.autohide . #t)))
> +;;;            (user-chrome "\
> +;;; #TabsToolbar { visibility: collapse !important; }")
> +;;;            (user-content "\
> +;;; :root{ scrollbar-width: none !important; }"))
> +;;;           (icecat-profile
> +;;;            (default? #f)
> +;;;            (name "github")
> +;;;            (id 1)
> +;;;            (settings '((browser.urlbar.shortcuts.bookmarks . #f)
> +;;;                        (browser.fullscreen.autohide . #t)))))))
> +;;;
> +
> +(define %icecat-config-path "mozilla/icecat")
> +(define (listof-icecat-profile? val)
> +  (listof icecat-profile?))
> +
> +(define-configuration icecat-profile
> +  (default?
> +    (boolean #f)
> +    "Whether or not this is the default profile for IceCat.")
> +  (name
> +   (string)
> +   "The name of this IceCat profile.  This name will show up in the
> +@uref{about:profiles} page, and it has to be unique for each
> +@code{icecat-profile}.")
> +  (id
> +   (integer)
> +   "The profile id assigned to this profile.  This has to be unique to
> +each @code{icecat-profile}.")
> +  (settings
> +   (alist '())
> +   "An association list of options to set in this profile.  These are
> +options you can see in the @uref{about:config} page.  The key of the
> +pair can be a string or a symbol, and the value can be a string,
> +symbol, boolean, or number.")
> +  (user-chrome
> +   (string "")
> +   "Custom user chrome CSS.  See @uref{https://www.userchrome.org/} for
> +details on how to customize the look and feel of IceCat.")
> +  (user-content
> +   (string "")
> +   "Custom user content CSS.")
> +  (no-serialization))
> +
> +;; TODO: Extensions.
> +(define-configuration icecat-configuration
> +  (package
> +    (package icecat)
> +    "The IceCat package to use.")
> +  (profiles
> +   (listof-icecat-profile '())
> +   "List of IceCat profiles.")
> +  (no-serialization))
> +
> +(define (icecat-profile-service config)
> +  (list (icecat-configuration-package config)))
> +
> +(define (icecat-files-service config)
> +  (define (serialize-field key val)
> +    (let ((val (cond
> +                ((boolean? val) => boolean->true-or-false)

(boolean? val) will be passed to boolean->true-or-false and it will be
always #t.

> +                (else val))))
> +      (format #f "user_pref(\"~a\", ~a);\n" key val)))

Won't work for string values.

> +
> +  (define (serialize-settings settings)
> +    (generic-serialize-alist string-append serialize-field settings))

Doesn't support gexps.  Not sure that they really needed, but
implemented support for them.

> +
> +  (define (check-duplicate-field field-name fields)
> +    (let loop ((acc '())
> +               (fields fields))
> +      (cond
> +       ((null? fields) #t)

check-duplicate-field should return #f if there is no duplicates.

> +       (else (let ((head (first fields)))
> +               (if (member head acc)
> +                   (raise (formatted-message
> +                           (G_ "`icecat-configuration' cannot contain \
> +`icecat-profile's with duplicate ~as: `~a'")
> +                           field-name head))
> +                   (loop (cons head acc) (rest fields))))))))

Doesn't really matter here, but sort + fold would be faster:
O(NlogN) vs O(N^2).

> +
> +  (define (check-only-one-default defaults)
> +    (if (= (length (filter identity defaults)) 1)
> +        #t
> +        (raise (formatted-message
> +                (G_ "Only one `icecat-profile' in `icecat-configuration' can \
> +be the default profile.")))))
> +
> +  ;; Return a list where the first element is a list of alists
> +  ;; representing the content of profiles.ini, and the rest of the
> +  ;; elements is a containing the content of the config files
> +  ;; (user.js, userChrome.css, userContent.css)
> +  (define (serialize-profiles profiles)
> +    (match profiles
> +      (($ <icecat-profile> location default? name id
> +                           settings user-chrome user-content)
> +       (let ((profile-path (if default? "default" name))
> +             (file-name (string-append "icecat-" name "-profile")))
> +         (filter
> +          (compose not null?)
> +          `(((,(format #f "Profile~a" id)
> +              ((default . ,(if default? 1 0))
> +               (is-relative . 1)
> +               (name . ,(string-capitalize name))
> +               (path . ,profile-path))))
> +            ,(optional (not (null? settings))

if or when is better here, because arguments won't be evaluated if
condition is #f 

> +                       (list
> +                        (format #f "~a/~a/user.js"
> +                                %icecat-config-path profile-path)
> +                        (mixed-text-file
> +                         (string-append file-name "-settings")
> +                         (serialize-settings settings))))
> +            ,(optional (not (string=? user-chrome ""))
> +                       (list
> +                        (format #f "~a/~a/chrome/userChrome.css"
> +                                %icecat-config-path profile-path)
> +                        (mixed-text-file
> +                         (string-append file-name "-user-chrome")
> +                         user-chrome)))
> +            ,(optional (not (string=? user-content ""))
> +                       (list
> +                        (format #f "~a/~a/chrome/userContent.css"
> +                                %icecat-config-path profile-path)
> +                        (mixed-text-file
> +                         (string-append file-name "-user-content")
> +                         user-content)))))))))
> +
> +  (match config
> +    (($ <icecat-configuration> location package profiles)
> +     (begin
> +       (check-only-one-default (map icecat-profile-default? profiles))
> +       (check-duplicate-field "name" (map icecat-profile-name profiles))
> +       (check-duplicate-field "id" (map icecat-profile-id profiles))
> +       (let* ((configs (map serialize-profiles profiles))
> +              (profile-ini (append '((General
> +                                      ((start-with-last-profile . 1))))
> +                                   (append-map first configs))))
> +         (define (serialize-field key val)
> +           (let ((val (cond
> +                       ((boolean? val) (if val 1 0))
> +                       (else val))))
> +             (format #f "~a=~a\n" (object->camel-case-string key 'upper) val)))
> +         `((,(format #f "~a/profiles.ini" %icecat-config-path)
> +            ,(mixed-text-file
> +              "icecat-profile-ini"
> +              (generic-serialize-ini-config
> +               #:serialize-field serialize-field
> +               #:fields profile-ini)))
> +           ,@(flatten (map rest configs))))))))

Why not just apply append?

> +
> +(define home-icecat-service-type
> +  (service-type (name 'home-icecat)
> +                (extensions
> +                 (list (service-extension
> +                        home-files-service-type
> +                        icecat-files-service)
> +                       (service-extension
> +                        home-profile-service-type
> +                        icecat-profile-service)))))

> base-commit: ee8140d920f15aa68434b10617379d3a3bafd3e1
> -- 
> 2.31.1

Thank you for the service! Applied, added fixes and slightly
refactored. I fixed only most important things, not addressed some
comments, you can add other updates on top of master.
Details
Message ID
<87y2cehjm5.fsf@yoctocell.xyz>
In-Reply-To
<87v97m7p4q.fsf@trop.in> (view parent)
DKIM signature
pass
Download raw message
On Thu, May 13 2021, Andrew Tropin wrote:

>> +(define (icecat-files-service config)
>> +  (define (serialize-field key val)
>> +    (let ((val (cond
>> +                ((boolean? val) => boolean->true-or-false)
>
> (boolean? val) will be passed to boolean->true-or-false and it will be
> always #t.

Oops, good catch.

>> +                (else val))))
>> +      (format #f "user_pref(\"~a\", ~a);\n" key val)))
>
> Won't work for string values.

Good catch!

>> +
>> +  (define (serialize-settings settings)
>> +    (generic-serialize-alist string-append serialize-field settings))
>
> Doesn't support gexps.  Not sure that they really needed, but
> implemented support for them.

Yeah, I intentionally didn’t add support for Gexps because I don’t see a
use case for them.

>> +  (define (check-only-one-default defaults)
>> +    (if (= (length (filter identity defaults)) 1)
>> +        #t
>> +        (raise (formatted-message
>> +                (G_ "Only one `icecat-profile' in `icecat-configuration' can \
>> +be the default profile.")))))
>> +
>> +  ;; Return a list where the first element is a list of alists
>> +  ;; representing the content of profiles.ini, and the rest of the
>> +  ;; elements is a containing the content of the config files
>> +  ;; (user.js, userChrome.css, userContent.css)
>> +  (define (serialize-profiles profiles)
>> +    (match profiles
>> +      (($ <icecat-profile> location default? name id
>> +                           settings user-chrome user-content)
>> +       (let ((profile-path (if default? "default" name))
>> +             (file-name (string-append "icecat-" name "-profile")))
>> +         (filter
>> +          (compose not null?)
>> +          `(((,(format #f "Profile~a" id)
>> +              ((default . ,(if default? 1 0))
>> +               (is-relative . 1)
>> +               (name . ,(string-capitalize name))
>> +               (path . ,profile-path))))
>> +            ,(optional (not (null? settings))
>
> if or when is better here, because arguments won't be evaluated if
> condition is #f 
>
>> +                       (list
>> +                        (format #f "~a/~a/user.js"
>> +                                %icecat-config-path profile-path)
>> +                        (mixed-text-file
>> +                         (string-append file-name "-settings")
>> +                         (serialize-settings settings))))
>> +            ,(optional (not (string=? user-chrome ""))
>> +                       (list
>> +                        (format #f "~a/~a/chrome/userChrome.css"
>> +                                %icecat-config-path profile-path)
>> +                        (mixed-text-file
>> +                         (string-append file-name "-user-chrome")
>> +                         user-chrome)))
>> +            ,(optional (not (string=? user-content ""))
>> +                       (list
>> +                        (format #f "~a/~a/chrome/userContent.css"
>> +                                %icecat-config-path profile-path)
>> +                        (mixed-text-file
>> +                         (string-append file-name "-user-content")
>> +                         user-content)))))))))
>> +
>> +  (match config
>> +    (($ <icecat-configuration> location package profiles)
>> +     (begin
>> +       (check-only-one-default (map icecat-profile-default? profiles))
>> +       (check-duplicate-field "name" (map icecat-profile-name profiles))
>> +       (check-duplicate-field "id" (map icecat-profile-id profiles))
>> +       (let* ((configs (map serialize-profiles profiles))
>> +              (profile-ini (append '((General
>> +                                      ((start-with-last-profile . 1))))
>> +                                   (append-map first configs))))
>> +         (define (serialize-field key val)
>> +           (let ((val (cond
>> +                       ((boolean? val) (if val 1 0))
>> +                       (else val))))
>> +             (format #f "~a=~a\n" (object->camel-case-string key 'upper) val)))
>> +         `((,(format #f "~a/profiles.ini" %icecat-config-path)
>> +            ,(mixed-text-file
>> +              "icecat-profile-ini"
>> +              (generic-serialize-ini-config
>> +               #:serialize-field serialize-field
>> +               #:fields profile-ini)))
>> +           ,@(flatten (map rest configs))))))))
>
> Why not just apply append?

Oh, that would also work.

> Thank you for the service! Applied, added fixes and slightly
> refactored. I fixed only most important things, not addressed some
> comments, you can add other updates on top of master.

Thanks for the review!  I will add some additional fixes. :)
Details
Message ID
<CABrWRW0vgWBSGaN4MG+GiZ-2rd1t8Zf+-rHn5jKMkvZYFBkOpw@mail.gmail.com>
In-Reply-To
<87y2cehjm5.fsf@yoctocell.xyz> (view parent)
DKIM signature
missing
Download raw message
> I will add some additional fixes. :)

Saw your changes, good job!)
Reply to thread Export thread (mbox)