1
0
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:
Virgil Dupras 2019-07-14 17:29:00 -04:00
parent 77a23cee84
commit eefadc3917
11 changed files with 163 additions and 53 deletions

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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"

View File

@ -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
View 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

View File

@ -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"

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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