On 2022-01-09 20:44, Liliana Marie Prikler wrote: > Hi, > > Am Sonntag, dem 09.01.2022 um 20:48 +0300 schrieb Andrew Tropin: >> On 2022-01-09 12:19, Liliana Marie Prikler wrote: >> >> > Hi Andrew, >> > >> > Am Sonntag, dem 09.01.2022 um 12:12 +0300 schrieb Andrew Tropin: >> > >> > > Before fee0bc serialization for text-config worked this way: >> > > --8<---------------cut here---------------start------------->8--- >> > > `("string here" >> > >   ,#~"string valued gexp" >> > >   "source \" >> > >   ,(local-file "blabla.sh")) >> > > --8<---------------cut here---------------end--------------->8--- >> > > >> > > would yield something like: >> > > >> > > --8<---------------cut here---------------start------------->8--- >> > > string here >> > > string valued gexp >> > > source \ >> > > /gnu/store/00fl96dj2aak4i1vqvdqzlhbmmskc7fx-blabla.sh >> > > --8<---------------cut here---------------end--------------->8--- >> > > >> > > [...] >> > > >> > > The new text-config serialization implementation (after fee0bc >> > > commit) doesn't support gexps and tries to insert the literal >> > > content >> > > of the file in place where file-like object was used[.] >> > I agree that the old one looks nicer in this context, but wasn't >> > the new one introduced to solve the issue of (slurp-file-gexp) in >> > the importer?  Meaning whichever way we go, we need something that >> > allows us to insert literal file contents of another file at more >> > or less G- exp compile time. >> > >> >> From my experience the usage of slurp-file-gexp is somewhat really >> rare, so I didn't upstream it originally, keeping in mind that it is >> possible to use the gexp mentioned below directly and that later we >> can add slurp-file-gexp or alternative if necessary.  Just missed >> that importer already uses it. >> >> We could just do something like that instead of slurp-file-gexp: >> --8<---------------cut here---------------start------------->8--- >> #~(call-with-input-file #$(local-file "./files/bashrc") >>     (@ (ice-9 textual-ports) get-string-all)) >> --8<---------------cut here---------------end--------------->8--- >> >> Or just take the implementation >> https://git.sr.ht/~abcdw/rde/tree/47f6c65c82a4f6761fa1ff5b9405b363cfda6482/gnu/home-services-utils.scm#L90 >> and rename it to read-file-content-gexp or somewhat more apropriate >> and use it. > Using ill-defined slurp-patterns at all just adds ways of shooting > yourself in the foot. You're turning Guix into an ouroboros that reads > itself inside-out. Better restrict such patterns to where they cause > the least harm and make their effects very explicit. Not sure what you mean. >> > Perhaps that issue could be solved, if instead the importer just >> > reads the file contents and declares it as a variable as in (define >> > %bashrc " ;; Original contents of bashrc ") (define bashrc (plain- >> > file %bashrc)). >> > >> > WDYT? >> >> Another possible solution, but I would prefer to stick with the >> direct usage of gexp with the code for reading a file, because >> importer is intended for creation of an example configuration and >> user will need to continue the work on it and copying the content of >> bashrc and other configs to scheme files, escaping string can be a >> little tedious. > There is certainly a tradeoff here, but I think explicitly showing > (plain-file CONTENT) is the right approach here. Users are going to > figure out mixed-text-file exists soon enough. As for proper string > escaping, that's not really an excuse imo -- pretty-print exists and > you can use it. Yep, of course it possible, but I mean that the whole point of escape hatch is to make it possible to reuse existing files directly whithout any manipulation on them and importer should demonstrate how to do it. If importer internally do some manipulation (escaping) with the content of the file and places the result in the string in scheme file, user won't be able to replicate such process easily for other services, which not covered by the importer. If I understood correctly what you meant in the first message. >> read-everything-from-file is just a shorthand for >> >> --8<---------------cut here---------------start------------->8--- >> #~(begin >>     (use-modules (ice-9 rdelim)) >>     (with-fluids ((%default-port-encoding "UTF-8")) >>       (with-input-from-file #$COMPUTED_FILE_CALL_HERE read-string))) >> --8<---------------cut here---------------end--------------->8--- >> >> a gexp used in >> https://git.savannah.gnu.org/cgit/guix.git/tree/gnu/services/configuration.scm?h=2c451db39aabc69bdbf186f412ee6e0b4e180ccb#n386 >> >> The example was already verbose, so I decided to simplify it a little >> bit. >> >> Actually, it's very similar to what slurp-file-gexp does, but it's >> moved inside serializer and hidden from user.  Why not to give it to >> the user and eleminate two more layers of wrapping in gexps and file- >> likes. > That's like saying "memory management already exists, but it's hidden > from the user, why not let them play around with malloc?" In > programming languages that aren't C/C++, abstractions ought to make it > harder to shoot yourself in the foot. You (in my POV correctly) > pointed out that our current handling of text configs makes it very > easy to shoot yourself in the foot and is therefore badly abstracted. Mostly my point was that it's more intuitive to expect that file-like objects get serialized to the file path in the store and string-valued gexps to the strings (as they does when we use them in mixed-text-file for example), but new approach doesn't allow to use gexps directly and serializes file-likes to it's content and requires much more hassle. In both cases it's possible to use both gexps and file-likes, but in the second one we have a few more levels of nestiness of gexps inside file-likes inside gexps, which seems unecessary. > The point I'm making is that we shouldn't swap out one bad abstraction > for another, but pave the road towards good abstractions, e.g. G- > expressions in the way the rest of Guix typically uses them. Actually, for me, the original implementation looks consistent with how the rest of Guix treats G-expressions (uses already known abstraction) and only new one intoduces a new abstraction. We can treat slurp-file-gexp as an abstraction here, but actually 1. this is more a tiny helper function, than an abstraction. On 2022-01-09 20:00, Maxime Devos wrote: > That would avoid having to remember the (call-with-input-file ...) > trick. 2. this function is not really necessary. > > Now one thing I had not considered back in my previous mail was that we > want to be able to compose bashrc together from multiple sources, so > having the field be just one file-like object probably won't cut it. > However, we can let it be a list of file like objects (with a field > sanitizer transparently turning a single file-like object into a list > either silently or loudly). And within those file-like objects, we can > use the usual semantics. I considered this option, but the problem is that we can't control the place where the content will be inserted. Let's assume it will go at the end of the bashrc (we can demonstrate the similar if it will be added to the beginning). (home-bash-configuration (bashrc (list "call_function_from_lib_A()")) (bashrc-content (list (local-file "lib_A.sh")))) which will make a call before lib_A loaded. Also, it's already possible to achieve the same with gexps/file-like in both new and old text-config implementations. In reality, it's rarely needed to insert the content directly, in most cases it better to source/include/whatever file from the store. With old implementation it will look like: (home-bash-configuration (bashrc (list "source \\" (local-file "lib_A.sh") ;; Or an alternative way to do the same with gexp ;; #~(format #f "source ~a" #$(local-file "lib_A.sh")) "call_function_from_lib_A()"))) With new implementation: (home-bash-configuration (bashrc (list "source \\" (mixed-text-file "unecessary-name" (local-file "lib_A.sh")) ;; Or an alternative way to do the same with gexp ;; (computed-file ;; "unecessary-name" ;; #~(format #f "source ~a" #$(local-file "lib_A.sh"))) "call_function_from_lib_A()"))) which not that bad, but still looks more verbose, less intuitive and consistent with the rest of the Guix (at least in my perception of it). * All the code examples are in a pseudocode and maybe don't work and used mostly to demonstarte the idea, provide a feeling of how final configurations look. > > I'm not sure how the current implementation of Guix Home handles > composition, but I believe the root of the issue probably stems from > there in some capacity. Might want to check what our requirements are. It's offtopic, but when you will have time please take a look at https://issues.guix.gnu.org/52388. -- Best regards, Andrew Tropin