Basic function kinda works
This commit is contained in:
@@ -2,4 +2,4 @@ from hissp.reader import transpile
|
||||
transpile(__package__, "livesort", "test_livesort")
|
||||
del transpile
|
||||
|
||||
from livesort_hssp.livesort import livesort, render
|
||||
from livesort_hssp.livesort import Livesort
|
||||
|
||||
@@ -1,44 +1,72 @@
|
||||
(hissp.basic.._macro_.prelude)
|
||||
|
||||
(defmacro setq (symbol value)
|
||||
"lol this isn't even my lisp"
|
||||
`(setitem (locals) (quote ,symbol) ,value))
|
||||
|
||||
(define livesort
|
||||
(lambda (next-line ; iterable function
|
||||
print ; function to write output
|
||||
height ; window/screen height in lines
|
||||
width ; window/screen width in characters
|
||||
)
|
||||
(let (lines (list) ; sorted lines
|
||||
cursor 0 ; line number to keep on screen and highlight
|
||||
quitting? False ; set flag to exit loop
|
||||
)
|
||||
;; the cursor is thought to exist between line `cursor` and `cursor - 1`
|
||||
(any-for line next-line
|
||||
(let (lineno (bisect..bisect lines line))
|
||||
(unless (gt lineno cursor)
|
||||
(setq cursor (add cursor 1)))
|
||||
(.insert lines lineno line)
|
||||
(print (.format "c{}" (render lines cursor height width))))
|
||||
quitting?))))
|
||||
(deftype Livesort ()
|
||||
__init__
|
||||
(lambda (self
|
||||
next-line ; iterable function yielding lines of text
|
||||
print ; function to write output
|
||||
height ; window/screen height in lines
|
||||
width ; window/screen width in characters
|
||||
)
|
||||
(attach self next-line print height width :
|
||||
lines (list) ; sorted input lines
|
||||
screen (list (mul height '(None))))
|
||||
None) ; __init__ required to return `None`
|
||||
|
||||
(define render
|
||||
(lambda (lines ; sequence of sorted lines
|
||||
cursor ; line to keep on-screen
|
||||
height ; window height
|
||||
width ; and width
|
||||
)
|
||||
(.join "\n"
|
||||
(map (lambda (line) (getitem line (slice 0 width)))
|
||||
(getitem lines
|
||||
(let (r (ifloordiv height 2))
|
||||
(slice (max 0 (sub cursor r))
|
||||
(min (len lines) (add cursor r)))))))))
|
||||
sortline
|
||||
(lambda (self line)
|
||||
"Insort a line and update the cursor position"
|
||||
(when (.strip line)
|
||||
(let (lineno (bisect..bisect self.lines line))
|
||||
;; Normally would use `..insort` but there's going to be more
|
||||
(.insert self.lines lineno line))))
|
||||
|
||||
render
|
||||
(lambda (self)
|
||||
"Produce a list of the lines which should be visible, cropped to `width`"
|
||||
(list (map (lambda (line) (getitem line (slice None self.width)))
|
||||
(getitem self.lines (slice None self.height)))))
|
||||
|
||||
display
|
||||
(lambda (self)
|
||||
"Compare `(self.render)` to `self.screen` and return a string that
|
||||
will update the display."
|
||||
(let (output (list)
|
||||
lines (self.render)
|
||||
changed? (list))
|
||||
(.append output "[H") ; Home cursor
|
||||
(any-for lineno (range self.height)
|
||||
(let (line (if-else (lt lineno (len lines))
|
||||
(getitem lines lineno)
|
||||
""))
|
||||
(unless (eq line (getitem self.screen lineno))
|
||||
(setitem self.screen lineno line)
|
||||
(.append changed? line)
|
||||
;; ^[[K to erase any characters that follow on this line
|
||||
(.append output (.format "{}[K"
|
||||
(.rstrip line (chr 0x0a)))))
|
||||
(.append output (chr 0x0a))) ; Move to beginning of next line
|
||||
False)
|
||||
;; If something changed, don't bother outputting the last cursor
|
||||
;; movement code. If nothing changed, don't bother outputting
|
||||
;; anything.
|
||||
(if-else changed?
|
||||
(.join "" (getitem output (slice None -1)))
|
||||
"")))
|
||||
|
||||
livesort
|
||||
(lambda (self)
|
||||
"Process every input line, updating screen each line"
|
||||
(any-for line self.next-line
|
||||
(.sortline self line)
|
||||
(.print self (.display self))
|
||||
False)))
|
||||
|
||||
(when (eq __name__ '__main__)
|
||||
(livesort sys..stdin
|
||||
sys..stdout.write
|
||||
(int (|| (os..getenv 'LINES) "24"))
|
||||
(int (|| (os..getenv 'COLUMNS) "80"))))
|
||||
(.livesort (Livesort sys..stdin
|
||||
(lambda (data)
|
||||
(sys..stdout.write data)
|
||||
(sys..stdout.flush))
|
||||
(int (|| (os..getenv 'LINES) "24"))
|
||||
(int (|| (os..getenv 'COLUMNS) "80")))))
|
||||
|
||||
@@ -1,8 +1,63 @@
|
||||
(hissp.basic.._macro_.prelude)
|
||||
|
||||
(deftype TestLivesort (unittest..TestCase)
|
||||
setUp
|
||||
(lambda (self)
|
||||
(attach self :
|
||||
input-buf (list)
|
||||
output-buf (list)
|
||||
ls (livesort_hssp.livesort..Livesort self.input-buf
|
||||
self.output-buf.append
|
||||
4
|
||||
8)))
|
||||
|
||||
tearDown
|
||||
(lambda (self)
|
||||
(delattr self 'ls)
|
||||
(delattr self 'output-buf)
|
||||
(delattr self 'input-buf))
|
||||
|
||||
test_Livesort
|
||||
(lambda (self)
|
||||
(cascade self
|
||||
(.assertEqual self.ls.next-line self.input-buf)
|
||||
(.assertEqual self.ls.print self.output-buf.append)
|
||||
(.assertEqual self.ls.height 4)
|
||||
(.assertEqual self.ls.width 8)
|
||||
(.assertFalse self.ls.lines)
|
||||
(.assertTrue self.ls.screen))
|
||||
(any-for line self.ls.screen
|
||||
(not (self.assertEqual None line))))
|
||||
|
||||
test_sortline
|
||||
(lambda (self)
|
||||
(self.assertFalse self.ls.lines)
|
||||
(self.ls.sortline "line 2")
|
||||
(self.assertEqual self.ls.lines (list '(.#"line 2")))
|
||||
(self.ls.sortline "line 1")
|
||||
(self.assertEqual self.ls.lines (list '(.#"line 1" .#"line 2"))))
|
||||
|
||||
test_render
|
||||
(lambda (self)
|
||||
(.assertEqual self "----" (livesort_hssp..render '(.#"-----") 0 4 4))))
|
||||
(self.ls.sortline "line 1")
|
||||
(self.assertEqual (self.ls.render)
|
||||
(list '(.#"line 1"))))
|
||||
|
||||
(when (eq __name__ '__main__) (hissp.reader..transpile __package__ 'test_livesort))
|
||||
test_display
|
||||
(lambda (self)
|
||||
;; I got fed up trying to write this sensibly, will go away after refacor
|
||||
(self.assertEqual "[H[K
|
||||
[K
|
||||
[K
|
||||
[K" (self.ls.display))
|
||||
(self.ls.sortline "line 1")
|
||||
(self.assertEqual "[Hline 1[K
|
||||
|
||||
|
||||
" (self.ls.display)))
|
||||
|
||||
test_livesort ; note (unfortunate) capitalization
|
||||
(lambda (self)
|
||||
(self.input-buf.append "line 1")
|
||||
(self.ls.livesort)
|
||||
_#(self.assertEqual self.output-buf (list '(.#"line 1")))))
|
||||
|
||||
Reference in New Issue
Block a user