diff mbox series

[bug#62806] gnu: home: services: fontutils: Add support for SXML fragments.

Message ID 20230413034059.5585-1-andrewpatt7@gmail.com
State New
Headers show
Series [bug#62806] gnu: home: services: fontutils: Add support for SXML fragments. | expand

Commit Message

Andrew Patterson April 13, 2023, 3:40 a.m. UTC
* gnu/home/services/fontutils.scm (add-fontconfig-config-file): Add
support for adding arbitrary SXML configuration into fonts.conf;
* doc/guix.texi (Fonts Services): Update the documentation.
---
One of the main reasons I haven't started using guix home is that I use
fonts.conf for setting default fonts, which guix home doesn't work with.
This patch fixes that issue, by letting you add arbitrary XML to
fonts.conf via SXML. 

 doc/guix.texi                   | 16 +++++++++-----
 gnu/home/services/fontutils.scm | 38 ++++++++++++++++++++++++++-------
 2 files changed, 41 insertions(+), 13 deletions(-)


base-commit: 60c97c60a53686ec321eb541b85e01b6decc2014

Comments

Ludovic Courtès April 24, 2023, 8:41 p.m. UTC | #1
Hi,

Andrew Patterson <andrewpatt7@gmail.com> skribis:

> * gnu/home/services/fontutils.scm (add-fontconfig-config-file): Add
> support for adding arbitrary SXML configuration into fonts.conf;
> * doc/guix.texi (Fonts Services): Update the documentation.
> ---
> One of the main reasons I haven't started using guix home is that I use
> fonts.conf for setting default fonts, which guix home doesn't work with.
> This patch fixes that issue, by letting you add arbitrary XML to
> fonts.conf via SXML. 

Nice!  You’re the third person looking into this, which shows there’s a
real need.  :-)

  https://issues.guix.gnu.org/62145
  https://issues.guix.gnu.org/57963

I like that your patch is simple (it doesn’t try to do anything beyond
serializing SXML); perhaps there are ideas to borrow from the patch by
Taiju HIGASHI?

OTOH it’s less convenient to use for someone who’s not familiar with the
XML schema of ‘fonts.conf’ than what the patch by conses does.

I think we should really move forward on this.  Because it’s not
invasive, this patch sounds like the path of least resistance.

What are your thoughts, people?  What should we choose?  :-)

Ludo’.
Andrew Patterson April 24, 2023, 11:24 p.m. UTC | #2
On Mon, 2023-04-24 at 22:41+02, Ludovic Courtès <ludo@gnu.org> 
wrote:

> Nice!  You’re the third person looking into this, which shows 
> there’s a
> real need.  :-)
>
>   https://issues.guix.gnu.org/62145
>   https://issues.guix.gnu.org/57963
>
> I like that your patch is simple (it doesn’t try to do anything 
> beyond
> serializing SXML); perhaps there are ideas to borrow from the 
> patch by
> Taiju HIGASHI?
>
> OTOH it’s less convenient to use for someone who’s not familiar 
> with the
> XML schema of ‘fonts.conf’ than what the patch by conses does.
>
> I think we should really move forward on this.  Because it’s not
> invasive, this patch sounds like the path of least resistance.

Thanks!

> What are your thoughts, people?  What should we choose?  :-)

Brain dump below:

My patch was an attempt to do the least work to get fontconfig
configuration working, so I agree on it being the simplest option.
(As I would, being it's author.)
Whatever we end up with shouldn't break existing configurations, 
of
course, and should have /some/ way to add arbitrary XML 
configuration,
preferably as SXML.

Both general principles and the other patches suggest we should
have an actual configuration record, though, with slots for
default font families, additional font directories, and extra SXML
config.  IMHO, the main design question for this is whether the
default font family slots should be single font family names,
leaving setting up default fonts with fallback fonts as a complex
case written in SXML, or should be a list of font families.
The list of font families is more annoying for the common case, 
but
my fonts.conf does have fallback defaults, so it is useful.

home-fontconfig-service-type probably should be taken out of
%base-home-services, as Taiju HAGASHI's patch eventually did, but
that scope creep looks like it was part of why the patch went
nowhere.

I like the idea of conses' <font-spec> record, but it seems like
it'd be awkward in practice?  An example config might help.

My write-fontconfig-doctype hack was definitely a bad idea: 
calling
thunks in the SXML with the output port as current-output-port
doesn't seem to be a purposeful feature, and just writing the
doctype tag separately is more clear.

It seems to me that the main options are:
1) Just use my patch, or
2) write a new patch with an actual configuration record type,
   based on conses and Taiju HAGASHI's patches, either with
   a) a single font family for the default font family settings,
   b) a list of font families for the default font families, or
   c) allowing either.

