blob: a27e1ba5107c4b99ff52b59d384ef01cd1b0b844 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
|
set editorUtilsLib [library create editorUtilsLib {
proc applyTextViewport {originalText x y width height} {
set lines [split $originalText \n]
set lines [lrange $lines $y [expr {($height - 1) + $y}]]
set lines [lmap line $lines {
set line [string range $line $x [expr {($width - 1) + $x}]]
}]
return [join $lines \n]
}
proc cursorToXy {code cursor} {
set codeBeforeCursor [string range $code 0 [- $cursor 1]]
set linesBeforeCursor [split $codeBeforeCursor "\n"]
set lineCountBeforeCursor [llength $linesBeforeCursor]
set cursorX [string length [lindex $linesBeforeCursor end]]
set cursorY [max [- $lineCountBeforeCursor 1] 0]
return [list $cursorX $cursorY]
}
proc xyToCursor {code cursorX cursorY} {
if { $cursorX < 0 } { set cursorX 0 }
if { $cursorY < 0 } { set cursorY 0 }
set lines [split $code "\n"]
set maxCursorY [max 0 [- [llength $lines] 1]]
set cursorY [min $cursorY $maxCursorY]
set relevantLines [lrange $lines 0 [- $cursorY 1]]
set relevantLineLen [string length [lindex $lines $cursorY]]
set joined [join $relevantLines "\n"]
# make sure cursorX < line length
set cursorX [min $cursorX $relevantLineLen]
set cursor [+ [string length $joined] $cursorX]
# don't forget to add the length of \n at the beginning
if {$cursorY > 0} { incr cursor }
return $cursor
}
proc insertText {code cursor newText} {
set before [string range $code 0 [- $cursor 1]]
set after [string range $code $cursor end]
set joined [join [list $before $newText $after] ""]
incr cursor
lassign [cursorToXy $code $cursor] cursorX cursorY
set maxCursorX $cursorX
return [list $joined $cursor $maxCursorX]
}
proc deleteText {code cursor count} {
set before [string range $code 0 [- $cursor 1]]
set after [string range $code [+ $cursor $count] end]
set joined [join [list $before $after] ""]
return $joined
}
proc deleteToBeginning {code cursor} {
lassign [cursorToXy $code $cursor] x y
set lines [split $code "\n"]
set line [lindex $lines $y]
set newLine [string range $line $x end]
lset lines $y $newLine
return [join $lines "\n"]
}
proc getLine {code cursor} {
lassign [cursorToXy $code $cursor] x y
set lines [split $code "\n"]
set line [lindex $lines $y]
}
proc getLineLength {code cursor} {
set line [getLine $code $cursor]
set ll [string length $line]
return $ll
}
# returns {newCursor newMaxCursorX}
proc handleNavigation {key code cursor maxCursorX} {
switch $key {
Left {
set cursor [- $cursor 1]
set cursor [max $cursor 0]
lassign [cursorToXy $code $cursor] cursorX cursorY
set maxCursorX $cursorX
}
Right {
set cursor [+ $cursor 1]
set codeLength [string length $code]
set cursor [min $cursor $codeLength]
lassign [cursorToXy $code $cursor] cursorX cursorY
set maxCursorX $cursorX
}
Up {
lassign [cursorToXy $code $cursor] cursorX cursorY
set cursorX $maxCursorX
set cursorY [- $cursorY 1]
set cursor [xyToCursor $code $cursorX $cursorY]
}
Down {
lassign [cursorToXy $code $cursor] cursorX cursorY
set cursorX $maxCursorX
set cursorY [+ $cursorY 1]
set cursor [xyToCursor $code $cursorX $cursorY]
}
Control_a {
lassign [cursorToXy $code $cursor] cursorX cursorY
set newX 0
set maxCursorX $newX
set cursor [xyToCursor $code $newX $cursorY]
}
Control_e {
lassign [cursorToXy $code $cursor] cursorX cursorY
set newX [getLineLength $code $cursor]
set maxCursorX $newX
set cursor [xyToCursor $code $newX $cursorY]
}
}
return [list $cursor $maxCursorX]
}
# returns {newCode newCursor newMaxCursorX}
proc handleRemovalAndReturn {key code cursor maxCursorX} {
switch $key {
Delete {
if { $cursor != 0 } {
set cursor [- $cursor 1]
set code [deleteText $code $cursor 1]
set maxCursorX [lindex [cursorToXy $code $cursor] 0]
}
}
Remove {
set code [deleteText $code $cursor 1]
}
Control_u {
# delete from cursor back to 0 and move cursor to 0
lassign [cursorToXy $code $cursor] cursorX cursorY
set code [deleteToBeginning $code $cursor]
set newX 0
set cursor [xyToCursor $code $newX $cursorY]
}
Return {
# figure out how many spaces there are before the current line
regexp {^(\s*)} [getLine $code $cursor] -> spacing
set spacingLen [string length $spacing]
lassign [insertText $code $cursor "\n$spacing"] code
set maxCursorX $spacingLen
set cursor [+ $cursor [+ 1 $spacingLen]]
}
}
return [list $code $cursor $maxCursorX]
}
proc getSelectedText {code selAnchor cursor} {
set start [min $selAnchor $cursor]
set end [max $selAnchor $cursor]
return [string range $code $start [- $end 1]]
}
proc replaceRange {code rangeStart rangeEnd newText} {
if {$rangeStart > 0} {
set before [string range $code 0 [- $rangeStart 1]]
} else {
set before ""
}
set after [string range $code $rangeEnd end]
set code "${before}${newText}${after}"
set cursor [+ $rangeStart [string length $newText]]
lassign [cursorToXy $code $cursor] cursorX cursorY
set maxCursorX $cursorX
return [list $code $cursor $maxCursorX]
}
proc lineNumberView {ystart linecount} {
set yend [expr {$ystart + $linecount}]
set numbers [list]
for {set i [expr {$ystart + 1}]} {$i <= $yend} {incr i} {
lappend numbers $i
}
join $numbers "\n"
}
}]
Claim the editor utils library is $editorUtilsLib
|