Browse code
Used cells to handle character display
Ed L authored on 30/10/2015 16:12:12
Showing 1 changed files
Showing 1 changed files
... | ... |
@@ -10,7 +10,6 @@ |
10 | 10 |
(:use :cl :cl-charms :cells :alexandria :anaphora)) |
11 | 11 |
(in-package :lisp-edit) |
12 | 12 |
|
13 |
- |
|
14 | 13 |
(defun apply-cursor-action (action) |
15 | 14 |
(case action |
16 | 15 |
((:up) (cons 0 -1)) |
... | ... |
@@ -18,7 +17,6 @@ |
18 | 17 |
((:left) (cons -1 0)) |
19 | 18 |
((:right) (cons 1 0)))) |
20 | 19 |
|
21 |
- |
|
22 | 20 |
(defun dispatch-char (c) |
23 | 21 |
(case c |
24 | 22 |
((nil) nil) |
... | ... |
@@ -35,11 +33,25 @@ |
35 | 33 |
|
36 | 34 |
(defmodel cursor () |
37 | 35 |
((action :cell :ephemeral :initarg :action :accessor action :initform (c-in nil)) |
36 |
+ (current-char :initarg :current-char :accessor current-char :initform (c-in nil)) |
|
38 | 37 |
(delta :accessor cursor-delta :initform |
39 | 38 |
(c? (apply-cursor-action (^action)))) |
40 | 39 |
(x :accessor cursor-x :initarg :x :initform (c... (0) (car (^cursor-delta)))) |
41 | 40 |
(y :accessor cursor-y :initarg :y :initform (c... (0) (cdr (^cursor-delta)))))) |
42 | 41 |
|
42 |
+(defun map-actions (current-char action) |
|
43 |
+ (case action |
|
44 |
+ ((:paint) (case current-char |
|
45 |
+ ((#\#) #\Space) |
|
46 |
+ ((#\Space) #\*) |
|
47 |
+ ((#\*) #\#))))) |
|
48 |
+ |
|
49 |
+(defmodel painter () |
|
50 |
+ ((action :cell :ephemeral :initarg :action :accessor action :initform (c-in nil)) |
|
51 |
+ (current-char :initarg :current-char :accessor current-char :initform (c-in nil)) |
|
52 |
+ (output :cell :ephemeral :accessor output :initform (c? (map-actions (^current-char) |
|
53 |
+ (^action)))))) |
|
54 |
+ |
|
43 | 55 |
(defvar *input-handler*) |
44 | 56 |
(defvar *painter*) |
45 | 57 |
(defvar *cursor*) |
... | ... |
@@ -72,38 +84,54 @@ |
72 | 84 |
(enable-raw-input :interpret-control-characters t) |
73 | 85 |
(enable-non-blocking-mode *standard-window*) |
74 | 86 |
|
75 |
- (let* ((*input-handler* (make-instance 'input-handler)) |
|
76 |
- (*cursor* (make-instance 'cursor :action (c? (action *input-handler*)))) |
|
77 |
- (screen-dimensions (multiple-value-list (window-dimensions *standard-window*)))) |
|
78 |
- |
|
79 |
- (defobserver action ((self input-handler)) |
|
80 |
- (case new-value |
|
81 |
- ((:paint) (paint)))) |
|
82 |
- |
|
83 |
- |
|
84 |
- (defobserver y ((self cursor)) |
|
85 |
- (with-integrity (:change) |
|
86 |
- (let ((adjusted-n-v (mod new-value |
|
87 |
- (cadr screen-dimensions)))) |
|
88 |
- (if (/= new-value adjusted-n-v) |
|
89 |
- (setf (^cursor-y) (- adjusted-n-v new-value)) |
|
90 |
- (move-cursor *standard-window* |
|
91 |
- (^cursor-x) adjusted-n-v))))) |
|
92 |
- |
|
93 |
- (defobserver x ((self cursor)) |
|
94 |
- (with-integrity (:change) |
|
95 |
- (let ((adjusted-n-v (mod new-value |
|
96 |
- (car screen-dimensions)))) |
|
97 |
- (if (/= new-value adjusted-n-v) |
|
98 |
- (setf (^cursor-x) (- adjusted-n-v new-value)) |
|
99 |
- (move-cursor *standard-window* |
|
100 |
- adjusted-n-v (^cursor-y)))))) |
|
101 |
- |
|
102 |
- (loop :named driver-loop |
|
103 |
- :for c := (get-char *standard-window* :ignore-error t) |
|
104 |
- :do (progn |
|
105 |
- (refresh-window *standard-window*) |
|
106 |
- |
|
107 |
- (setf (input-key *input-handler*) c))))) |
|
87 |
+ (setf *input-handler* (make-instance 'input-handler) |
|
88 |
+ *cursor* (make-instance 'cursor :action (c? (action *input-handler*))) |
|
89 |
+ *painter* (make-instance 'painter |
|
90 |
+ :action (c? (action *input-handler*)) |
|
91 |
+ :current-char (c? (current-char *cursor*)))) |
|
92 |
+ |
|
93 |
+ (let* ((screen-dimensions (multiple-value-bind (x y) (window-dimensions *standard-window*) |
|
94 |
+ (cons x y)))) |
|
95 |
+ (labels |
|
96 |
+ ((set-current-char (cursor) |
|
97 |
+ (with-restored-cursor *standard-window* |
|
98 |
+ (setf (current-char cursor) (char-at-cursor *standard-window*)))) |
|
99 |
+ (mvc (x y) |
|
100 |
+ (move-cursor *standard-window* x y) |
|
101 |
+ (set-current-char *cursor*)) |
|
102 |
+ (constrain-coordinate (side coord) |
|
103 |
+ (mod coord (funcall |
|
104 |
+ (ecase side |
|
105 |
+ ((:x) #'car) |
|
106 |
+ ((:y) #'cdr)) |
|
107 |
+ screen-dimensions)))) |
|
108 |
+ |
|
109 |
+ (defobserver output ((self painter)) |
|
110 |
+ (with-restored-cursor *standard-window* |
|
111 |
+ (write-char-at-cursor *standard-window* new-value)) |
|
112 |
+ (with-integrity (:change) |
|
113 |
+ (set-current-char *cursor*))) |
|
114 |
+ |
|
115 |
+ (defobserver y ((self cursor)) |
|
116 |
+ (with-integrity (:change) |
|
117 |
+ (let ((adjusted-n-v (constrain-coordinate :y new-value))) |
|
118 |
+ (if (/= new-value adjusted-n-v) |
|
119 |
+ (setf (^cursor-y) (- adjusted-n-v new-value)) |
|
120 |
+ (mvc (^cursor-x) adjusted-n-v))))) |
|
121 |
+ |
|
122 |
+ (defobserver x ((self cursor)) |
|
123 |
+ (with-integrity (:change) |
|
124 |
+ (let ((adjusted-n-v (constrain-coordinate :x new-value))) |
|
125 |
+ (if (/= new-value adjusted-n-v) |
|
126 |
+ (setf (^cursor-x) (- adjusted-n-v new-value)) |
|
127 |
+ (mvc adjusted-n-v (^cursor-y)))))) |
|
128 |
+ |
|
129 |
+ (mvc 0 0) |
|
130 |
+ (loop :named driver-loop |
|
131 |
+ :for c := (get-char *standard-window* :ignore-error t) |
|
132 |
+ :do (progn |
|
133 |
+ (refresh-window *standard-window*) |
|
134 |
+ (setf (input-key *input-handler*) c)))))) |
|
135 |
+ |
|
108 | 136 |
(sb-sys:interactive-interrupt (c) (declare (ignore c))))) |
109 | 137 |
|