If we don't want to just use my patch, I can work on a new patch
with a configuration record.  How do you print a deprecation
warning?
Ludovic Courtès May 11, 2023, 12:34 p.m. UTC | #3
Hi Andrew,

Sorry for the delay and thanks for your feedback.

Andrew Patterson <andrewpatt7@gmail.com> skribis:

> It seems to me that the main options are:
> 1) Just use my patch, or
> 2) write a new patch with an actual configuration record type,
>   based on conses and Taiju HAGASHI's patches, either with
>   a) a single font family for the default font family settings,
>   b) a list of font families for the default font families, or
>   c) allowing either.

I went with #1, but that doesn’t prevent us from considering #2 as an
improvement going forward.  Conses, Andrews: you’re welcome to share
your thoughts!

> If we don't want to just use my patch, I can work on a new patch
> with a configuration record.  How do you print a deprecation
> warning?

The (guix deprecation) module provides facilities for that.  If that’s
too restrictive, use ‘warning’ from (guix diagnostics).

Thanks!

Ludo’.
Andrew Tropin May 12, 2023, 6:45 a.m. UTC | #4
On 2023-05-11 14:34, Ludovic Courtès wrote:

> Hi Andrew,
>
> Sorry for the delay and thanks for your feedback.
>
> Andrew Patterson <andrewpatt7@gmail.com> skribis:
>
>> It seems to me that the main options are:
>> 1) Just use my patch, or
>> 2) write a new patch with an actual configuration record type,
>>   based on conses and Taiju HAGASHI's patches, either with
>>   a) a single font family for the default font family settings,
>>   b) a list of font families for the default font families, or
>>   c) allowing either.
>
> I went with #1, but that doesn’t prevent us from considering #2 as an
> improvement going forward.  Conses, Andrews: you’re welcome to share
> your thoughts!

The implementation LGTM and probably it covers most of use cases
mentioned on the related threads, however, I'm a little bit rusty on
this topic and can't say it for sure :)

I think Miguel (conses) have more to say on this, because AFAIR he
recently did something related to fontconfig configuration.

>
>> If we don't want to just use my patch, I can work on a new patch
>> with a configuration record.  How do you print a deprecation
>> warning?
>
> The (guix deprecation) module provides facilities for that.  If that’s
> too restrictive, use ‘warning’ from (guix diagnostics).
>
> Thanks!
>
> Ludo’.
Miguel Ángel Moreno May 18, 2023, 9:11 a.m. UTC | #5
On 2023-05-12 10:45, Andrew Tropin wrote:

> On 2023-05-11 14:34, Ludovic Courtès wrote:
>
>> Hi Andrew,
>>
>> Sorry for the delay and thanks for your feedback.
>>
>> Andrew Patterson <andrewpatt7@gmail.com> skribis:
>>
>>> It seems to me that the main options are:
>>> 1) Just use my patch, or
>>> 2) write a new patch with an actual configuration record type,
>>>   based on conses and Taiju HAGASHI's patches, either with
>>>   a) a single font family for the default font family settings,
>>>   b) a list of font families for the default font families, or
>>>   c) allowing either.
>>
>> I went with #1, but that doesn’t prevent us from considering #2 as an
>> improvement going forward.  Conses, Andrews: you’re welcome to share
>> your thoughts!
>
> The implementation LGTM and probably it covers most of use cases
> mentioned on the related threads, however, I'm a little bit rusty on
> this topic and can't say it for sure :)
>

Yeah, I think it's not as intrusive as Taiju's or mine.

> I think Miguel (conses) have more to say on this, because AFAIR he
> recently did something related to fontconfig configuration.
>

Not really, since this is more of a general approach, we can add the
font records and default families as part of RDE for those who want a
more batteries-included approach.

