Skip to content

Commit

Permalink
cleanup for v1
Browse files Browse the repository at this point in the history
  • Loading branch information
xt0fer committed Nov 27, 2018
1 parent a5f9328 commit e18b125
Show file tree
Hide file tree
Showing 25 changed files with 106 additions and 2,328 deletions.
116 changes: 0 additions & 116 deletions CHANGE.LOG.md

This file was deleted.

15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# kg Emacs

A small functional Emacs in Go
A small functional Emacs written in Go

kg Emacs is inspired by Atto Emacs (by Hugh Barney), MicroEmacs, Nano, Pico and his earlier project known as Perfect Emacs [1].
kg Emacs is inspired by Atto Emacs (by Hugh Barney), MicroEmacs, Nano, Pico and his earlier project known as Perfect Emacs [1]. Also by JOE, uEmacs, MicroEmacs, mg, zile and of course, GNU Emacs. I learnt Emacs on a Sun 2/120 a long time ago in a galaxy far, far, away.


> A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away.
Expand All @@ -13,9 +13,12 @@ kg Emacs is inspired by Atto Emacs (by Hugh Barney), MicroEmacs, Nano, Pico and
## Goals of kg Emacs

* Mine own, finally.
* Mine own, finally, in Go.
* uses an array of Rune to handle Unicode codepoints.
* no damn Overwrite mode. Too bad.
* pure Go implementation
* removal of the C-based hilite stuff
* add go routines for some operations.
* ...
* Be easy to understand without extensive study (to encourage further experimentation).

Expand All @@ -24,7 +27,7 @@ Using Atto as the lowest functional Emacs, Hugh had to consider the essential fe

## Derivation

kg is based on the design of Atto Emacs which is based on the public domain code of Anthony Howe's editor (commonly known as Anthony's Editor or AE, [2]). Rather than representing a file as a linked list of lines, the AE Editor uses the concept of a Buffer-Gap [4,5,6]. A Buffer-Gap editor stores the file in a single piece of contiguous memory with some extra unused space known as the buffer gap. On character insertion and deletion the gap is first moved to the current point. A character deletion then extends the gap by moving the gap pointer back by 1 OR the gap is reduced by 1 when a character is inserted. The Buffer-Gap technique is elegant and significantly reduces the amount of code required to load a file, modify it and redraw the display. The proof of this is seen when you consider that Atto supports almost the same command set that Pico supports, but Pico requires almost 17 times the amount of code.
kg is based on the design of _Atto Emacs which is based on the public domain code of Anthony Howe's editor (commonly known as Anthony's Editor or AE, [2]). Rather than representing a file as a linked list of lines, the AE Editor uses the concept of a Buffer-Gap [4,5,6]. A Buffer-Gap editor stores the file in a single piece of contiguous memory with some extra unused space known as the buffer gap. On character insertion and deletion the gap is first moved to the current point. A character deletion then extends the gap by moving the gap pointer back by 1 OR the gap is reduced by 1 when a character is inserted. The Buffer-Gap technique is elegant and significantly reduces the amount of code required to load a file, modify it and redraw the display. The proof of this is seen when you consider that Atto supports almost the same command set that Pico supports, but Pico requires almost 17 times the amount of code._

## Comparisons with Other Emacs Implementations

Expand Down Expand Up @@ -155,7 +158,7 @@ Maybe a piece-table or piece-chain implementation? Maybe a different key mapping

## Multiple Windows or Not?

Kg supports multiple windows
Kg supports multiple windows.

## Known Issues

Expand All @@ -181,5 +184,5 @@ Kg supports multiple windows
[3] MG - https://github.com/rzalamena/mg
[4] Jonathan Payne, Buffer-Gap: http://ned.rubyforge.org/doc/buffer-gap.txt
[5] Anthony Howe, http://ned.rubyforge.org/doc/editor-101.txt
[6] Anthony Howe, http://ned.rubyforge.org/doc/editor-102.txt
[6] Hugh Barney, https://github.com/hughbarney/atto

6 changes: 6 additions & 0 deletions ToDo.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# To Do

* screen down and up TBD
* word movement (who does that) is TBD
* mouse to change windows (only works with one-window)
* the CollapseGap idea needs to be optimized, too sloppy rght now
* make editing larger files faster by optimizing the Buffer stuff
* the error(s) from RuneAt which are currently panic-ing on check, should be handled differently
* and what's with func window2Buffer(w *Window) (window.go); needs the multiwindow update unfangled.
84 changes: 34 additions & 50 deletions buffer.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,30 @@ import (
"fmt"
)

/*
* Buffer is where all the opertions on the main rune array are implemented.
* Because of the Gap, all the indexing around it should be done by these routines.
*/

// Buffer main struct
type Buffer struct {
data []rune
preLen int
postLen int
Next *Buffer /* b_next Link to next buffer_t */
Mark int /* b_mark the mark */
OrigPoint int /* b_cpoint the original current point, used for mutliple window displaying */
PageStart int /* b_page start of page */
PageEnd int /* b_epage end of page */
Reframe bool /* b_reframe force a reframe of the display */
WinCount int /* b_cnt count of windows referencing this buffer */
TextSize int /* b_size current size of text being edited (not including gap) */
PrevSize int /* b_psize previous size */
PointRow int /* b_row Point row */
PointCol int /* b_col Point col */
Filename string // b_fname[NAME_MAX + 1]; /* filename */
Buffername string //[b_bnameSTRBUF_S]; /* buffer name */
Flags byte /* char b_flags buffer flags */
data []rune
preLen int
postLen int
Next *Buffer /* b_next Link to next buffer_t */
Mark int /* b_mark the mark */
OrigPoint int /* b_cpoint the original current point, used for mutliple window displaying */
PageStart int /* b_page start of page */
PageEnd int /* b_epage end of page */
Reframe bool /* b_reframe force a reframe of the display */
WinCount int /* b_cnt count of windows referencing this buffer */
TextSize int /* b_size current size of text being edited (not including gap) */
PrevSize int /* b_psize previous size */
PointRow int /* b_row Point row */
PointCol int /* b_col Point col */
Filename string // b_fname[NAME_MAX + 1]; /* filename */
Buffername string //[b_bnameSTRBUF_S]; /* buffer name */
Flags byte /* char b_flags buffer flags */
modified bool
}

