Open ghost opened 7 years ago
^[FBUDEY]
this took me a good minute to parse
As you enter ed ranges, the line numbers get highlighted (right when you type them). Maybe working on multiple ranges, separated by a ; like 2,13;32;34s/$/;/.
this is an idea that's occured to me before. if you dig deep into edna's getaddr()
function, you'll notice it's very complex for what should be something very simple (parsing some number, maybe with an infix expression or two). in fact, the backend in quite wasteful, using a big bitarray (take a look at the mess that is set.c
) for storing single line-numbers.
but I had two goals with the design of getaddr()
et al.
in ed, you cannot do 4+/foo/
(selecting the first line containing `foo' after line four), nor can you do /foo/ - /bar/
(selecting the first occurance of `bar' before the next occurance of `foo'. this is useful, however, so I want to add the capability
this is closely related to your syntax for composing addresses, but I avoid the ;
because I have other uses for it (I'm torn between using it as a command seperator, as in sh (s/foo/bar/; /quux/d; w fn
) or for macro invocation (;mac arg1 arg2
))
instead, I planned to use the logical operators, in set-theoretic way
sel1 & sel2
-- intersection; selects every line in both sel1
and sel2
sel1 | sel2
-- union; selects every line in either sel1
or sel2
(this my answer to your ;
proposal)
sel1 ^ sel2
-- symmetric difference; selects every line in sel1
and set2
, but not both
the standard ed operators would be overloaded,
sel + line
would shift each line in sel
by line
, which can be a number or pattern, sel + 1
shifts each line in sel
forward one line, sel + /pat/
shifts each line to the next occurance of /pat/
sel - line
behaves opposite +
, which should not need too much explaining
sel1,sel2
produces a selection with every line between the end of sel1
and the begining of sel2
is selected, along with the union of sel1 and sel2.
Maybe it could even only display the selected lines (and not the not-selected around) with a few lines of context (like git diff), skipping lines in-between. Then, while finished, focusing on the dot afterward (with highlighted line number), showing all the lines around.
this is actually a very interesting idea. the lack of context is one thing that make ed somewhat awkward to use for quick edits.
"a visual editor without a cursor"
there is another, related idea I've had, which this reminded me of, which is being able to pass around arbitrary strings in the command mode of a vi-clone. the way I concieved of it was pressing the '
(single-quote) key and typing some stuff, then single quote again. this could then be passed to other commands, like counts or text-objects in vi{,m,s}.
you could take this idea farther, I considered a screen editor where the commands look just like ed'. (e.g. type
15, and line fifteen is scrolled too and highlighted. type
,18and the next three lines are highlighted. type
sand little dialog pops up. type
patand as you type the pattern, each occurance matching what you typed is highlighed in a different color. hit return, and type
repl` and each sub-seletion is replaced with it.
the invocation of s would have to be changed, since it's a bit awkward decision where g
and 2
and other options appended to end of the command in ed would go in this setup.
I should mention I haven't been working on edna much lately. I had been working on overhauling the parser, and after three aborted attempts, I gave up. I do have a edna-next
project sitting on my hard-drive, but it doesn't have much of note going for it.
of course, I mention this because you've inspired me to try another dive back into the codebase. I'll what I can do the polish it up today.
in a slightly related bit, I'll mention the ideas that have been piling up. I'll accept criticisms, particularly pointing out weird edges or possible limitations. other ideas are also appreciated
this is a small one, but it is implicit in most of my following snippets, so I'll be explicit
essentially, it's that 1 + 1 s/this/that
is the same as 1+1s/this/that
most commands implicitly work on lines. if they can be re-worked to instead work on whatever selection is handed to them, it opens the possibility of sub-line selections. this is the syntax I've considered:
/naet/v s/ae/ea
v
would have an antonym in l
, but it would be the default (or perhaps this could be a config.h switch?)
related to the above, is giving ordinary regex options.
/pat/i
would be case-insensitive matching
/pat/g
would be global search, like g/pat/
in ed
g
would define macros. do g mac s/this/that
, and then mac
is equivalent to s/this/that
there would also be vi-style macros
: g mac
: s/this/that
: /foo/
: d
/* ... */
: g
recorded macro `mac'
g
would be to escape macro-mode, so no nested macro-defintion.
macros also would not effect the actual state of the buffer until they're played. the rationale for this is simply that I try to choose the default behavior that's easy to reverse -- it'd be simple to write a g
macro to define a macro and play it, but harder to write a macro to define one and then reverse every single side effect that could have been invoked, which may need to be revised if the set of potental side-effects grows or the behavior of undo changes
have vi-style registers, without th restriction to single-latter names
d reg
move to register reg
y reg
copy to register reg
x reg
paste form register reg
"reg s/this/that
do a substitution on the contents of a register
p reg
print the contents of a register
special registers:
"" - anonymous register
"/ - search register, contains last search
"_ - black hole register
": - command register, contains last executed command
"? - help registers. contains last error message
when I said I was making a text editor in #unix, one of the first reactions was that undo-trees would be a pain to implement.
edna should support more than a single level of undo, but I'm not sure what the redo command should be called. r
is for read files. R
, perhaps.
some ideas
4u
undo the last change to line 4
u 4
undo four times
"reg u
undo register action. this could emulate emacs' kill rings, perhaps
h
- could be a `history' command instead of help?
e.g.
h /this/
- search history for `this'
!cmd
would execute cmd
in a shell
!cmd %
would write the buffer to a tmpfile, then call the cmd on it
/start/,/end/ !cmd
would call cmd with the selection /start/,/end
as standard input
and that's most of my notes. it feels kinda disingenuous to talk about things I haven't coded yet, but I wanted someone else's thoughts on them
Hi,
Maybe I will not have time enough to answer this weekend, so a quick answer for now.
I read it all, I liked the way of adresing the ranges and the way you can combine them.
I did try sam(1) yesterday, and it really looks like what I was proposing, and also have some of the features you talked about (commposing ranges, excluding some... se structural regular expressions). This could be of some help for the design.
Sam is an ed-like editor after all... And it has less lines of code than either vis(1) or ex-vi(1) (the original one).
Sorry for the ^[FBUDEY]
.
`getaddr()'
It looks like AST generation and exploitation. But it is important feature for an editor without a cursor.
set.c - bit array
Well, that just works ! It would be (1 / bits_per_wchar_t) * size_of_the_buffer
. If we store the text as WCHAR_T, one bit needed to represent one wchar_t.
There may be implementation, or even whole books on the topic (or small articles).
infix expressions - power of line addresses
I do not know any tool but sam-style expressions, and they may even lack a few features.
syntax of line addresses
Do lines addresses works a bit like evaluation: with expressions evaluated to become ranges, and operators directly acting on ranges? With the range being 'Set' objects.
arbitrary strings in the command
Yes, in the end, why such a gap between vi and ex. That is two different ways to interact with an editor.
this idea farther
In sam, you can scroll the screen, the cursor will not follow. Then you can write somewhere, read elsewhere, and come back at the cursor: it did not move at all. This also makes sense if you work with ranges: there will be too much to fit into the screen.
invocation of s would have to be changed, since it's a bit awkward decision where g and 2 and other options appended to end
sam and vis:
x/pattern/
: To select all occurences of pattern (within active range, so % x/pattern/ to
select all pattern in the file, . x/pattern/ for the current line...).
c/replacement/
: Your repl command
d
: Delete the selection: not only replacement available.
working on edna
I am lacking time too. Hope there will be some holidays ahead (I am still a student).
sub-line selection
/naet/v s/ae/ea
In sam:
, x/naet/ x/ae/ c/ea/
macros
This is macro done right! There is no difference between function definition and macro. As edna is line-oriented, macro could be like an 'edna script' recorded to a new command name. Is that what you meant?
registers
With then "reg command
a command on a range outside of the main buffer (on a register buffer).
I imagined it would be nice to store the registers as plain text files:
~/.cache/edna/registers/register1
~/.cache/edna/registers/register2
~/.cache/edna/registers/_ -> /dev/null
~/.cache/edna/registers/search
~/.cache/edna/registers/:
~/.cache/edna/registers/?
Maybe this could make registers hidden buffers also open in the editor. Making undos on the registers as hard as undo for plain files to implement.
things I haven't coded yet
I imagine: the earlier I change my decisions, the less work I have to change.
I quote sam too often. :-P But it is close to these ideas. Maybe it could be even be interesting to share the syntax with it, and extend it. This would make transition between vis/sam/edna simple. Other commands could still be added, like what vis(1) did.
Sam has a text-only version: sam -d
.
Command language explained: http://sam.cat-v.org/ > Documentation and Manuals Structrual regular expressions: http://doc.cat-v.org/bell_labs/structural_regexps/
I first thought about displaying the ranges as they got typed, (e.g.: right after the ,
in 12,14 s/foo/bar/
).
Maybe this is a bit too much. Maybe vis-style could be better:
Entering a range, if you type another command, nothing is changed on screen. If you type enter, the range is displayed on screen, and you can continue typing the command, which will act on the current selection.
[EDIT] I was repeating myself.
I am having a strange idea:
It would be used like ed, but always with an overview of the lines above the prompt (like the
z
command), that can scroll with^[FBUDEY]
as in vi. It would be like having a pager always showing the result on top of ed.As you enter ed ranges, the line numbers get highlighted (right when you type them). Maybe working on multiple ranges, separated by a
;
like2,13;32;34s/$/;/
.Maybe it could even only display the selected lines (and not the not-selected around) with a few lines of context (like git diff), skipping lines in-between. Then, while finished, focusing on the dot afterward (with highlighted line number), showing all the lines around.
This would be like vis multiple cursors + structural regex, without the cursors but with ranges instead.
I am keeping this in mind for when I will have some more time.