>>
>>> If we don't want to just use my patch, I can work on a new patch
>>> with a configuration record.  How do you print a deprecation
>>> warning?
>>
>> The (guix deprecation) module provides facilities for that.  If that’s
>> too restrictive, use ‘warning’ from (guix diagnostics).
>>
>> Thanks!
>>
>> Ludo’.
diff mbox series

Patch

diff --git a/doc/guix.texi b/doc/guix.texi
index acb6f0c2e1..f1cfdd77f4 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -42968,8 +42968,10 @@  library is used by many applications to access fonts on the system.
 
 @defvar home-fontconfig-service-type
 This is the service type for generating configurations for Fontconfig.
-Its associated value is a list of strings (or gexps) pointing to fonts
-locations.
+Its associated value is a list of either strings (or gexps) pointing to
+fonts locations, or SXML (@pxref{SXML,,, guile, GNU Guile Reference
+Manual}) fragments to be converted into XML and put inside the main
+@code{fontconfig} node.
 
 Generally, it is better to extend this service than to directly
 configure it, as its default value is the default Guix Home's profile
@@ -42977,13 +42979,17 @@  font installation path (@file{~/.guix-home/profile/share/fonts}).  If
 you configure this service directly, be sure to include the above
 directory.
 
-A typical extension for adding an additional font directory might look
-like this:
+A typical extension for adding an additional font directory and setting
+a font as the default monospace font might look like this:
 
 @lisp
 (simple-service 'additional-fonts-service
                 home-fontconfig-service-type
-                (list "~/.nix-profile/share/fonts"))
+                (list "~/.nix-profile/share/fonts"
+                      '(alias
+                        (family "monospace")
+                        (prefer
+                         (family "Liberation Mono")))))
 @end lisp
 @end defvar
 
diff --git a/gnu/home/services/fontutils.scm b/gnu/home/services/fontutils.scm
index 3399cb7ec8..0e60bc2035 100644
--- a/gnu/home/services/fontutils.scm
+++ b/gnu/home/services/fontutils.scm
@@ -2,6 +2,7 @@ 
 ;;; Copyright © 2021 Andrew Tropin <andrew@trop.in>
 ;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
 ;;; Copyright © 2023 Giacomo Leidi <goodoldpaul@autistici.org>
+;;; Copyright © 2023 Andrew Patterson <andrewpatt7@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -23,6 +24,8 @@  (define-module (gnu home services fontutils)
   #:use-module (gnu packages fontutils)
   #:use-module (guix gexp)
   #:use-module (srfi srfi-1)
+  #:use-module (ice-9 match)
+  #:use-module (sxml simple)
 
   #:export (home-fontconfig-service-type))
 
@@ -35,17 +38,36 @@  (define-module (gnu home services fontutils)
 ;;;
 ;;; Code:
 
-(define (add-fontconfig-config-file directories)
+(define (write-fontconfig-doctype)
+  "Prints fontconfig's DOCTYPE to current-output-port."
+  ;; This is necessary because SXML doesn't seem to have a way to represent a doctype,
+  ;; but sxml->xml /does/ currently call any thunks in the SXML with the XML output port
+  ;; as current-output-port, allowing the output to include arbitrary text instead of
+  ;; just properly quoted XML.
+  (format #t "<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>"))
+
+(define (config->sxml config)
+  "Converts a <home-fontconfig-configuration> record into the SXML representation
+of fontconfig's fonts.conf file."
+  (define (snippets->sxml snippet)
+    (match snippet
+      ((or (? string? dir)
+           (? gexp? dir))
+       `(dir ,dir))
+      ((? list?)
+       snippet)))
+  `(*TOP* (*PI* xml "version='1.0'")
+          ,write-fontconfig-doctype
+          (fontconfig
+           ,@(map snippets->sxml config))))
+
+(define (add-fontconfig-config-file config)
   `(("fontconfig/fonts.conf"
      ,(mixed-text-file
        "fonts.conf"
-       (apply string-append
-              `("<?xml version='1.0'?>
-<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
-<fontconfig>\n" ,@(map (lambda (directory)
-                         (string-append "  <dir>" directory "</dir>\n"))
-                       directories)
-                "</fontconfig>\n"))))))
+       (call-with-output-string
+         (lambda (port)
+           (sxml->xml (config->sxml config) port)))))))
 
 (define (regenerate-font-cache-gexp _)
   `(("profile/share/fonts"