Expand All @@ -35,34 +40,27 @@ func (bp *Buffer) MarkModified() {
// NewBuffer - Create a new Buffer
func NewBuffer() *Buffer {
nb := Buffer{}
nb.data = []rune("\n")
nb.preLen = 0
nb.postLen = len(nb.data)
nb.setText("\n")
return &nb
}

// SetText xxx
func (bp *Buffer) SetText(s string) {
// setText xxx
func (bp *Buffer) setText(s string) {
bp.data = []rune(s)
bp.preLen = 0
bp.postLen = len(bp.data)
}

// GetText xxx
func (bp *Buffer) GetText() string {
// getText xxx
func (bp *Buffer) getText() string {
ret := make([]rune, bp.preLen+bp.postLen)
copy(ret, bp.data)
copy(ret[bp.preLen:], bp.data[bp.postStart():])
return string(ret)
}

func (bp *Buffer) logBufferEOB(pt int) {

}

// RuneAt finally reliable!!
func (bp *Buffer) RuneAt(pt int) (rune, error) {
bp.logBufferEOB(pt)
if pt >= len(bp.data) {
return 0, errors.New("Beyond data buffer in RuneAt")
}
Expand All @@ -88,10 +86,6 @@ func (bp *Buffer) dataPointForBufferPoint(pt int) int {

// AddRune add a run to the buffer
func (bp *Buffer) AddRune(ch rune) {
// if bp.data == nil {
// bp.SetText(string(ch))
// return
// }
if bp.gapLen() == 0 {
_ = bp.GrowGap(gapchunk)
}
Expand All @@ -107,7 +101,6 @@ func (bp *Buffer) Point() int {

// SetPoint set the current point to np
func (bp *Buffer) SetPoint(np int) {
bp.logBufferEOB(np)
bp.CollapseGap()
// move gap <-(left) by np chars
gs := bp.gapStart()
Expand All @@ -117,17 +110,10 @@ func (bp *Buffer) SetPoint(np int) {
bp.postLen++
}
if bp.PageEnd < bp.preLen {
//// log.Println("reframing!")
bp.Reframe = true
}
}

//SetPointAndCursor xxx
func (bp *Buffer) SetPointAndCursor(np int) {
bp.SetPoint(np)
bp.setCursor()
}

// setCursor xxx
func (bp *Buffer) setCursor() {
x, y := bp.XYForPoint(bp.preLen)
Expand Down Expand Up @@ -184,11 +170,10 @@ func (bp *Buffer) Insert(s string) {
bp.MarkModified()
}

// GetTextForLines return string for [l1, l2) (l2 not included)
func (bp *Buffer) GetTextForLines(l1, l2 int) string {
// getTextForLines return string for [l1, l2) (l2 not included)
func (bp *Buffer) getTextForLines(l1, l2 int) string {
pt1 := bp.PointForLine(l1)
pt2 := bp.PointForLine(l2)
//fmt.Println(pt1, pt2)
ret := make([]rune, pt2-pt1)
j := 0
for i := pt1; j < len(ret); i++ {
Expand Down Expand Up @@ -479,7 +464,8 @@ func (bp *Buffer) PointUp() {
if npt < bp.PageStart {
bp.Reframe = true
}
bp.SetPointAndCursor(npt)
bp.SetPoint(npt)
bp.setCursor()
}

// PointDown move point down one line
Expand All @@ -495,7 +481,8 @@ func (bp *Buffer) PointDown() {
if npt > bp.PageEnd {
bp.Reframe = true
}
bp.SetPointAndCursor(npt)
bp.SetPoint(npt)
bp.setCursor()
}

// PointNext move point left one
Expand All @@ -518,8 +505,6 @@ func (bp *Buffer) PointPrevious() {
bp.data[bp.postStart()-1] = bp.data[bp.preLen-1]
bp.preLen--
bp.postLen++
//bp.setCursor()
bp.logBufferEOB(bp.preLen)
}

// UpUp Move up one screen line
Expand All @@ -536,7 +521,6 @@ func (bp *Buffer) UpUp(pt, cc int) int {

// DownDown Move down one screen line
func (bp *Buffer) DownDown(pt, cc int) int {
//bp := e.CurrentBuffer
return bp.SegNext(bp.LineStart(pt), pt, cc)
}

Expand All @@ -548,7 +532,7 @@ func (bp *Buffer) GetLineStats() (curline int, lastline int) {
return curline, lastline
}

// DebugPrint xxx
// DebugPrint prints out a view of the buffer and the gap and so on.
func (bp *Buffer) DebugPrint() {
fmt.Printf("*********(gap)\n")
for i := 0; i < len(bp.data); i++ {
Expand Down
Loading

0 comments on commit e18b125

Please sign in to comment.