* Editing Scheme in the installation image
@ 2017-01-05 23:05 Ludovic Courtès
2017-01-06 1:54 ` Kei Kebreau
` (3 more replies)
0 siblings, 4 replies; 12+ messages in thread
From: Ludovic Courtès @ 2017-01-05 23:05 UTC (permalink / raw)
To: guix-devel; +Cc: Mike Gran
[-- Attachment #1: Type: text/plain, Size: 532 bytes --]
Hello Guix!
One issue that’s often reported is that it’s inconvenient to edit the
config file with all its parentheses in the installation image given the
available options (Zile, Nano, and nvi).
Something like Paredit and ‘show-paren-mode’ in Emacs would help avoid
mistakes such as unbalanced parenthesis. However ‘emacs-minimal’ takes
180 MiB and it would be unreasonable to include it.
So I figured we could use Zile-on-Guile¹ (yes!) and extend it to have
something that resembles Paredit, like:
[-- Attachment #2: Type: text/x-scheme, Size: 259 bytes --]
;; Poor developer’s Paredit.
(define (paredit-open-paren)
(insert "()")
(backward-char))
(define (paredit-close-paren)
(unless (search-forward ")")
(insert ")")))
(set-key "(" 'paredit-open-paren)
(set-key ")" 'paredit-close-paren)
[-- Attachment #3: Type: text/plain, Size: 400 bytes --]
Of course, it takes more than these few lines to write a real Paredit,
but still, wouldn’t it be cool? :-)
What do people (Mike in particular!) think?
Ludo’.
¹ https://www.gnu.org/software/guix/packages/z.html#zile-on-guile
PS: The closure of Zile-on-Guile is 103 MiB, but Zile-on-Guile itself is
only 400K and its dependencies are already in the installation
image.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Editing Scheme in the installation image
2017-01-05 23:05 Editing Scheme in the installation image Ludovic Courtès
@ 2017-01-06 1:54 ` Kei Kebreau
2017-01-06 9:09 ` Ricardo Wurmus
` (2 subsequent siblings)
3 siblings, 0 replies; 12+ messages in thread
From: Kei Kebreau @ 2017-01-06 1:54 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: guix-devel, Mike Gran
[-- Attachment #1: Type: text/plain, Size: 1402 bytes --]
ludo@gnu.org (Ludovic Courtès) writes:
> Hello Guix!
>
> One issue that’s often reported is that it’s inconvenient to edit the
> config file with all its parentheses in the installation image given the
> available options (Zile, Nano, and nvi).
>
> Something like Paredit and ‘show-paren-mode’ in Emacs would help avoid
> mistakes such as unbalanced parenthesis. However ‘emacs-minimal’ takes
> 180 MiB and it would be unreasonable to include it.
>
> So I figured we could use Zile-on-Guile¹ (yes!) and extend it to have
> something that resembles Paredit, like:
>
> ;; Poor developer’s Paredit.
>
> (define (paredit-open-paren)
> (insert "()")
> (backward-char))
>
> (define (paredit-close-paren)
> (unless (search-forward ")")
> (insert ")")))
>
> (set-key "(" 'paredit-open-paren)
> (set-key ")" 'paredit-close-paren)
>
>
> Of course, it takes more than these few lines to write a real Paredit,
> but still, wouldn’t it be cool? :-)
>
> What do people (Mike in particular!) think?
>
> Ludo’.
>
> ¹ https://www.gnu.org/software/guix/packages/z.html#zile-on-guile
>
> PS: The closure of Zile-on-Guile is 103 MiB, but Zile-on-Guile itself is
> only 400K and its dependencies are already in the installation
> image.
This sounds useful! Provided that everything is stable in Zile-on-Guile,
I'm for this inclusion.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Editing Scheme in the installation image
2017-01-05 23:05 Editing Scheme in the installation image Ludovic Courtès
2017-01-06 1:54 ` Kei Kebreau
@ 2017-01-06 9:09 ` Ricardo Wurmus
2017-01-06 13:49 ` Mike Gran
2017-01-07 16:00 ` Christopher Allan Webber
3 siblings, 0 replies; 12+ messages in thread
From: Ricardo Wurmus @ 2017-01-06 9:09 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: guix-devel, Mike Gran
Ludovic Courtès <ludo@gnu.org> writes:
> One issue that’s often reported is that it’s inconvenient to edit the
> config file with all its parentheses in the installation image given the
> available options (Zile, Nano, and nvi).
>
> Something like Paredit and ‘show-paren-mode’ in Emacs would help avoid
> mistakes such as unbalanced parenthesis. However ‘emacs-minimal’ takes
> 180MiB and it would be unreasonable to include it.
>
> So I figured we could use Zile-on-Guile¹ (yes!) and extend it to have
> something that resembles Paredit, like:
Haha, that’s very cute! It’s a great idea.
> PS: The closure of Zile-on-Guile is 103MiB, but Zile-on-Guile itself is
> only 400K and its dependencies are already in the installation
> image.
Excellent!
~~
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Editing Scheme in the installation image
2017-01-05 23:05 Editing Scheme in the installation image Ludovic Courtès
2017-01-06 1:54 ` Kei Kebreau
2017-01-06 9:09 ` Ricardo Wurmus
@ 2017-01-06 13:49 ` Mike Gran
2017-01-07 11:54 ` Ludovic Courtès
2017-01-07 16:00 ` Christopher Allan Webber
3 siblings, 1 reply; 12+ messages in thread
From: Mike Gran @ 2017-01-06 13:49 UTC (permalink / raw)
To: Ludovic Courtès, guix-devel
On Thursday, January 5, 2017 3:05 PM, Ludovic Courtès <ludo@gnu.org> wrote:
> Hello Guix!
> One issue that’s often reported is that it’s inconvenient to edit the
> config file with all its parentheses in the installation image given the
> available options (Zile, Nano, and nvi).
> Something like Paredit and ‘show-paren-mode’ in Emacs would help avoid
> mistakes such as unbalanced parenthesis. However ‘emacs-minimal’ takes
> 180 MiB and it would be unreasonable to include it.
> So I figured we could use Zile-on-Guile¹ (yes!) and extend it to have
> something that resembles Paredit, like:
> Of course, it takes more than these few lines to write a real Paredit,
> but still, wouldn’t it be cool? :-)
> What do people (Mike in particular!) think?
Could work, but, there are caveats.
This Zile fork, and upstream Zile, have characters restricted to 8-bits
in most places. It also will not do any bi-directional characters
or double-width characters. For non-ASCII config files, Zile-on-Guile
might be too limited.
The functions expressed in Scheme in Zile-on-Guile are the same
as upstream Zile had. It is a fairly limited set.
Zile-on-Guile is a Scheme, not an elisp, even though the functions
it expresses have elisp-like names. So there is little portability
between Emacs and this Zile.
But, for me, putting together Zile-on-Guile was a fun project. It would
be cool to see it used for something. I guess if somebody were
actually going to use it, it would need a better home than my GitHub.
I could probably help out, as time permits.
-Mike
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Editing Scheme in the installation image
2017-01-06 13:49 ` Mike Gran
@ 2017-01-07 11:54 ` Ludovic Courtès
2017-01-07 22:44 ` Maxim Cournoyer
0 siblings, 1 reply; 12+ messages in thread
From: Ludovic Courtès @ 2017-01-07 11:54 UTC (permalink / raw)
To: Mike Gran; +Cc: guix-devel
Hi Mike!
Mike Gran <spk121@yahoo.com> skribis:
> Could work, but, there are caveats.
> This Zile fork, and upstream Zile, have characters restricted to 8-bits
> in most places. It also will not do any bi-directional characters
> or double-width characters. For non-ASCII config files, Zile-on-Guile
> might be too limited.
Sure, but these are restrictions acceptable in this context (it’s just
about editing the GuixSD config file in the installation image.)
> The functions expressed in Scheme in Zile-on-Guile are the same
> as upstream Zile had. It is a fairly limited set.
> Zile-on-Guile is a Scheme, not an elisp, even though the functions
> it expresses have elisp-like names. So there is little portability
> between Emacs and this Zile.
Yes. Any idea how hard it would be to port the real Paredit to
Zile-on-Guile?
Also, would it be possible to do highlighting à la ‘show-paren-mode’?
> But, for me, putting together Zile-on-Guile was a fun project. It would
> be cool to see it used for something. I guess if somebody were
> actually going to use it, it would need a better home than my GitHub.
> I could probably help out, as time permits.
If that works, we could get in touch with the Zile folks to discuss
merging it (Guile extension would be an optional feature).
Thanks for your feedback!
Ludo’.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Editing Scheme in the installation image
2017-01-05 23:05 Editing Scheme in the installation image Ludovic Courtès
` (2 preceding siblings ...)
2017-01-06 13:49 ` Mike Gran
@ 2017-01-07 16:00 ` Christopher Allan Webber
3 siblings, 0 replies; 12+ messages in thread
From: Christopher Allan Webber @ 2017-01-07 16:00 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: guix-devel, Mike Gran
Ludovic Courtès writes:
> Hello Guix!
>
> One issue that’s often reported is that it’s inconvenient to edit the
> config file with all its parentheses in the installation image given the
> available options (Zile, Nano, and nvi).
>
> Something like Paredit and ‘show-paren-mode’ in Emacs would help avoid
> mistakes such as unbalanced parenthesis. However ‘emacs-minimal’ takes
> 180MiB and it would be unreasonable to include it.
>
> So I figured we could use Zile-on-Guile¹ (yes!) and extend it to have
> something that resembles Paredit, like:
>
>
> Of course, it takes more than these few lines to write a real Paredit,
> but still, wouldn’t it be cool? :-)
>
> What do people (Mike in particular!) think?
Note that I saw that mit-scheme's edwin now includes some sort of
paredit:
https://www.gnu.org/software/mit-scheme/release.html
New parenthesis-editing minor mode M-x paredit-mode.
iirc edwin is written in scheme, so adapting their paredit-mode might be
less work than writing our own from scratch?
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Editing Scheme in the installation image
2017-01-07 11:54 ` Ludovic Courtès
@ 2017-01-07 22:44 ` Maxim Cournoyer
2017-01-08 10:48 ` Ludovic Courtès
0 siblings, 1 reply; 12+ messages in thread
From: Maxim Cournoyer @ 2017-01-07 22:44 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: guix-devel, Mike Gran
ludo@gnu.org (Ludovic Courtès) writes:
> Mike Gran <spk121@yahoo.com> skribis:
>
>> The functions expressed in Scheme in Zile-on-Guile are the same
>> as upstream Zile had. It is a fairly limited set.
>> Zile-on-Guile is a Scheme, not an elisp, even though the functions
>> it expresses have elisp-like names. So there is little portability
>> between Emacs and this Zile.
>
> Yes. Any idea how hard it would be to port the real Paredit to
> Zile-on-Guile?
Isn't there native support for elisp in Guile? Would this allow running
directly Paredit (elisp), provided that Zile-on-Guile implements
everything that Paredit needs from the Emacs API?
This is probably more work in the short term than rewriting Paredit in
Scheme, but it would enable Zile-on-Guile to potentially run (m)any Emacs
packages.
Maxim
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Editing Scheme in the installation image
2017-01-07 22:44 ` Maxim Cournoyer
@ 2017-01-08 10:48 ` Ludovic Courtès
2017-01-08 18:43 ` Mike Gran
0 siblings, 1 reply; 12+ messages in thread
From: Ludovic Courtès @ 2017-01-08 10:48 UTC (permalink / raw)
To: Maxim Cournoyer; +Cc: guix-devel, Mike Gran
Hello,
Maxim Cournoyer <maxim.cournoyer@gmail.com> skribis:
> ludo@gnu.org (Ludovic Courtès) writes:
>
>> Mike Gran <spk121@yahoo.com> skribis:
>>
>>> The functions expressed in Scheme in Zile-on-Guile are the same
>>> as upstream Zile had. It is a fairly limited set.
>>> Zile-on-Guile is a Scheme, not an elisp, even though the functions
>>> it expresses have elisp-like names. So there is little portability
>>> between Emacs and this Zile.
>>
>> Yes. Any idea how hard it would be to port the real Paredit to
>> Zile-on-Guile?
>
> Isn't there native support for elisp in Guile? Would this allow running
> directly Paredit (elisp), provided that Zile-on-Guile implements
> everything that Paredit needs from the Emacs API?
>
> This is probably more work in the short term than rewriting Paredit in
> Scheme, but it would enable Zile-on-Guile to potentially run (m)any Emacs
> packages.
I think it would take more than elisp compilation support to port Emacs
packages to Zile-on-Guile. Essentially we’d need many APIs that Emacs
provides.
Ludo’.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Editing Scheme in the installation image
2017-01-08 10:48 ` Ludovic Courtès
@ 2017-01-08 18:43 ` Mike Gran
2017-01-08 22:43 ` Ludovic Courtès
0 siblings, 1 reply; 12+ messages in thread
From: Mike Gran @ 2017-01-08 18:43 UTC (permalink / raw)
To: Ludovic Courtès, Maxim Cournoyer; +Cc: guix-devel
>On Sunday, January 8, 2017 2:48 AM, Ludovic Courtès <ludo@gnu.org> wrote:
>Hello,
>Maxim Cournoyer <maxim.cournoyer@gmail.com> skribis:
>> ludo@gnu.org (Ludovic Courtès) writes:
>>
>>> Mike Gran <spk121@yahoo.com> skribis:
>>>
>>>> The functions expressed in Scheme in Zile-on-Guile are the same
>>>> as upstream Zile had. It is a fairly limited set.
>>>> Zile-on-Guile is a Scheme, not an elisp, even though the functions
>>>> it expresses have elisp-like names. So there is little portability
>>>> between Emacs and this Zile.
>>>
>>> Yes. Any idea how hard it would be to port the real Paredit to
>>> Zile-on-Guile?
>>
>> Isn't there native support for elisp in Guile? Would this allow running
>> directly Paredit (elisp), provided that Zile-on-Guile implements
>> everything that Paredit needs from the Emacs API?
>>
>> This is probably more work in the short term than rewriting Paredit in
>> Scheme, but it would enable Zile-on-Guile to potentially run (m)any Emacs
>> packages.
>I think it would take more than elisp compilation support to port Emacs
>packages to Zile-on-Guile. Essentially we’d need many APIs that Emacs
>provides.
I looked at the current beta of paredit, and I quickly scanned
the code to look for *emacs* primitives. Below please find a list
of the primitives that Zile is missing. Note that this isn't the
missing *elisp* procedures.
Adding the majority of these is quite straightforward, but,
some have heretofore been out of scope for Zile. The missing
categories of concepts are
- lisp and scheme filling and indentation
- blinking the cursor or a matching parenthesis
- handling comments
- handling what emacs calls "lists" which is moving up and down
balanced parentheses
Here's the list. I probably missed a few.
backward-delete-char-untabify
backward-up-list
beginning-of-defun
blink-matching-open
buffer-end
buffer-string
buffer-substring
char-after
char-before
check-parens
comment-forward
comment-indent
comment-kill
comment-region
comment-search-forward
current-column
delete-active-region
delete-indentation
end-of-defun
indent-sexp
indent-to
interactive
kill-whole-line
line
lisp-fill-paragraph
lisp-indent-function
lisp-indent-line
make-marker
matching-paren
message
narrow-to-region
newline
point
point-at-bol
point-at-eol
point-max
point-min
position
read-kbd-macro
region-beginning
region-end
save-excursion
scan-sexps
show-paren-mode
skip-chars-forward
start+end
uncomment-region
up-list
yank-pop
zerop
Thanks,
Mike
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Editing Scheme in the installation image
2017-01-08 18:43 ` Mike Gran
@ 2017-01-08 22:43 ` Ludovic Courtès
2017-01-09 1:27 ` Christopher Allan Webber
0 siblings, 1 reply; 12+ messages in thread
From: Ludovic Courtès @ 2017-01-08 22:43 UTC (permalink / raw)
To: Mike Gran; +Cc: guix-devel, Maxim Cournoyer
Mike Gran <spk121@yahoo.com> skribis:
>>On Sunday, January 8, 2017 2:48 AM, Ludovic Courtès <ludo@gnu.org> wrote:
[...]
>>I think it would take more than elisp compilation support to port Emacs
>>packages to Zile-on-Guile. Essentially we’d need many APIs that Emacs
>>provides.
>
> I looked at the current beta of paredit, and I quickly scanned
> the code to look for *emacs* primitives. Below please find a list
> of the primitives that Zile is missing. Note that this isn't the
> missing *elisp* procedures.
> Adding the majority of these is quite straightforward, but,
> some have heretofore been out of scope for Zile. The missing
> categories of concepts are
> - lisp and scheme filling and indentation
> - blinking the cursor or a matching parenthesis
> - handling comments
> - handling what emacs calls "lists" which is moving up and down
> balanced parentheses
> Here's the list. I probably missed a few.
Woow, thanks for investigating!
Looks non-trivial. I wonder how much of it could be trimmed by focusing
just on the subset of Paredit relating to matching parens.
Ludo’.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Editing Scheme in the installation image
2017-01-08 22:43 ` Ludovic Courtès
@ 2017-01-09 1:27 ` Christopher Allan Webber
2017-01-09 9:10 ` Ludovic Courtès
0 siblings, 1 reply; 12+ messages in thread
From: Christopher Allan Webber @ 2017-01-09 1:27 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: guix-devel, Maxim Cournoyer, Mike Gran
[-- Attachment #1: Type: text/plain, Size: 1717 bytes --]
Ludovic Courtès writes:
> Mike Gran <spk121@yahoo.com> skribis:
>
>>>On Sunday, January 8, 2017 2:48 AM, Ludovic Courtès <ludo@gnu.org> wrote:
>
> [...]
>
>>>I think it would take more than elisp compilation support to port Emacs
>>>packages to Zile-on-Guile. Essentially we’d need many APIs that Emacs
>>>provides.
>>
>> I looked at the current beta of paredit, and I quickly scanned
>> the code to look for *emacs* primitives. Below please find a list
>> of the primitives that Zile is missing. Note that this isn't the
>> missing *elisp* procedures.
>> Adding the majority of these is quite straightforward, but,
>> some have heretofore been out of scope for Zile. The missing
>> categories of concepts are
>> - lisp and scheme filling and indentation
>> - blinking the cursor or a matching parenthesis
>> - handling comments
>> - handling what emacs calls "lists" which is moving up and down
>> balanced parentheses
>> Here's the list. I probably missed a few.
>
> Woow, thanks for investigating!
>
> Looks non-trivial. I wonder how much of it could be trimmed by focusing
> just on the subset of Paredit relating to matching parens.
>
> Ludo’.
I mentioned this earlier in the thread, but I think it got lost...
mit-scheme's edwin includes a scheme-based paredit. I haven't tried
looking at how much work it would be to port to Zile, but I'm guessing
since it's also scheme, it wouldn't be much work.
I've extracted it from the latest mit-scheme release and included it.
The code is in the public domain.
Maybe it can be of use?
Note: it might also be possible to pilfer some logic from edwin to "fill
in" the missing procedures to make Zile work.
[-- Attachment #2: paredit.scm --]
[-- Type: application/octet-stream, Size: 39048 bytes --]
#| -*-Scheme-*-
This code is written by Taylor R. Campbell and placed in the Public
Domain. All warranties are disclaimed.
|#
;;;; Paredit: Parenthesis-Editing Minor Mode (based on paredit.el)
(declare (usual-integrations))
(define-command paredit-mode
"Toggle pseudo-structural editing of Lisp code.
With a prefix argument, enable paredit mode if the argument is
positive, and disable paredit mode if not."
"P"
(lambda (argument)
(let ((mode (ref-mode-object paredit)))
(if (if argument
(positive? (command-argument-value argument))
(not (current-minor-mode? mode)))
(enable-current-minor-mode! mode)
(disable-current-minor-mode! mode)))))
(define-minor-mode paredit "Paredit"
"Minor mode for pseudo-structurally editing Lisp code.
\\{paredit}")
(for-each (lambda (key)
(define-key 'paredit (car key) (cadr key)))
'(
;; Insertion commands
(#\( paredit-open-list)
(#\) paredit-close-list-and-newline)
(#\M-\) paredit-close-list)
(#\M-\" paredit-close-string-and-newline)
(#\" paredit-doublequote)
(#\\ paredit-backslash)
(#\return paredit-newline) ; This defies the convention,
(#\C-j newline) ; but I prefer it, and you can
; customize it yourself anyway.
;; Killing & deleting
(#\C-d paredit-forward-delete)
(#\rubout paredit-backward-delete)
(#\C-k paredit-kill)
;; Movement & navigation
(#\C-M-f paredit-forward)
(#\C-M-b paredit-backward)
;;; (#\C-M-u backward-up-list) ; These two are built-in.
;;; (#\C-M-d down-list)
(#\C-M-p backward-down-list)
(#\C-M-n up-list)
((#\C-c #\C-M-l) paredit-recentre-on-sexp)
;; Depth-changing commands
(#\M-\( paredit-wrap-sexp)
(#\M-r paredit-raise-sexp)
(#\M-s paredit-splice-sexp) ;++ This conflicts with M-s
;++ for STEP-DEFUN. Hmmmm.
;; Splitting and Joining
(#\M-S paredit-split-sexp)
(#\M-J paredit-join-sexps)
))
\f
;;;; Basic Editing Commands
(define-command paredit-open-list
"Insert a balanced round bracket parenthesis pair.
With a prefix argument N, put the closing round bracket after N
S-expressions forward.
If in string or comment, inserts a single opening round bracket.
If in a character literal, does nothing. This prevents accidentally
changing what was in the character literal to a meaningful delimiter
unintentionally."
"P"
(let ((open-list
(lambda (argument)
(insert-sexp-pair #\( #\)
(or (command-argument-value argument)
0)))))
(lambda (argument)
(if (group-start? (current-point))
(open-list #f)
(let ((state (current-parse-state)))
(cond ((or (parse-state-in-string? state)
(parse-state-in-comment? state))
(insert-char #\( ))
((not (mark-right-char-quoted? (current-point)))
(open-list argument))))))))
(define-command paredit-close-list
"Move past the closing delimiter of the list the point is on.
Delete all extraneous space before the closing delimiter, but do not
move it past comments between it and the point.
If in a string or comment, insert a single closing round bracket.
If in a character literal, do nothing. This prevents accidentally
changing what was in the character literal to a meaningful delimiter
unintentionally."
()
(lambda ()
(let ((point (current-point)))
(if (group-start? point)
(editor-failure "No list to close at buffer start.")
(let ((state (current-parse-state)))
(cond ((or (parse-state-in-string? state)
(parse-state-in-comment? state))
(insert-char #\) ))
((not (mark-right-char-quoted? point))
(paredit-move-past-close-and-reindent point state)
(flash-sexp-match))))))))
(define-command paredit-close-list-and-newline
"Move past close of the current list, insert a newline, & indent.
If in a string or comment, insert a single closing round bracket.
If in a character literal, do nothing. This prevents accidentally
changing what was in the character literal to a meaningful delimiter
unintentionally."
()
(lambda ()
(let ((point (current-point)))
(if (group-start? point)
(editor-failure "No list to close at buffer start.")
(let ((state (current-parse-state)))
(cond ((or (parse-state-in-string? state)
(parse-state-in-comment? state))
(insert-char #\) ))
(else
(paredit-move-past-close-and-reindent
(if (mark-right-char-quoted? point)
(mark1+ point)
point)
state)
(insert-newline-preserving-comment)
(lisp-indent-line-and-sexp)
(flash-sexp-match #t))))))))
\f
(define (paredit-move-past-close-and-reindent mark state)
(cond ((forward-up-one-list mark)
=> (lambda (after-close)
(undo-record-point!)
(set-current-point! after-close)
(let loop ((before-close (mark-1+ after-close)))
(if (mark= (horizontal-space-end
(line-start before-close 0))
before-close)
;; The closing delimiter is the first thing on the
;; line. If the previous line ends in a comment,
;; we stop here; otherwise, we go on.
(let ((end-of-prev (line-end before-close -1))
(location (parse-state-location state)))
(cond ((and (not (mark<= end-of-prev location))
(parse-state-in-comment?
(parse-partial-sexp location
end-of-prev
#f #f
state)))
;; Nothing more to be done, so just
;; indent the line we're on (which has
;; the closing delimiter).
(lisp-indent-line #f))
(else
;; More to delete.
(delete-string end-of-prev before-close)
(loop end-of-prev))))
;; We've reached our goal, though there might be
;; some indentation between the closing delimiter
;; and where we want it to be. We must take care,
;; though, to preserve whitespace characters.
(let* ((mark
(horizontal-space-start before-close))
(escaped
(and (mark-right-char-quoted? mark)
(mark-right-char mark))))
(delete-horizontal-space before-close)
(if escaped
(insert-char escaped mark)))))))
(else
(editor-error "No closing delimiter to move over."))))
\f
(define-command paredit-close-string-and-newline
"Move to the end of the string, insert a newline, and indent.
If not in a string, act as `paredit-doublequote'."
()
(lambda ()
(let ((state (current-parse-state)))
(if (not (parse-state-in-string? state))
((ref-command paredit-doublequote))
(let ((after-string (parse-state-end-of-sexp state)))
(set-current-point! after-string)
(insert-newline)
(lisp-indent-line-and-sexp)
(flash-sexp-match #f after-string))))))
(define-command paredit-doublequote
"Insert a pair of double-quotes.
Inside a comment, insert a literal double-quote.
At the end of a string, move past the closing double-quote.
In the middle of a string, insert a backslash-escaped double-quote.
If in a character literal, do nothing. This prevents accidentally
changing what was in the character literal to a meaningful delimiter
unintentionally."
()
(lambda ()
(let ((state (current-parse-state)))
(cond ((parse-state-in-string? state)
(if (mark= (mark-1+ (parse-state-end-of-sexp state))
(current-point))
;; On the closing quote -- move past it & flash.
(begin (set-current-point! (mark1+ (current-point)))
(flash-sexp-match))
;; Elsewhere in a string: insert escaped.
(begin (insert-char #\\ )
(insert-char #\"))))
((parse-state-in-comment? state)
(insert-char #\" ))
((not (mark-right-char-quoted? (current-point)))
(insert-sexp-pair #\" #\" 0))))))
(define-command paredit-backslash
"Insert a backslash followed by a character to escape."
()
(lambda ()
(let ((state (current-parse-state)))
(insert-char #\\ )
(if (not (parse-state-in-comment? state))
(let ((char #f))
(dynamic-wind ;++ What happens if this gets
(lambda () unspecific) ;++ used in a recursive edit?
(lambda ()
(set! char (prompt-for-char "Character to escape")))
(lambda ()
(if (and char (not (char=? char #\rubout)))
(insert-char char)
(delete-left-char)))))))))
\f
(define-command paredit-newline
"Insert a newline and indent.
This is like `newline-and-indent', but it not only indents the line
that the point is on but also the S-expression following the point,
if there is one.
Move forward one character first if on an escaped character.
If in a string, just insert a literal newline."
()
(lambda ()
(let ((state (current-parse-state)))
(cond ((parse-state-in-string? state)
(insert-newline))
(else
(let ((point (current-point)))
(if (and (not (parse-state-in-string? state))
(mark-right-char-quoted? point))
(set-current-point! (mark1+ point))))
(delete-horizontal-space)
(insert-newline)
(lisp-indent-line-and-sexp))))))
\f
(define-command paredit-forward-delete
"Delete a character forward or move forward over a delimiter.
If on an opening S-expression delimiter, move forward into the
S-expression.
If on a closing S-expression delimiter, refuse to delete unless the
S-expression is empty, in which case delete the whole S-expression.
With a prefix argument, simply delete a character forward, without
regard for delimiter balancing. This is useful when the buffer has
entered a structurally inconsistent state which paredit is unable to
cope with."
"P"
(lambda (argument)
(let ((point (current-point)))
(if (or (command-argument-value argument)
(group-end? point))
((ref-command delete-char) #f)
(let ((state (current-parse-state))
(right (mark-right-char point)))
(cond ((parse-state-in-string? state)
(paredit-forward-delete-in-string point state))
((parse-state-in-comment? state)
(delete-right-char point))
((mark-right-char-quoted? point)
;; Escape -- delete both characters.
(delete-string (mark-1+ point)
(mark1+ point)))
((char=? right #\\ )
;; Ditto.
(delete-string (mark+ point 2) point))
((let ((syn (char-syntax right)))
(or (char=? syn #\( )
(char=? syn #\" )))
;; Enter into an S-expression forward.
(set-current-point! (mark1+ point)))
((and (not (group-start? point))
(not (mark-right-char-quoted?
(mark-1+ point)))
(char=? (char-syntax right)
#\) )
(char=? (mark-left-char point)
(char-matching-paren right)))
;; Empty list -- delete both delimiters.
(delete-string (mark-1+ point)
(mark1+ point)))
;; Just delete a single character, if it's not a
;; closing parenthesis.
((not (char=? (char-syntax right) #\) ))
(delete-right-char point))))))))
(define (paredit-forward-delete-in-string point state)
(let ((before (mark-1+ point))
(after (mark1+ point)))
(cond ((not (mark= after (parse-state-end-of-sexp state)))
;; If it's not the close-quote, it's safe to delete. But
;; first handle the case that we're in a string escape.
(cond ((mark-within-string-escape? point)
;; We're right after the backslash, so delete one
;; character backward (the backslash) and one
;; character forward (the escaped character).
(delete-string before after))
((mark-within-string-escape? after)
;; A string escape starts here, so delete both
;; characters forward.
(delete-string point (mark1+ after)))
(else
;; Otherwise, just delete a single character.
(delete-right-char point))))
((mark= before (parse-state-start-of-sexp state))
;; If it is the close-quote, delete only if we're also
;; right past the open-quote (i.e. it's empty), and then
;; delete both quotes. Otherwise refuse to delete it.
(delete-string before after)))))
\f
(define-command paredit-backward-delete
"Delete a character backward or move backward over a delimiter.
If on a closing S-expression delimiter, move backward into the
S-expression.
If on an opening S-expression delimiter, refuse to delete unless the
S-expression is empty, in which case delete the whole S-expression.
With a prefix argument, simply delete a character backward, without
regard for delimiter balancing, and possibly untabify. This is
useful when the buffer has entered a structurally inconsistent state
which paredit is unable to cope with."
"P"
(lambda (argument)
(let ((point (current-point)))
(if (or (command-argument-value argument)
(group-start? point))
((ref-command backward-delete-char-untabify) #f)
(let ((state (current-parse-state))
(left (mark-left-char point)))
(cond ((parse-state-in-string? state)
(paredit-backward-delete-in-string point state))
((parse-state-in-comment? state)
((ref-command backward-delete-char-untabify) #f))
((mark-right-char-quoted? point)
;; Escape -- delete both characters.
(delete-string (mark-1+ point)
(mark1+ point)))
((mark-left-char-quoted? point)
;; Ditto.
(delete-string (mark- point 2) point))
((let ((syn (char-syntax left)))
(or (char=? syn #\) )
(char=? syn #\" )))
;; Enter into an S-expression backward.
(set-current-point! (mark-1+ point)))
((and (char=? (char-syntax left) #\( )
(char=? (mark-right-char point)
(char-matching-paren left)))
;; Empty list -- delete both delimiters.
(delete-string (mark-1+ point)
(mark1+ point)))
;; Delete it only on the condition that it's not an
;; opening parenthesis.
((not (char=? (char-syntax left) #\( ))
((ref-command backward-delete-char-untabify) #f))))))))
(define (paredit-backward-delete-in-string point state)
(let ((before (mark-1+ point))
(after (mark1+ point)))
(cond ((not (mark= before (parse-state-start-of-sexp state)))
;; If it's not the open-quote, it's safe to delete, but we
;; still must be careful with escapes.
(cond ((mark-within-string-escape? point)
(delete-string before after))
((mark-within-string-escape? before)
(delete-string (mark-1+ before) point))
(else
(delete-left-char point))))
((mark= after (parse-state-end-of-sexp state))
;; If it is the open-quote, delete only if we're also right
;; past the close-quote (i.e. it's empty), and then delete
;; both quotes. Otherwise we refuse to delete it.
(delete-string before after)))))
\f
(define-command paredit-kill
"Kill a line as if with `kill-line', but respect delimiters.
In a string, act exactly as `kill-line' but do not kill past the
closing string delimiter.
On a line with no S-expressions on it starting after the point or
within a comment, act exactly as `kill-line'.
Otherwise, kill all S-expressions that start on the line after the
point."
"P"
(lambda (argument)
(if (command-argument-value argument)
((ref-command kill-line) #f)
(let ((state (current-parse-state))
(point (current-point)))
(cond ((parse-state-in-string? state)
(paredit-kill-line-in-string point))
((or (parse-state-in-comment? state)
(let* ((eol (line-end point 0))
(next
(skip-whitespace-forward point eol)))
(or (mark= next eol)
(char=? (mark-right-char next)
#\; ))))
((ref-command kill-line) #f))
(else
(paredit-kill-sexps-on-line point)))))))
(define (paredit-kill-line-in-string point)
(let ((eol (line-end point 0)))
(cond ((mark= (skip-whitespace-forward point eol)
eol)
((ref-command kill-line) #f))
(else
(let ((beginning (if (mark-within-string-escape? point)
(mark-1+ point)
point)))
(let loop ((mark beginning))
(if (or (mark= mark eol)
(char=? (mark-right-char mark)
#\" ))
(kill-string beginning mark)
(loop (mark+ mark
(if (char=? (mark-left-char mark)
#\\ )
2
1))))))))))
(define (paredit-kill-sexps-on-line point)
(let* ((beginning (if (mark-right-char-quoted? point)
(mark1+ point) ; Don't break a line in a
point)) ; character literal.
(eol (line-end beginning 0))
(kill-to (lambda (end)
(kill-string beginning end))))
(let loop ((mark beginning))
(cond ((or (group-end? mark)
(not (mark= (line-end mark 0) eol)))
(kill-to mark))
((forward-one-sexp mark)
=> (lambda (sexp-end-mark)
(cond ((backward-one-sexp sexp-end-mark)
=> (lambda (sexp-start-mark)
;; Only if it starts on the same line
;; will we include it in what we kill.
(if (mark= (line-end sexp-start-mark 0)
eol)
(loop sexp-end-mark)
(kill-to mark))))
(else (kill-to mark)))))
((forward-up-one-list mark)
=> (lambda (after-close)
(kill-to (if (mark= (line-end after-close 0)
eol)
(mark-1+ after-close)
eol))))
(else
(kill-to mark))))))
\f
;;;; Cursor and Screen Movement Commands on S-expressions
(define (paredit-movement-command move-sexp move-char move-up)
(lambda ()
(set-current-point!
(let ((point (current-point)))
(cond ((move-sexp point))
((parse-state-in-string? (current-parse-state))
(move-char point))
((move-up point))
(else
(editor-error "Unable to move.")))))))
(define-command paredit-forward
"Move forward an S-expression, or up an S-expression forward.
If there are no more S-expressions in this one before the closing
delimiter, move past that closing delimiter; otherwise, move forward
over the S-expression following the point."
()
(paredit-movement-command forward-one-sexp
mark1+
forward-up-one-list))
(define-command paredit-backward
"Move backward an S-expression, or up an S-expression backward.
If there are no more S-expressions in this one after the opening
delimiter, move past that opening delimiter; otherwise, move
backward over the S-expression preceding the point."
()
(paredit-movement-command backward-one-sexp
mark-1+
backward-up-one-list))
(define-command paredit-recentre-on-sexp
"Recentre the screen on the S-expression following the point.
With a prefix argument N, encompass all N S-expressions forward."
"p"
(lambda (n)
(let* ((end-mark (forward-sexp (current-point) n 'ERROR))
(start-mark (backward-sexp end-mark n 'ERROR))
(centre-offset (quotient (count-lines start-mark end-mark)
2)))
(set-current-point! (line-start start-mark centre-offset))
((ref-command recenter) #f))))
\f
;;;; Wrappage, splicage, & raisage
(define-command paredit-wrap-sexp
"Wrap the following S-expression in a list.
If a prefix argument N is given, wrap N S-expressions.
Automatically indent the newly wrapped S-expression.
As a special case, if the point is at the end of a list, simply insert
a pair of parentheses."
"p"
(lambda (n)
(insert-sexp-pair #\( #\)
(if (forward-sexp (current-point) n #f)
n
0))
(lisp-indent-sexp
(or (backward-up-one-list (current-point))
(error "Wrappage bogosity. Please inform TRC.")))))
(define-command paredit-raise-sexp
"Raise the following S-expression in a tree, deleting its siblings.
With a prefix argument N, raise the following N S-expressions. If N
is negative, raise the preceding N S-expressions."
"p"
(lambda (n)
;; I have very carefully selected where to use {FOR,BACK}WARD-SEXP
;; with arguments 1 & ERROR and {FOR,BACKWARD}-ONE-SEXP here, so
;; that the error is signalled initially and then not checked
;; redundantly later.
;++ This should be verified.
(let* ((point (current-point))
(mark (forward-sexp (current-point) n 'ERROR))
(sexps (if (negative? n)
(extract-string mark
(forward-one-sexp
(backward-one-sexp point)))
(extract-string (backward-one-sexp
(forward-one-sexp point))
mark)))
(before-encloser (mark-temporary-copy
(backward-up-list point 1 'ERROR))))
(delete-string before-encloser
(forward-sexp before-encloser 1 'ERROR))
(insert-string sexps before-encloser)
(let loop ((n n) (mark before-encloser))
(if (positive? n)
(let ((after (forward-one-sexp mark)))
(set-current-point! (backward-one-sexp after))
(lisp-indent-line #f)
(lisp-indent-sexp (current-point))
(loop (- n 1) after))))
(set-current-point! before-encloser))))
\f
(define-command paredit-splice-sexp
"Splice the list that the point is on by removing its delimiters.
With a prefix argument as in `C-u', kill all S-expressions backward in
the current list before splicing all S-expressions forward into the
enclosing list.
With two prefix arguments as in `C-u C-u', kill all S-expressions
forward in the current list before splicing all S-expressions
backward into the enclosing list.
With a numerical prefix argument N, kill N S-expressions backward in
the current list before splicing the remaining S-expressions into the
enclosing list. If N is negative, kill forward."
"P"
(lambda (argument)
(undo-record-point!)
(if argument (paredit-kill-surrounding-sexps-for-splice argument))
(let* ((before-open (backward-up-list (current-point) 1 'ERROR))
(before-close
(mark-1+ (forward-sexp before-open 1 'ERROR))))
(delete-right-char before-close)
(delete-right-char before-open)
(with-current-point before-open
(lambda ()
(paredit-reindent-splicage argument))))))
(define (paredit-kill-surrounding-sexps-for-splice argument)
(cond ((command-argument-multiplier-only? argument)
(let ((loop (lambda (mark-end? advance-one-sexp)
(let ((point-a (current-point)))
(let loop ((point-b point-a))
(define (win) (kill-string point-a point-b))
(cond ((mark-end? point-b) (win))
((advance-one-sexp point-b) => loop)
(else (win)))))))
(value (command-argument-numeric-value argument)))
(if (= value 4) ;One C-u
(loop group-start? backward-one-sexp)
(loop group-end? forward-one-sexp))))
((exact-integer? argument)
(let* ((point (current-point))
(mark (backward-sexp point argument 'ERROR)))
(kill-string point mark)))
(else
(error "Bizarre prefix argument to PAREDIT-SPLICE:"
argument))))
(define (paredit-reindent-splicage argument)
(cond ((backward-up-list (current-point) 1 #f)
=> lisp-indent-sexp)
((not (exact-integer? argument))
unspecific)
((positive? argument)
(lisp-indent-line #f)
(lisp-indent-sexp (current-point))
(if (> argument 1)
(save-excursion
(lambda ()
(let loop ((n argument))
(lisp-indent-line #f)
(modify-current-point!
(lambda (point)
(lisp-indent-sexp point)
(forward-one-sexp point)))
(let ((m (- n 1)))
(if (positive? m)
(loop m))))))))
((negative? argument)
(save-excursion
(lambda ()
(let loop ((n argument))
(cond ((not (zero? n))
(modify-current-point! backward-one-sexp)
(lisp-indent-line #f)
(lisp-indent-sexp (current-point))
(loop (+ n 1))))))))))
\f
;;;; Splitting and Joining
(define-command paredit-split-sexp
"Split the list or string the point is on in two."
()
(lambda ()
(let ((state (current-parse-state)))
(cond ((parse-state-in-string? state)
(insert-char #\")
(save-excursion
(lambda ()
(insert-char #\space)
(insert-char #\"))))
((or (parse-state-in-comment? state)
(mark-right-char-quoted? (current-point)))
(editor-error
"Invalid context for S-expression splitting."))
((let ((point (current-point)))
(and (memv (char-syntax (mark-left-char point))
'(#\w #\_))
(memv (char-syntax (mark-right-char point))
'(#\w #\_))))
(save-excursion (lambda ()
(insert-char #\space))))
(else
(undo-record-point!)
(split-sexp-at-point))))))
(define (split-sexp-at-point)
(let ((open (backward-up-list (current-point) 1 'ERROR))
(close (forward-up-list (current-point) 1 'ERROR)))
(let ((open-char (mark-right-char open))
(close-char (mark-left-char close)))
(let ((new-close (cond ((backward-one-sexp (current-point))
=> forward-one-sexp)
(else (mark1+ open))))
(new-open (cond ((forward-one-sexp (current-point))
=> backward-one-sexp)
(else (mark-1+ close)))))
(if (mark< new-open new-close) ;Can't actually happen...
(editor-error ;I guess Democritus was right!
"Splitting atom! RUN, before critical mass!!"))
(let ((new-close (mark-left-inserting-copy new-close))
(new-open (mark-left-inserting-copy new-open)))
(insert-char close-char new-close)
(mark-temporary! new-close)
(save-excursion
(lambda ()
(if (not (char=? (char-syntax (mark-left-char new-open))
#\space))
(insert-char #\space new-open))
(mark-temporary! new-open)
(insert-char open-char new-open)
(if (mark/= (line-start (current-point) 0)
(line-start new-open 0))
(with-current-point new-open
lisp-indent-line-and-sexp)
(lisp-indent-sexp new-open)))))))))
\f
(define-command paredit-join-sexps
"Join the S-expressions adjacent on either side of the point.
Both must be lists, strings, or atoms; error if there is mismatch."
()
(lambda ()
(let ((state (current-parse-state)))
(if (or (parse-state-in-comment? state)
(parse-state-in-string? state) ;foo
(mark-right-char-quoted? (current-point)))
(editor-error "Invalid context for S-expression joining.")
(let ((left-point (end-of-sexp-backward (current-point)))
(right-point (start-of-sexp-forward (current-point))))
(cond ((mark< right-point left-point)
(editor-error "Joining single S-expression."))
((intervening-text? left-point right-point)
(editor-error
"S-expressions to join have intervenining text."))
(else
(save-excursion
(lambda ()
(join-sexps left-point right-point))))))))))
(define (join-sexps left-point right-point)
(let ((left-syntax (char-syntax (mark-left-char left-point)))
(right-syntax (char-syntax (mark-right-char right-point))))
(cond ((and (char=? left-syntax #\))
(char=? right-syntax #\())
(let ((right-point
(if (mark/= left-point right-point)
right-point
(begin (insert-char #\space right-point)
(mark1+ right-point)))))
(delete-right-char right-point)
(delete-left-char left-point))
(lisp-indent-sexp
(backward-up-list (current-point) 1 'ERROR)))
((and (char=? left-syntax #\")
(char=? right-syntax #\"))
(delete-string (mark-1+ left-point)
(mark1+ right-point)))
((or (and (memq left-syntax '(#\w #\_))
(memq right-syntax '(#\w #\_))))
;; Word or symbol
(delete-string left-point right-point))
(else
(editor-error
"Mismatched S-expressions to join.")))))
\f
;;;; Miscellaneous Utilities
(define (current-parse-state #!optional point)
(let ((point (if (default-object? point)
(current-point)
point)))
(parse-partial-sexp (or (this-definition-start point)
(buffer-start (current-buffer)))
point)))
(define (insert-sexp-pair open close sexps #!optional mark)
(define (insert-space end? mark)
(if (and (not (if end?
(group-end? mark)
(group-start? mark)))
(memv (char-syntax (if end?
(mark-right-char mark)
(mark-left-char mark)))
(cons (if end? #\( #\) )
'(#\\ ; escape
#\w ; word constituent
#\_ ; symbol constituent
#\")))) ; string quote
(begin (insert-char #\space mark)
(mark1+ mark))
mark))
(let* ((start (mark-temporary-copy (if (default-object? mark)
(current-point)
mark)))
(before (insert-space #f start)))
(insert-char open before)
(let ((point (mark1+ before)))
(let ((after (forward-sexp point sexps 'ERROR)))
(insert-char close after)
(insert-space #t (mark1+ after)))
(set-current-point! point))))
\f
(define (insert-newline-preserving-comment #!optional mark)
(let ((mark (if (default-object? mark) (current-point) mark)))
(cond ((line-margin-comment-region mark)
=> (lambda (region)
(mark-permanent! mark)
(let* ((before-semi (region-start region))
(bol (line-start before-semi 0))
(column (region-count-chars
(make-region bol before-semi)))
(comment (extract-and-delete-string
before-semi
(region-end region))))
(delete-horizontal-space before-semi)
(let ((copy (mark-temporary-copy mark)))
(insert-newline mark)
(indent-to column 0 copy)
(insert-string comment (line-end copy 0))))))
(else
(insert-newline mark)))))
;;; This assumes that POINT is before the comment on the line, if there
;;; is a comment. This assumption may be flawed for general use, but
;;; it is guaranteed by paredit's use of this procedure.
(define (line-margin-comment-region #!optional point)
(let* ((point (if (default-object? point)
(current-point)
point))
(eol (line-end point 0)))
(let loop ((point point)
(state (current-parse-state point)))
(cond ((char-search-forward #\; point eol)
=> (lambda (after-semi)
(let ((state* (parse-partial-sexp point after-semi
#f #f
state)))
(if (or (mark-left-char-quoted? after-semi)
(parse-state-in-string? state*))
(loop after-semi state*)
(make-region (mark-1+ after-semi)
eol)))))
(else #f)))))
(define (start-of-sexp-forward mark)
(backward-sexp (forward-sexp mark 1 'ERROR) 1))
(define (end-of-sexp-backward mark)
(forward-sexp (backward-sexp mark 1 'ERROR) 1))
(define (intervening-text? start end)
(mark/= (skip-whitespace-forward start end)
end))
\f
(define (lisp-indent-line-and-sexp)
(lisp-indent-line #f)
(let ((point (current-point)))
(if (cond ((forward-one-sexp point)
=> (lambda (end)
(mark= (line-start (backward-one-sexp end) 0)
(line-start point 0))))
(else #f))
(lisp-indent-sexp point))))
;;; In paredit.el, the ABSOLUTELY? argument determined whether or not
;;; to override the BLINK-MATCHING-PAREN variable, because in some
;;; contexts SHOW-PAREN-MODE suffices for the purpose; however, Edwin
;;; has no such variable or SHOW-PAREN-MODE, but I'd like to make it
;;; easy to support them later on.
(define (flash-sexp-match #!optional absolutely? point)
absolutely?
(mark-flash (backward-one-sexp (if (default-object? point)
(current-point)
point))
'RIGHT))
(define (char-matching-paren char)
;++ This is a hideous kludge. Why is it necessary? There must be
;++ something built-in that does this.
(string-ref (char-syntax->string
(get-char-syntax (ref-variable syntax-table)
char))
1))
;;; This assumes that MARK is already in a string.
(define (mark-within-string-escape? mark)
(let loop ((flag #f) (mark mark))
(if (char=? (mark-left-char mark)
#\\)
(loop (not flag) (mark-1+ mark))
flag)))
(define (skip-whitespace-forward #!optional start end)
(skip-chars-forward (char-set->string char-set:whitespace)
start
end))
(define (char-set->string char-set)
(list->string (char-set-members char-set)))
(define (undo-record-point! #!optional buffer)
(let ((group (buffer-group (if (default-object? buffer)
(current-buffer)
buffer))))
(set-group-undo-data! group
(cons (mark-index (group-point group))
(group-undo-data group)))))
(define (modify-current-point! modifier)
(set-current-point! (modifier (current-point))))
\f
;;; Edwin Variables:
;;; outline-pattern: "^\f\n;;;;+"
;;; End:
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Editing Scheme in the installation image
2017-01-09 1:27 ` Christopher Allan Webber
@ 2017-01-09 9:10 ` Ludovic Courtès
0 siblings, 0 replies; 12+ messages in thread
From: Ludovic Courtès @ 2017-01-09 9:10 UTC (permalink / raw)
To: Christopher Allan Webber; +Cc: guix-devel, Maxim Cournoyer, Mike Gran
Christopher Allan Webber <cwebber@dustycloud.org> skribis:
> Ludovic Courtès writes:
>
>> Mike Gran <spk121@yahoo.com> skribis:
>>
>>>>On Sunday, January 8, 2017 2:48 AM, Ludovic Courtès <ludo@gnu.org> wrote:
>>
>> [...]
>>
>>>>I think it would take more than elisp compilation support to port Emacs
>>>>packages to Zile-on-Guile. Essentially we’d need many APIs that Emacs
>>>>provides.
>>>
>>> I looked at the current beta of paredit, and I quickly scanned
>>> the code to look for *emacs* primitives. Below please find a list
>>> of the primitives that Zile is missing. Note that this isn't the
>>> missing *elisp* procedures.
>>> Adding the majority of these is quite straightforward, but,
>>> some have heretofore been out of scope for Zile. The missing
>>> categories of concepts are
>>> - lisp and scheme filling and indentation
>>> - blinking the cursor or a matching parenthesis
>>> - handling comments
>>> - handling what emacs calls "lists" which is moving up and down
>>> balanced parentheses
>>> Here's the list. I probably missed a few.
>>
>> Woow, thanks for investigating!
>>
>> Looks non-trivial. I wonder how much of it could be trimmed by focusing
>> just on the subset of Paredit relating to matching parens.
>>
>> Ludo’.
>
> I mentioned this earlier in the thread, but I think it got lost...
> mit-scheme's edwin includes a scheme-based paredit. I haven't tried
> looking at how much work it would be to port to Zile, but I'm guessing
> since it's also scheme, it wouldn't be much work.
>
> I've extracted it from the latest mit-scheme release and included it.
> The code is in the public domain.
>
> Maybe it can be of use?
Yes, probably! It seems smaller than the “real” Paredit, which is
already a good thing.
(I won’t be working on it in the near future but I’m bookmarking this
thread…)
Ludo’.
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2017-01-09 9:10 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-01-05 23:05 Editing Scheme in the installation image Ludovic Courtès
2017-01-06 1:54 ` Kei Kebreau
2017-01-06 9:09 ` Ricardo Wurmus
2017-01-06 13:49 ` Mike Gran
2017-01-07 11:54 ` Ludovic Courtès
2017-01-07 22:44 ` Maxim Cournoyer
2017-01-08 10:48 ` Ludovic Courtès
2017-01-08 18:43 ` Mike Gran
2017-01-08 22:43 ` Ludovic Courtès
2017-01-09 1:27 ` Christopher Allan Webber
2017-01-09 9:10 ` Ludovic Courtès
2017-01-07 16:00 ` Christopher Allan Webber
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/guix.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).