Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
4974993
[framedemo] Add the start of a frame demonstration
rjkroege Feb 5, 2018
bfeda0e
[framedemo] Get key events
rjkroege Feb 5, 2018
98aae3a
[frame] Add package comment.
rjkroege Feb 6, 2018
25c147c
Improve the demo program
rjkroege Feb 10, 2018
a20cc33
Improved function comments
rjkroege Feb 10, 2018
17eeec3
Made the well-defined frame colours public
rjkroege Feb 10, 2018
212cd3a
First text draw
rjkroege Feb 11, 2018
d94c4a0
[Frame Demo] Make it draw
rjkroege Feb 11, 2018
df59d7d
[frame] Unitest for runeindex
rjkroege Feb 11, 2018
3a21b7a
[frame] Correct box model on second insert
rjkroege Feb 14, 2018
f6513e1
[frame] factored out debugging log
rjkroege Feb 14, 2018
37dd278
[frame] Simple insert works
rjkroege Feb 14, 2018
04f9c2b
[frame] fix up the handling of merge and clean
rjkroege Feb 15, 2018
0a61ba7
[frame] Fix bugs in box model for multibyte insert
rjkroege Feb 16, 2018
8e395c0
[frame] Fix insertion of a line-broken string
rjkroege Feb 17, 2018
44874b7
[framedemo] Extend framedemo with model
rjkroege Feb 18, 2018
c7317c6
[frame] Improved mock box in test
rjkroege Feb 20, 2018
473a422
[frame] Adjust logging for delete
rjkroege Feb 20, 2018
c8a69f6
[framedemo] complete ultra-simple framedemo
rjkroege Feb 20, 2018
2f48f51
[frame] addbox more idiomatic and test
rjkroege Feb 22, 2018
73bcee4
[frame] Removed unnecessary log statements
rjkroege Feb 22, 2018
e9adba0
[frame] gofmt on box_test.go
rjkroege Feb 22, 2018
b9c72ed
[frame] refactor boxmodel tests
rjkroege Feb 22, 2018
5d63f55
[frame] added test for closebox
rjkroege Feb 22, 2018
56649f6
[frame] added test for dupbox
rjkroege Feb 22, 2018
5a98f22
[frame] Testability refactor for splitbox
rjkroege Feb 24, 2018
ef5ed93
[frame] More splitbox tests
rjkroege Feb 24, 2018
9ff5b20
[frame] unittests for mergebox
rjkroege Feb 24, 2018
25a5b97
[frame] Removed unnecessary debug output
rjkroege Feb 24, 2018
2adafbf
[frame] Unittests for findbox
rjkroege Feb 24, 2018
05a5625
[frame] Remove unnecessary logging
rjkroege Feb 24, 2018
b2db93a
[frame] delete mostly works
rjkroege Feb 24, 2018
b8e57c0
[frame] canfit unitest
rjkroege Feb 25, 2018
cda694f
[frame] make use of clean consistent
rjkroege Feb 25, 2018
e8c9bde
[acme] extract Disk
rjkroege Feb 28, 2018
97e5ef2
[acme] added a unittest for ntosize
rjkroege Mar 1, 2018
7aae1a5
[acme] Completed disk unittests
rjkroege Mar 3, 2018
975f033
Implement Elog; add a Texter interface (#1)
paul-lalonde Mar 5, 2018
c56be76
[all] Changed README
rjkroege Mar 5, 2018
290e687
[acme] more gofmt
rjkroege Mar 5, 2018
212b9f3
[all] More readme update
rjkroege Mar 5, 2018
c64312b
[frame] Improved test harness
rjkroege Mar 6, 2018
a6649c0
[frame] Test for bxscan
rjkroege Mar 7, 2018
f9f70bc
[frame] Go report card nit
rjkroege Mar 7, 2018
2a31e42
[frame] Go report card formatting nits
rjkroege Mar 7, 2018
d96ac24
[frame] more formatting nits
rjkroege Mar 7, 2018
2645d08
[frame] Fix Go report card complexity nit
rjkroege Mar 7, 2018
973906b
[frame] Start rationalizing the frame accessors
rjkroege Mar 10, 2018
39f935f
[frame] Draw the tick properly
rjkroege Mar 10, 2018
406f167
[frame] Rename _tick to tick
rjkroege Mar 11, 2018
75c85b0
[frame] Correctly change _tick to tick
rjkroege Mar 11, 2018
9e8aae3
[framedemo] added text generation
rjkroege Mar 11, 2018
57a24c6
[frame] Fix more naming issues
rjkroege Mar 11, 2018
5489ebf
[frame] formatting
rjkroege Mar 12, 2018
2b35635
[frame] fix bug in ptofchar
rjkroege Mar 12, 2018
fe0c5d4
[frame] Rename DrawText to drawtext
rjkroege Mar 12, 2018
964d4d8
[frame,framedemo] WIP on selection
rjkroege Mar 12, 2018
b0b6dc2
[frame/framedemo] wip code, selection drawing
rjkroege Mar 18, 2018
e7877c9
[frame/framedemo] working selection and editing
rjkroege Mar 19, 2018
357685e
[frame] Fix resize
rjkroege Mar 20, 2018
6eb55df
[framedemo] Make the demo resizable
rjkroege Mar 20, 2018
ceaa9e9
[frame] Fix bug in Charofpt
rjkroege Mar 21, 2018
ffd841f
[frame] Removed some unnecessary logging
rjkroege Mar 21, 2018
99e7f2f
[framedemo] Extra debugging logs
rjkroege Mar 21, 2018
b574800
Update README.md
rjkroege Mar 24, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
*NB: this is deprecated and will go away in a few days. See https://github.com/rjkroege/edwood instead.*

# acme
Go port of Rob Pike's Acme editor, based on the implementation in plan9port.

Expand All @@ -15,3 +17,10 @@ Go port of Rob Pike's Acme editor, based on the implementation in plan9port.
## Contributions

Contributions are very welcome. Just submit a pull request and we'll review the code before merging it in. I intend to handle the bulk of the transliteration myself, but contributions for the refactor into idiomatic Go are more than welcome.

# Build And Test
[![Go Report Card](https://goreportcard.com/badge/github.com/rjkroege/acme)](https://goreportcard.com/report/github.com/rjkroege/acme)

Project needs work. But I knew that.


6 changes: 3 additions & 3 deletions acme.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package main

import (
"9fans.net/go/draw"
"9fans.net/go/draw"
"github.com/ProjectSerenity/acme/frame"
"image"
)
Expand Down Expand Up @@ -59,9 +59,9 @@ func main() {
img, err := display.AllocImage(image.Rect(0, 0, 1024, 720), draw.RGB16, true, draw.Cyan)
if err != nil {
panic(err)
}
}
f := frame.NewFrame(image.Rect(0, 0, 500, 600), display.DefaultFont, img, cols)

for {
f.Tick(image.ZP, true)
}
Expand Down
8 changes: 8 additions & 0 deletions buf_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package main

import (
"testing"
)

func TestBuf(t *testing.T) {
}
118 changes: 4 additions & 114 deletions dat.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@ package main

import (
"9fans.net/go/draw"
"bytes"
"fmt"
"image"
"io/ioutil"
"os"
"os/user"
"sync"
"unicode/utf8"
)
Expand Down Expand Up @@ -35,12 +30,10 @@ const (
QWxdata
QMAX

Blockincr = 256
MaxBlock = 8 * 1024
NRange = 10
Infinity = 0x7FFFFFFF

STACK = 65536
NRange = 10
// Infinity = 0x7FFFFFFF

// STACK = 65536

Empty = 0
Null = '-'
Expand All @@ -57,8 +50,6 @@ const (
)

var (
blist *Block

globalincref bool
seq uint
maxtab uint /*size of a tab, in units of the '0' character */
Expand Down Expand Up @@ -129,107 +120,6 @@ type Range struct {
q0, q1 int
}

type Block struct {
addr uint // disk address in bytes
n uint // number of used runes in block
next *Block // pointer to next in free list
}

type Disk struct {
fd *os.File
addr uint
free [MaxBlock/Blockincr + 1]*Block
}

func NewDisk() *Disk {
d := new(Disk)
u, err := user.Current()
if err != nil {
panic(err)
}
tmp, err := ioutil.TempFile("/tmp", fmt.Sprintf("X%d.%.4sacme", os.Getpid(), u.Username))
if err != nil {
panic(err)
}
d.fd = tmp
return d
}

func ntosize(n uint) (uint, uint) {
if n > MaxBlock {
panic("internal error: ntosize")
}
size := n
if size&(Blockincr-1) != 0 {
size += Blockincr - (size & (Blockincr - 1))
}

// last bucket holds blocks of exactly Maxblock
ip := size / Blockincr
return size, ip
}

func (d *Disk) NewBlock(n uint) *Block {
size, i := ntosize(n)
b := d.free[i]
if b != nil {
d.free[i] = b.next
} else {
if blist == nil {
bl := new(Block)
blist = bl
for j := 0; j < 100-1; j++ {
bl.next = new(Block)
bl = bl.next
}
}
b = blist
blist = b.next
b.addr = d.addr
d.addr += size
}
b.n = n
return b
}

func (d *Disk) Release(b *Block) {
_, i := ntosize(b.n)
b.next = d.free[i]
d.free[i] = b
}

func (d *Disk) Read(b *Block, r []rune, n uint) {
if n > b.n {
panic("internal error: disk.Read")
}
// this is a simplified way of checking that b.n < MaxBlock
_, _ = ntosize(b.n)
buf := make([]byte, n)
if m, err := d.fd.ReadAt(buf, int64(b.addr)); err != nil {
panic(err)
} else if m != len(r) {
panic("read error from temp file")
}
copy(r, bytes.Runes(buf))
}

func (d *Disk) Write(bp **Block, r []rune, n uint) {
bl := *bp
size, _ := ntosize(bl.n)
nsize, _ := ntosize(n)
if size != nsize {
d.Release(bl)
bl = d.NewBlock(n)
*bp = bl
}
if m, err := d.fd.WriteAt([]byte(string(r)), int64(bl.addr)); err != nil {
panic(err)
} else if m != len(r) {
panic("write error to temp file")
}
bl.n = n
}

type Command struct {
pid int
name []rune
Expand Down
160 changes: 160 additions & 0 deletions disk.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package main

import (
"io/ioutil"
"log"
"os"
"reflect"
"unsafe"
)

// Acme stores blocks as (raw) runes. This does not align well with how Go
// works where the language (rightly) tries to make sure that we don't do
// non-portable C things.
//
// I have switched this to Acme-style raw rune handling to avoid multiple
// copies and rune to byte conversion. This seems better in keeping with how
// Acme actually should work. However, this is not perhaps the right way
// to do it. It might be better to always store files in UTF8 (ideally as strings).

const (
MaxBlock = 8 * 1024
Blockincr = 256
)

type Block struct {
addr uint // disk address in bytes

// NB: in the C version, these are in a union together. Only one is
// used at a time.
n uint // number of used runes in block
next *Block // pointer to next in free list
}

// Disk is a singleton managing the file that Acme blocks. Blocks
// are sized from 256B to 8K in 256B increments.
type Disk struct {
fd *os.File
addr uint
free [MaxBlock/Blockincr + 1]*Block // Disk-backed blocks bucketed by size
blist *Block // Empty block objects
}

// NewDisk creates a new backing on-disk file for Acme's paging.
func NewDisk() *Disk {
// tmp, err := ioutil.TempFile("/tmp", fmt.Sprintf("X%d.%.4sacme", os.Getpid(), u.Username))
tmp, err := ioutil.TempFile("", "acme")
if err != nil {
panic(err)
}
return &Disk{
fd: tmp,
}
}

// ntosize computes the size of block to hold n bytes where n must be
// MaxBlock and the index into the bucket array. The 0-th bucket holds
// only 0-length blocks.
func ntosize(n uint) (uint, uint) {
if n > MaxBlock {
panic("internal error: ntosize")
}
size := n
if size&(Blockincr-1) != 0 {
size += Blockincr - (size & (Blockincr - 1))
}

// last bucket holds blocks of exactly Maxblock
ip := size / Blockincr
return size, ip
}

func (d *Disk) NewBlock(n uint) *Block {
size, i := ntosize(n)
b := d.free[i]
if b != nil {
d.free[i] = b.next
} else {
if d.blist == nil {
// TODO(rjk): Is allocating 1/time really a perf bottleneck in go?
bl := new(Block)
d.blist = bl
for j := 0; j < 100-1; j++ {
bl.next = new(Block)
bl = bl.next
}
}
b = d.blist
d.blist = b.next
b.addr = d.addr
d.addr += size
}
b.n = n
return b
}

func (d *Disk) Release(b *Block) {
_, i := ntosize(b.n)
b.next = d.free[i]
d.free[i] = b
}

// TODO(rjk): Remove the n? Return an error?
func (d *Disk) Read(b *Block, r []rune, n uint) {
if n > b.n {
panic("internal error: disk.Read")
}
// this is a simplified way of checking that b.n < MaxBlock
_, _ = ntosize(b.n)

// Test prior to defeating type safety.
if n > uint(len(r)) {
panic("internal error: disk Read, n greater than r")
}

uby, sz := makeAliasByteArray(r, n)
if m, err := d.fd.ReadAt(uby, int64(b.addr)); err != nil {
panic(err)
} else if m != sz*int(n) {
panic("read error from temp file, m != sz * n ")
}
}

func makeAliasByteArray(r []rune, un uint) ([]byte, int) {
n := int(un)
sz := int(unsafe.Sizeof(' '))
rhdr := (*reflect.SliceHeader)(unsafe.Pointer(&r))

uby := make([]byte, 0)
bhdr := (*reflect.SliceHeader)(unsafe.Pointer(&uby))
bhdr.Data = rhdr.Data
bhdr.Len = sz * n
bhdr.Cap = sz * n

return uby, sz
}

func (d *Disk) Write(bp **Block, r []rune, n uint) {
bl := *bp
size, _ := ntosize(bl.n)
nsize, _ := ntosize(n)
if size != nsize {
d.Release(bl)
bl = d.NewBlock(n)
*bp = bl
}

// Test prior to defeating type safety.
if n > uint(len(r)) {
panic("internal error: disk Write, n greater than r")
}

uby, sz := makeAliasByteArray(r, n)
if m, err := d.fd.WriteAt(uby, int64(bl.addr)); err != nil {
panic(err)
} else if m != int(n)*sz {
log.Println("write mismatch", m, int(n)*sz)
panic("write error to temp file")
}
bl.n = n
}
Loading