guix-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: RFC: new syntax for inline patches


From: Liliana Marie Prikler
Subject: Re: RFC: new syntax for inline patches
Date: Thu, 06 Jan 2022 07:43:46 +0100
User-agent: Evolution 3.42.1

Hi,

Am Donnerstag, dem 06.01.2022 um 02:20 +0100 schrieb Jelle Licht:
> > 
> > 
> > > Here’s a colour sample for the new bikeshed:
> > > 
> > >   (arguments
> > >     (list
> > >       #:patches
> > >       #~(patch "the-file"
> > >          ((line 10)
> > >           (+ "I ONLY WANTED TO ADD THIS LINE"))
> > >          ((line 3010)
> > >           (- "maybe that’s better")
> > >           (+ (string-append #$guix " is better"))
> > >           (+ "but what do you think?")))))
> > Now this thing is again just as brittle as the patch it encodes and
> > if I know something about context-less patches then it's that
> > they're super not trustworthy.
> 
> What do you mean here, with 'brittle' and 'trustworthy'? Is it the
> fact that line numbers are hardcoded, compared to the substitute*
> approach?
What Ricardo is writing here as a colour sample is a context-less diff
and if you've ever worked with those, then you'll know they apply
exactly without context.  So that line 10 is stuck there, it doesn't
move with regards to whatever entity is interesting at line 10.  The
second hunk is better in that it needs a line to match and replace, but
it throws an error if it doesn't find that at line 3010, even if it'd
exist and 3020 or 2048.

Now with substitute*s, you also need to account for wrong regexps, both
matching too many and too few lines (including the notorious 0, that
has sparked many a religious debate whether substitute* is safe
actually), so you might call that an even tradeoff.  However,
substitute is still more flexible in what it does than the proposed
patch objects.  Particularly, even if we added context, which would
trade away some of the nice look of it, we now have to go into and
manually regenerate our broken patches rather than using existing merge
tools with our plain old file patches.

> > However, have you considered that something similar has been lying
> > around in our codebase all this time and 99% of the packages ignore
> > it because it's so obscure and well hidden?  Why yes, of course I'm
> > talking about emacs-batch-edit-file.
> > 
> > Now of course there are some problems when it comes to invoking
> > Emacs inside Guix build.  For one, not every package has emacs-
> > minimal available at build time and honestly, that's a shame.  Even
> > then, you'd have to dance around and add emacs-utils to enable it. 
> > And after that?  You code Emacs Lisp in the middle of Guile code! 
> > Now certainly, this UI can be improved.
> 
> > Particularly, I'd propose a set of monadic functions that operate
> > on a buffer in much the same way Emacs does.  Now we wouldn't need
> > to implement all of Emacs in that way (though we certainly could if
> > given enough time).
> > 
> > Basic primitives would be the following to name a few: search-
> > forward, re-search-forward, goto-char, forward-line, point-min,
> > insert, beginning-of-line, end-of-line, delete-region, point.  Of
> > course we could rename them to be more guily, but that's a minor
> > concern imo. Notice how I omitted find-file and save-buffer,
> > because that should be taken care of by the monad.
> 
> I'd prefer something that is declarative in the sense that the 'how'
> is abstracted away, with a focus on the 'what'; both Ricardo's
> proposal and emacs-batch-edit-file do this, and to a much lesser
> extent the current substitute* mess. 'Navigation primitives' as you
> propose here are perhaps abstract in the technical sense of the
> phrase, but still indicate to me a focus on the 'how' instead of the
> 'what'.
I don't think you understood me correctly there.  The monadic
procedures I propose would implement a subset of Emacs' buffer
operations – we can bikeshed about what set of Emacs, so that the set
lets you focus on the 'how' instead of the 'what' – only inside Scheme
and inside some well-known (guix build) module.

Consider the translation of e.g. 
(emacs-batch-edit-file "foo.org"
  '(progn (goto-char (point-max))
          (insert "More content.")
          (basic-save-buffer))) 
to
(with-buffer "foo.org"
  (goto-char (point-max))
  (insert "More content."))
which would roughly equate to
(run-with-buffer (open-buffer "foo.org")
  (lambda (buffer-monad)
    (return [something magical going on here])))
where run-with-buffer would do an atomic file replacement which
temporarily creates a buffer monad for the translation from in to out.

> Another nice property of keeping these concerns separated is that it
> should be easy (or at least possible) to later reimplement
> e.g. Ricardo's proposal on top of such monadic primitives.  Doing it
> the other way around seems much less fun, if even feasible at all :-
> ).
I haven't heard about diff being Turing-complete while Emacs
demonstrably is, so buffer monads would be somewhere in between.

> > WDYT, should we pursue that?  Or should we just add an Emacs to our
> > native inputs?  :P
> 
> At the risk of escalating this perhaps-not-totally-serious proposal,
> I wrote some snippets that should allow one to write elisp in
> g-expressions using guile's built-in elisp reader + some hacks to
> serialize guile's internal representation of parsed elisp to valid
> elisp again.
I don't think we would need to use G-expressions here, because we would
have to quote or quasi-quote the batch-edit-file expression anyway and
if we do the latter, we can insert store references using the usual set
of primitives that you'd expect inside a build phase, e.g. search-
input-file.  However, that's still a cool thing.

Cheers



reply via email to

[Prev in Thread] Current Thread [Next in Thread]