mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-27 12:18:07 +11:00
ed: add support for 'a' and 'i'
This commit is contained in:
parent
77a23cee84
commit
eefadc3917
@ -10,11 +10,15 @@ mostly a repeat of `Ued`'s man page.
|
|||||||
## Differences
|
## Differences
|
||||||
|
|
||||||
There are a couple of differences with `Ued` that are intentional. Differences
|
There are a couple of differences with `Ued` that are intentional. Differences
|
||||||
not listed here are either bugs or simply arent implemented yet.
|
not listed here are either bugs or simply aren't implemented yet.
|
||||||
|
|
||||||
* Always has a prompt, `:`.
|
* Always has a prompt, `:`.
|
||||||
* No size printing on load
|
* No size printing on load
|
||||||
* Initial line is the first one
|
* Initial line is the first one
|
||||||
|
* Line input is for one line at once. Less scriptable for `Ued`, but we can't
|
||||||
|
script `ed` in Collapse OS anyway...
|
||||||
|
* For the sake of code simplicity, some commands that make no sense are
|
||||||
|
accepted. For example, `1,2a` is the same as `2a`.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@ -32,6 +36,8 @@ range is out of bounds.
|
|||||||
* `(addrs)p`: Print lines specified in `addrs` range. This is the default
|
* `(addrs)p`: Print lines specified in `addrs` range. This is the default
|
||||||
command. If only `(addrs)` is specified, it has the same effect.
|
command. If only `(addrs)` is specified, it has the same effect.
|
||||||
* `(addrs)d`: Delete lines specified in `addrs` range.
|
* `(addrs)d`: Delete lines specified in `addrs` range.
|
||||||
|
* `(addr)a`: Appends a line after `addr`.
|
||||||
|
* `(addr)i`: Insert a line before `addr`.
|
||||||
* `q`: quit `ed`
|
* `q`: quit `ed`
|
||||||
|
|
||||||
### Current line
|
### Current line
|
||||||
@ -41,7 +47,7 @@ to it and makes the app much more usable. The current line starts at `1` and
|
|||||||
every command changes the current line to the last line that the command
|
every command changes the current line to the last line that the command
|
||||||
affects. For example, `42p` changes the current line to `42`, `3,7d`, to 7.
|
affects. For example, `42p` changes the current line to `42`, `3,7d`, to 7.
|
||||||
|
|
||||||
### Address ranges
|
### Addresses
|
||||||
|
|
||||||
An "address" is a line number. The first line is `1`. An address range is a
|
An "address" is a line number. The first line is `1`. An address range is a
|
||||||
start line and a stop line, expressed as `start,stop`. For example, `2,4` refer
|
start line and a stop line, expressed as `start,stop`. For example, `2,4` refer
|
||||||
|
101
apps/ed/buf.asm
101
apps/ed/buf.asm
@ -3,24 +3,30 @@
|
|||||||
; Lines in edited file aren't loaded in memory, their offsets is referenced to
|
; Lines in edited file aren't loaded in memory, their offsets is referenced to
|
||||||
; in this buffer.
|
; in this buffer.
|
||||||
;
|
;
|
||||||
|
; About scratchpad and offsets. There are two scratchpads: file and memory.
|
||||||
|
; The file one is the contents of the active blkdev. The second one is
|
||||||
|
; in-memory, for edits. We differentiate between the two with a
|
||||||
|
; "scatchpad mask". When the high bits of the offset match the mask, then we
|
||||||
|
; know that this offset is from the scratchpad.
|
||||||
|
;
|
||||||
; *** Consts ***
|
; *** Consts ***
|
||||||
;
|
;
|
||||||
; Maximum number of lines allowed in the buffer.
|
; Maximum number of lines allowed in the buffer.
|
||||||
.equ BUF_MAXLINES 0x800
|
.equ BUF_MAXLINES 0x800
|
||||||
; Size of our scratchpad
|
; Size of our scratchpad
|
||||||
.equ BUF_PADMAXLEN 0x1000
|
.equ BUF_PADMAXLEN 0x1000
|
||||||
|
; Scratchpad mask (only applies on high byte)
|
||||||
|
.equ BUF_SCRATCHPAD_MASK 0b11110000
|
||||||
|
|
||||||
; *** Variables ***
|
; *** Variables ***
|
||||||
; Number of lines currently in the buffer
|
; Number of lines currently in the buffer
|
||||||
.equ BUF_LINECNT BUF_RAMSTART
|
.equ BUF_LINECNT BUF_RAMSTART
|
||||||
; List of words pointing to scratchpad offsets
|
; List of words pointing to scratchpad offsets
|
||||||
.equ BUF_LINES BUF_LINECNT+2
|
.equ BUF_LINES BUF_LINECNT+2
|
||||||
; size of file we read in bufInit. That offset is the beginning of our
|
; Points to the end of the scratchpad
|
||||||
; in-memory scratchpad.
|
.equ BUF_PADEND BUF_LINES+BUF_MAXLINES*2
|
||||||
.equ BUF_FSIZE BUF_LINES+BUF_MAXLINES*2
|
|
||||||
; The in-memory scratchpad
|
; The in-memory scratchpad
|
||||||
.equ BUF_PADLEN BUF_FSIZE+2
|
.equ BUF_PAD BUF_PADEND+2
|
||||||
.equ BUF_PAD BUF_PADLEN+2
|
|
||||||
|
|
||||||
.equ BUF_RAMEND BUF_PAD+BUF_PADMAXLEN
|
.equ BUF_RAMEND BUF_PAD+BUF_PADMAXLEN
|
||||||
|
|
||||||
@ -29,8 +35,8 @@
|
|||||||
; On initialization, we read the whole contents of target blkdev and add lines
|
; On initialization, we read the whole contents of target blkdev and add lines
|
||||||
; as we go.
|
; as we go.
|
||||||
bufInit:
|
bufInit:
|
||||||
ld hl, 0
|
ld hl, BUF_PAD
|
||||||
ld (BUF_PADLEN), hl
|
ld (BUF_PADEND), hl
|
||||||
ld ix, BUF_LINES
|
ld ix, BUF_LINES
|
||||||
ld bc, 0 ; line count
|
ld bc, 0 ; line count
|
||||||
.loop:
|
.loop:
|
||||||
@ -45,8 +51,6 @@ bufInit:
|
|||||||
call ioGetLine
|
call ioGetLine
|
||||||
jr .loop
|
jr .loop
|
||||||
.loopend:
|
.loopend:
|
||||||
; HL currently has the result of the last blkTell
|
|
||||||
ld (BUF_FSIZE), hl
|
|
||||||
ld (BUF_LINECNT), bc
|
ld (BUF_LINECNT), bc
|
||||||
ret
|
ret
|
||||||
|
|
||||||
@ -76,10 +80,27 @@ bufGetLine:
|
|||||||
ld d, (hl)
|
ld d, (hl)
|
||||||
; DE has seek offset
|
; DE has seek offset
|
||||||
ex de, hl
|
ex de, hl
|
||||||
; and now HL has it. We're ready to call ioGetLine!
|
|
||||||
pop de
|
pop de
|
||||||
|
; is it a scratchpad offset?
|
||||||
|
ld a, h
|
||||||
|
and BUF_SCRATCHPAD_MASK
|
||||||
|
cp BUF_SCRATCHPAD_MASK
|
||||||
|
jr z, .fromScratchpad
|
||||||
|
; not from scratchpad
|
||||||
cp a ; ensure Z
|
cp a ; ensure Z
|
||||||
jp ioGetLine ; preserves AF
|
jp ioGetLine ; preserves AF
|
||||||
|
.fromScratchpad:
|
||||||
|
; remove scratchpad mask
|
||||||
|
ld a, BUF_SCRATCHPAD_MASK
|
||||||
|
xor 0xff
|
||||||
|
and h
|
||||||
|
ld h, a
|
||||||
|
; HL is now a mask-less offset to BUF_PAD
|
||||||
|
push de ; --> lvl 1
|
||||||
|
ld de, BUF_PAD
|
||||||
|
add hl, de
|
||||||
|
pop de ; <-- lvl 1
|
||||||
|
ret
|
||||||
.outOfBounds:
|
.outOfBounds:
|
||||||
pop de
|
pop de
|
||||||
jp unsetZ
|
jp unsetZ
|
||||||
@ -125,3 +146,63 @@ bufDelLines:
|
|||||||
; Both HL and DE are translated. Go!
|
; Both HL and DE are translated. Go!
|
||||||
ldir
|
ldir
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
; Insert string where DE points to memory scratchpad, then insert that line
|
||||||
|
; at index HL, offsetting all lines by 2 bytes.
|
||||||
|
bufInsertLine:
|
||||||
|
push de ; --> lvl 1, scratchpad offset
|
||||||
|
push hl ; --> lvl 2, insert index
|
||||||
|
; The logic below is mostly copy-pasted from bufDelLines, but with a
|
||||||
|
; LDDR logic (to avoid overwriting). I learned, with some pain involved,
|
||||||
|
; that generalizing this code wasn't working very well. I don't repeat
|
||||||
|
; the comments, refer to bufDelLines
|
||||||
|
ex de, hl ; line index now in DE
|
||||||
|
ld hl, (BUF_LINECNT)
|
||||||
|
scf \ ccf
|
||||||
|
sbc hl, de
|
||||||
|
; mult by 2 and we're done
|
||||||
|
sla l \ rl h
|
||||||
|
push hl \ pop bc
|
||||||
|
; From this point, we don't need our line index in DE any more because
|
||||||
|
; LDDR will start from BUF_LINECNT-1 with count BC. We'll only need it
|
||||||
|
; when it's time to insert the line in the space we make.
|
||||||
|
ld hl, (BUF_LINECNT)
|
||||||
|
call bufLineAddr
|
||||||
|
push hl \ pop de
|
||||||
|
dec hl
|
||||||
|
dec hl
|
||||||
|
; HL = BUF_LINECNT-1, DE = BUF_LINECNT, BC is set. We're good!
|
||||||
|
lddr
|
||||||
|
; We still need to increase BUF_LINECNT
|
||||||
|
ld hl, (BUF_LINECNT)
|
||||||
|
inc hl
|
||||||
|
ld (BUF_LINECNT), hl
|
||||||
|
; A space has been opened at line index HL. Let's fill it with our
|
||||||
|
; inserted line.
|
||||||
|
pop hl ; <-- lvl 2, insert index
|
||||||
|
call bufLineAddr
|
||||||
|
pop de ; <-- lvl 1, scratchpad offset
|
||||||
|
ld (hl), e
|
||||||
|
inc hl
|
||||||
|
ld (hl), d
|
||||||
|
ret
|
||||||
|
|
||||||
|
; copy string that HL points to to scratchpad and return its seek offset, in HL.
|
||||||
|
bufScratchpadAdd:
|
||||||
|
push de
|
||||||
|
ld de, (BUF_PADEND)
|
||||||
|
push de ; --> lvl 1
|
||||||
|
call strcpyM
|
||||||
|
ld (BUF_PADEND), de
|
||||||
|
pop hl ; <-- lvl 1
|
||||||
|
; we have a memory offset in HL, but it's not what we want! we want a
|
||||||
|
; seek offset stamped with the "scratchpad mask"
|
||||||
|
ld de, BUF_PAD
|
||||||
|
scf \ ccf
|
||||||
|
sbc hl, de
|
||||||
|
ld a, h
|
||||||
|
or BUF_SCRATCHPAD_MASK
|
||||||
|
ld h, a
|
||||||
|
; now we're good...
|
||||||
|
pop de
|
||||||
|
ret
|
||||||
|
@ -55,6 +55,10 @@ cmdParse:
|
|||||||
jr z, .okCmd
|
jr z, .okCmd
|
||||||
cp 'd'
|
cp 'd'
|
||||||
jr z, .okCmd
|
jr z, .okCmd
|
||||||
|
cp 'a'
|
||||||
|
jr z, .okCmd
|
||||||
|
cp 'i'
|
||||||
|
jr z, .okCmd
|
||||||
; unsupported cmd
|
; unsupported cmd
|
||||||
ret ; Z unset
|
ret ; Z unset
|
||||||
.nullCmd:
|
.nullCmd:
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
jp edMain
|
jp edMain
|
||||||
|
|
||||||
|
#include "lib/util.asm"
|
||||||
#include "lib/parse.asm"
|
#include "lib/parse.asm"
|
||||||
.equ IO_RAMSTART USER_RAMSTART
|
.equ IO_RAMSTART USER_RAMSTART
|
||||||
#include "ed/io.asm"
|
#include "ed/io.asm"
|
||||||
|
@ -39,9 +39,8 @@
|
|||||||
; intoHL
|
; intoHL
|
||||||
; printstr
|
; printstr
|
||||||
; printcrlf
|
; printcrlf
|
||||||
; stdioGetLine
|
; stdioReadLine
|
||||||
; stdioPutC
|
; stdioPutC
|
||||||
; stdioReadC
|
|
||||||
; unsetZ
|
; unsetZ
|
||||||
;
|
;
|
||||||
; *** Variables ***
|
; *** Variables ***
|
||||||
@ -59,19 +58,24 @@ edMain:
|
|||||||
.mainLoop:
|
.mainLoop:
|
||||||
ld a, ':'
|
ld a, ':'
|
||||||
call stdioPutC
|
call stdioPutC
|
||||||
.inner:
|
call stdioReadLine ; --> HL
|
||||||
call stdioReadC
|
; Now, process line.
|
||||||
jr nz, .inner ; not done? loop
|
|
||||||
; We're done. Process line.
|
|
||||||
call printcrlf
|
call printcrlf
|
||||||
call stdioGetLine
|
|
||||||
call cmdParse
|
call cmdParse
|
||||||
jr nz, .error
|
jr nz, .error
|
||||||
ld a, (CMD_TYPE)
|
ld a, (CMD_TYPE)
|
||||||
cp 'q'
|
cp 'q'
|
||||||
jr z, .doQuit
|
jr z, .doQuit
|
||||||
|
; The rest of the commands need an address
|
||||||
|
call edReadAddrs
|
||||||
|
jr nz, .error
|
||||||
|
ld a, (CMD_TYPE)
|
||||||
cp 'd'
|
cp 'd'
|
||||||
jr z, .doDel
|
jr z, .doDel
|
||||||
|
cp 'a'
|
||||||
|
jr z, .doAppend
|
||||||
|
cp 'i'
|
||||||
|
jr z, .doInsert
|
||||||
jr .doPrint
|
jr .doPrint
|
||||||
|
|
||||||
.doQuit:
|
.doQuit:
|
||||||
@ -79,16 +83,22 @@ edMain:
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
.doDel:
|
.doDel:
|
||||||
call edReadAddrs
|
|
||||||
jr nz, .error
|
|
||||||
; bufDelLines expects an exclusive upper bound, which is why we inc DE.
|
; bufDelLines expects an exclusive upper bound, which is why we inc DE.
|
||||||
inc de
|
inc de
|
||||||
call bufDelLines
|
call bufDelLines
|
||||||
jr .mainLoop
|
jr .mainLoop
|
||||||
|
.doAppend:
|
||||||
|
inc de
|
||||||
|
.doInsert:
|
||||||
|
call stdioReadLine ; --> HL
|
||||||
|
call bufScratchpadAdd ; --> HL
|
||||||
|
; insert index in DE, line offset in HL. We want the opposite.
|
||||||
|
ex de, hl
|
||||||
|
call bufInsertLine
|
||||||
|
call printcrlf
|
||||||
|
jr .mainLoop
|
||||||
|
|
||||||
.doPrint:
|
.doPrint:
|
||||||
call edReadAddrs
|
|
||||||
jr nz, .error
|
|
||||||
.doPrintLoop:
|
|
||||||
push hl
|
push hl
|
||||||
call bufGetLine
|
call bufGetLine
|
||||||
jr nz, .error
|
jr nz, .error
|
||||||
@ -98,7 +108,7 @@ edMain:
|
|||||||
call cpHLDE
|
call cpHLDE
|
||||||
jr z, .doPrintEnd
|
jr z, .doPrintEnd
|
||||||
inc hl
|
inc hl
|
||||||
jr .doPrintLoop
|
jr .doPrint
|
||||||
.doPrintEnd:
|
.doPrintEnd:
|
||||||
ld (ED_CURLINE), hl
|
ld (ED_CURLINE), hl
|
||||||
jr .mainLoop
|
jr .mainLoop
|
||||||
|
21
apps/lib/util.asm
Normal file
21
apps/lib/util.asm
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
; Copy string from (HL) in (DE), that is, copy bytes until a null char is
|
||||||
|
; encountered. The null char is also copied.
|
||||||
|
; HL and DE point to the char right after the null char.
|
||||||
|
strcpyM:
|
||||||
|
ld a, (hl)
|
||||||
|
ld (de), a
|
||||||
|
inc hl
|
||||||
|
inc de
|
||||||
|
or a
|
||||||
|
jr nz, strcpyM
|
||||||
|
ret
|
||||||
|
|
||||||
|
; Like strcpyM, but preserve HL and DE
|
||||||
|
strcpy:
|
||||||
|
push hl
|
||||||
|
push de
|
||||||
|
call strcpyM
|
||||||
|
pop de
|
||||||
|
pop hl
|
||||||
|
ret
|
||||||
|
|
@ -53,6 +53,7 @@
|
|||||||
jp zasmMain
|
jp zasmMain
|
||||||
|
|
||||||
#include "zasm/const.asm"
|
#include "zasm/const.asm"
|
||||||
|
#include "lib/util.asm"
|
||||||
#include "zasm/util.asm"
|
#include "zasm/util.asm"
|
||||||
.equ IO_RAMSTART USER_RAMSTART
|
.equ IO_RAMSTART USER_RAMSTART
|
||||||
#include "zasm/io.asm"
|
#include "zasm/io.asm"
|
||||||
|
@ -107,27 +107,6 @@ strcmp:
|
|||||||
; early, set otherwise)
|
; early, set otherwise)
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Copy string from (HL) in (DE), that is, copy bytes until a null char is
|
|
||||||
; encountered. The null char is also copied.
|
|
||||||
; HL and DE point to the char right after the null char.
|
|
||||||
strcpyM:
|
|
||||||
ld a, (hl)
|
|
||||||
ld (de), a
|
|
||||||
inc hl
|
|
||||||
inc de
|
|
||||||
or a
|
|
||||||
jr nz, strcpyM
|
|
||||||
ret
|
|
||||||
|
|
||||||
; Like strcpyM, but preserve HL and DE
|
|
||||||
strcpy:
|
|
||||||
push hl
|
|
||||||
push de
|
|
||||||
call strcpyM
|
|
||||||
pop de
|
|
||||||
pop hl
|
|
||||||
ret
|
|
||||||
|
|
||||||
; If string at (HL) starts with ( and ends with ), "enter" into the parens
|
; If string at (HL) starts with ( and ends with ), "enter" into the parens
|
||||||
; (advance HL and put a null char at the end of the string) and set Z.
|
; (advance HL and put a null char at the end of the string) and set Z.
|
||||||
; Otherwise, do nothing and reset Z.
|
; Otherwise, do nothing and reset Z.
|
||||||
|
@ -202,3 +202,12 @@ stdioReadC:
|
|||||||
stdioGetLine:
|
stdioGetLine:
|
||||||
ld hl, STDIO_BUF
|
ld hl, STDIO_BUF
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
; Repeatedly call stdioReadC until Z is set, then make HL point to the read
|
||||||
|
; buffer.
|
||||||
|
stdioReadLine:
|
||||||
|
call stdioReadC
|
||||||
|
jr nz, stdioReadLine
|
||||||
|
ld hl, STDIO_BUF
|
||||||
|
ret
|
||||||
|
|
||||||
|
@ -36,8 +36,7 @@
|
|||||||
jp _blkTell
|
jp _blkTell
|
||||||
jp printcrlf
|
jp printcrlf
|
||||||
jp stdioPutC
|
jp stdioPutC
|
||||||
jp stdioReadC
|
jp stdioReadLine
|
||||||
jp stdioGetLine
|
|
||||||
jp blkGetC
|
jp blkGetC
|
||||||
jp blkSeek
|
jp blkSeek
|
||||||
jp blkTell
|
jp blkTell
|
||||||
|
@ -29,8 +29,7 @@
|
|||||||
.equ _blkTell 0x45
|
.equ _blkTell 0x45
|
||||||
.equ printcrlf 0x48
|
.equ printcrlf 0x48
|
||||||
.equ stdioPutC 0x4b
|
.equ stdioPutC 0x4b
|
||||||
.equ stdioReadC 0x4e
|
.equ stdioReadLine 0x4e
|
||||||
.equ stdioGetLine 0x51
|
.equ blkGetC 0x51
|
||||||
.equ blkGetC 0x54
|
.equ blkSeek 0x54
|
||||||
.equ blkSeek 0x57
|
.equ blkTell 0x57
|
||||||
.equ blkTell 0x5a
|
|
||||||
|
Loading…
Reference in New Issue
Block a user