1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-23 19:48:06 +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
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, `:`.
* No size printing on load
* 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
@ -32,6 +36,8 @@ range is out of bounds.
* `(addrs)p`: Print lines specified in `addrs` range. This is the default
command. If only `(addrs)` is specified, it has the same effect.
* `(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`
### 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
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
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
; 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 ***
;
; Maximum number of lines allowed in the buffer.
.equ BUF_MAXLINES 0x800
; Size of our scratchpad
.equ BUF_PADMAXLEN 0x1000
; Scratchpad mask (only applies on high byte)
.equ BUF_SCRATCHPAD_MASK 0b11110000
; *** Variables ***
; Number of lines currently in the buffer
.equ BUF_LINECNT BUF_RAMSTART
; List of words pointing to scratchpad offsets
.equ BUF_LINES BUF_LINECNT+2
; size of file we read in bufInit. That offset is the beginning of our
; in-memory scratchpad.
.equ BUF_FSIZE BUF_LINES+BUF_MAXLINES*2
; Points to the end of the scratchpad
.equ BUF_PADEND BUF_LINES+BUF_MAXLINES*2
; The in-memory scratchpad
.equ BUF_PADLEN BUF_FSIZE+2
.equ BUF_PAD BUF_PADLEN+2
.equ BUF_PAD BUF_PADEND+2
.equ BUF_RAMEND BUF_PAD+BUF_PADMAXLEN
@ -29,8 +35,8 @@
; On initialization, we read the whole contents of target blkdev and add lines
; as we go.
bufInit:
ld hl, 0
ld (BUF_PADLEN), hl
ld hl, BUF_PAD
ld (BUF_PADEND), hl
ld ix, BUF_LINES
ld bc, 0 ; line count
.loop:
@ -45,8 +51,6 @@ bufInit:
call ioGetLine
jr .loop
.loopend:
; HL currently has the result of the last blkTell
ld (BUF_FSIZE), hl
ld (BUF_LINECNT), bc
ret
@ -76,10 +80,27 @@ bufGetLine:
ld d, (hl)
; DE has seek offset
ex de, hl
; and now HL has it. We're ready to call ioGetLine!
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
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:
pop de
jp unsetZ
@ -125,3 +146,63 @@ bufDelLines:
; Both HL and DE are translated. Go!
ldir
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
cp 'd'
jr z, .okCmd
cp 'a'
jr z, .okCmd
cp 'i'
jr z, .okCmd
; unsupported cmd
ret ; Z unset
.nullCmd:

View File

@ -4,6 +4,7 @@
jp edMain
#include "lib/util.asm"
#include "lib/parse.asm"
.equ IO_RAMSTART USER_RAMSTART
#include "ed/io.asm"

View File

@ -39,9 +39,8 @@
; intoHL
; printstr
; printcrlf
; stdioGetLine
; stdioReadLine
; stdioPutC
; stdioReadC
; unsetZ
;
; *** Variables ***
@ -59,19 +58,24 @@ edMain:
.mainLoop:
ld a, ':'
call stdioPutC
.inner:
call stdioReadC
jr nz, .inner ; not done? loop
; We're done. Process line.
call stdioReadLine ; --> HL
; Now, process line.
call printcrlf
call stdioGetLine
call cmdParse
jr nz, .error
ld a, (CMD_TYPE)
cp 'q'
jr z, .doQuit
; The rest of the commands need an address
call edReadAddrs
jr nz, .error
ld a, (CMD_TYPE)
cp 'd'
jr z, .doDel
cp 'a'
jr z, .doAppend
cp 'i'
jr z, .doInsert
jr .doPrint
.doQuit:
@ -79,16 +83,22 @@ edMain:
ret
.doDel:
call edReadAddrs
jr nz, .error
; bufDelLines expects an exclusive upper bound, which is why we inc DE.
inc de
call bufDelLines
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:
call edReadAddrs
jr nz, .error
.doPrintLoop:
push hl
call bufGetLine
jr nz, .error
@ -98,7 +108,7 @@ edMain:
call cpHLDE
jr z, .doPrintEnd
inc hl
jr .doPrintLoop
jr .doPrint
.doPrintEnd:
ld (ED_CURLINE), hl
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
#include "zasm/const.asm"
#include "lib/util.asm"
#include "zasm/util.asm"
.equ IO_RAMSTART USER_RAMSTART
#include "zasm/io.asm"

View File

@ -107,27 +107,6 @@ strcmp:
; early, set otherwise)
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
; (advance HL and put a null char at the end of the string) and set Z.
; Otherwise, do nothing and reset Z.

View File

@ -202,3 +202,12 @@ stdioReadC:
stdioGetLine:
ld hl, STDIO_BUF
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 printcrlf
jp stdioPutC
jp stdioReadC
jp stdioGetLine
jp stdioReadLine
jp blkGetC
jp blkSeek
jp blkTell

View File

@ -29,8 +29,7 @@
.equ _blkTell 0x45
.equ printcrlf 0x48
.equ stdioPutC 0x4b
.equ stdioReadC 0x4e
.equ stdioGetLine 0x51
.equ blkGetC 0x54
.equ blkSeek 0x57
.equ blkTell 0x5a
.equ stdioReadLine 0x4e
.equ blkGetC 0x51
.equ blkSeek 0x54
.equ blkTell 0x57