t-rex 1.0.5 → 2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/t-rex +760 -0
- metadata +15 -14
- data/bin/t-rex.rb +0 -880
data/bin/t-rex.rb
DELETED
@@ -1,880 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# encoding: utf-8
|
3
|
-
|
4
|
-
require 'io/console'
|
5
|
-
require 'curses'
|
6
|
-
include Curses
|
7
|
-
|
8
|
-
# CLASSES
|
9
|
-
class Curses::Window # CLASS EXTENSION
|
10
|
-
# General extensions (see https://github.com/isene/Ruby-Curses-Class-Extension)
|
11
|
-
attr_accessor :color, :fg, :bg, :attr
|
12
|
-
# Set self.color for an already defined color pair such as: init_pair(1, 255, 3)
|
13
|
-
# The color pair is defined like this: init_pair(index, foreground, background)
|
14
|
-
# self.fg is set for the foreground color (and is used if self.color is not set)
|
15
|
-
# self.bg is set for the background color (and is used if self.color is not set)
|
16
|
-
# self.attr is set for text attributes like Curses::A_BOLD
|
17
|
-
def clr # Clears the whole window
|
18
|
-
self.setpos(0, 0)
|
19
|
-
self.maxy.times {self.deleteln()}
|
20
|
-
self.refresh
|
21
|
-
self.setpos(0, 0)
|
22
|
-
end
|
23
|
-
def fill # Fill window with color as set by self.color (or self.bg if not set)
|
24
|
-
self.setpos(0, 0)
|
25
|
-
self.fill_from_cur_pos
|
26
|
-
end
|
27
|
-
def fill_from_cur_pos # Fills the rest of the window from current line
|
28
|
-
x = curx
|
29
|
-
y = cury
|
30
|
-
self.setpos(y, 0)
|
31
|
-
blank = " " * self.maxx
|
32
|
-
if self.color == nil
|
33
|
-
self.bg = 0 if self.bg == nil
|
34
|
-
self.fg = 255 if self.fg == nil
|
35
|
-
init_pair(self.fg, self.fg, self.bg)
|
36
|
-
self.maxy.times {self.attron(color_pair(self.fg)) {self << blank}}
|
37
|
-
else
|
38
|
-
self.maxy.times {self.attron(color_pair(self.color)) {self << blank}}
|
39
|
-
end
|
40
|
-
self.refresh
|
41
|
-
self.setpos(y, x)
|
42
|
-
end
|
43
|
-
def fill_to_cur_pos # Fills the window up to current line
|
44
|
-
x = curx
|
45
|
-
y = cury
|
46
|
-
self.setpos(0, 0)
|
47
|
-
blank = " " * self.maxx
|
48
|
-
if self.color == nil
|
49
|
-
self.bg = 0 if self.bg == nil
|
50
|
-
self.fg = 255 if self.fg == nil
|
51
|
-
init_pair(self.fg, self.fg, self.bg)
|
52
|
-
y.times {self.attron(color_pair(self.fg)) {self << blank}}
|
53
|
-
else
|
54
|
-
y.times {self.attron(color_pair(self.color)) {self << blank}}
|
55
|
-
end
|
56
|
-
self.refresh
|
57
|
-
self.setpos(y, x)
|
58
|
-
end
|
59
|
-
def p(text) # Puts text to window
|
60
|
-
self.attr = 0 if self.attr == nil
|
61
|
-
if self.color == nil
|
62
|
-
self.bg = 0 if self.bg == nil
|
63
|
-
self.fg = 255 if self.fg == nil
|
64
|
-
init_pair(self.fg, self.fg, self.bg)
|
65
|
-
self.attron(color_pair(self.fg) | self.attr) { self << text }
|
66
|
-
else
|
67
|
-
self.attron(color_pair(self.color) | self.attr) { self << text }
|
68
|
-
end
|
69
|
-
self.refresh
|
70
|
-
end
|
71
|
-
end
|
72
|
-
class Stack
|
73
|
-
attr_accessor :x, :y, :z, :t, :l, :deg
|
74
|
-
|
75
|
-
def initialize(x, y, z, t, l)
|
76
|
-
self.x = x.to_f
|
77
|
-
self.y = y.to_f
|
78
|
-
self.z = z.to_f
|
79
|
-
self.t = t.to_f
|
80
|
-
self.l = l.to_f
|
81
|
-
end
|
82
|
-
def lift
|
83
|
-
self.y, self.z, self.t = self.x, self.y, self.z
|
84
|
-
end
|
85
|
-
def drop
|
86
|
-
self.y, self.z = self.z, self.t
|
87
|
-
end
|
88
|
-
def rdn
|
89
|
-
self.x, self.y, self.z, self.t = self.y, self.z, self.t, self.x
|
90
|
-
end
|
91
|
-
def rup
|
92
|
-
self.x, self.y, self.z, self.t = self.t, self.x, self.y, self.z
|
93
|
-
end
|
94
|
-
def xy
|
95
|
-
self.x, self.y = self.y, self.x
|
96
|
-
end
|
97
|
-
def add
|
98
|
-
self.l = self.x
|
99
|
-
self.x = self.y + self.x
|
100
|
-
self.drop
|
101
|
-
end
|
102
|
-
def subtract
|
103
|
-
self.l = self.x
|
104
|
-
self.x = self.y - self.x
|
105
|
-
self.drop
|
106
|
-
end
|
107
|
-
def multiply
|
108
|
-
self.l = self.x
|
109
|
-
self.x = self.y * self.x
|
110
|
-
self.drop
|
111
|
-
end
|
112
|
-
def divide
|
113
|
-
begin
|
114
|
-
throw if self.x == 0
|
115
|
-
self.l = self.x
|
116
|
-
self.x = self.y / self.x
|
117
|
-
self.drop
|
118
|
-
rescue
|
119
|
-
return "Error"
|
120
|
-
end
|
121
|
-
end
|
122
|
-
def mod
|
123
|
-
begin
|
124
|
-
throw if self.x == 0
|
125
|
-
self.l = self.x
|
126
|
-
self.x = self.y % self.x
|
127
|
-
self.drop
|
128
|
-
rescue
|
129
|
-
return "Error"
|
130
|
-
end
|
131
|
-
end
|
132
|
-
def percent
|
133
|
-
begin
|
134
|
-
throw if self.y == 0
|
135
|
-
self.l = self.x
|
136
|
-
self.x = 100*(self.x / self.y)
|
137
|
-
self.drop
|
138
|
-
rescue
|
139
|
-
return "Error"
|
140
|
-
end
|
141
|
-
end
|
142
|
-
def chs
|
143
|
-
self.x = -self.x
|
144
|
-
end
|
145
|
-
def pi
|
146
|
-
self.l = self.x
|
147
|
-
self.lift
|
148
|
-
self.x = Math::PI
|
149
|
-
end
|
150
|
-
def pow
|
151
|
-
self.l = self.x
|
152
|
-
self.x = self.y ** self.x
|
153
|
-
self.drop
|
154
|
-
end
|
155
|
-
def root
|
156
|
-
begin
|
157
|
-
self.l = self.x
|
158
|
-
self.x = self.y ** (1 / self.x)
|
159
|
-
self.drop
|
160
|
-
rescue
|
161
|
-
return "Error"
|
162
|
-
end
|
163
|
-
end
|
164
|
-
def recip
|
165
|
-
begin
|
166
|
-
throw if self.x == 0
|
167
|
-
self.l = self.x
|
168
|
-
self.x = 1 / self.x
|
169
|
-
rescue
|
170
|
-
return "Error"
|
171
|
-
end
|
172
|
-
end
|
173
|
-
def sqr
|
174
|
-
self.l = self.x
|
175
|
-
self.x = self.x ** 2
|
176
|
-
end
|
177
|
-
def sqrt
|
178
|
-
self.l = self.x
|
179
|
-
begin
|
180
|
-
self.x = Math::sqrt(self.x)
|
181
|
-
rescue
|
182
|
-
return "Error"
|
183
|
-
end
|
184
|
-
end
|
185
|
-
def cube
|
186
|
-
self.l = self.x
|
187
|
-
self.x = self.x ** 3
|
188
|
-
end
|
189
|
-
def ln
|
190
|
-
self.l = self.x
|
191
|
-
begin
|
192
|
-
self.x = Math::log(self.x)
|
193
|
-
rescue
|
194
|
-
return "Error"
|
195
|
-
end
|
196
|
-
end
|
197
|
-
def ex
|
198
|
-
self.l = self.x
|
199
|
-
self.x = Math::exp(self.x)
|
200
|
-
end
|
201
|
-
def log
|
202
|
-
self.l = self.x
|
203
|
-
begin
|
204
|
-
self.x = Math::log10(self.x)
|
205
|
-
rescue
|
206
|
-
return "Error"
|
207
|
-
end
|
208
|
-
end
|
209
|
-
def tenx
|
210
|
-
self.l = self.x
|
211
|
-
self.x = 10 ** self.x
|
212
|
-
end
|
213
|
-
def sin
|
214
|
-
self.l = self.x
|
215
|
-
self.x = self.x * Math::PI / 180 if self.deg
|
216
|
-
self.x = Math::sin(self.x)
|
217
|
-
end
|
218
|
-
def cos
|
219
|
-
self.l = self.x
|
220
|
-
self.x = self.x * Math::PI / 180 if self.deg
|
221
|
-
self.x = Math::cos(self.x)
|
222
|
-
end
|
223
|
-
def tan
|
224
|
-
self.l = self.x
|
225
|
-
self.x = self.x * Math::PI / 180 if self.deg
|
226
|
-
self.x = Math::tan(self.x)
|
227
|
-
end
|
228
|
-
def asin
|
229
|
-
self.l = self.x
|
230
|
-
self.x = Math::asin(self.x)
|
231
|
-
self.x = self.x * 180 / Math::PI if self.deg
|
232
|
-
end
|
233
|
-
def acos
|
234
|
-
self.l = self.x
|
235
|
-
self.x = Math::acos(self.x)
|
236
|
-
self.x = self.x * 180 / Math::PI if self.deg
|
237
|
-
end
|
238
|
-
def atan
|
239
|
-
self.l = self.x
|
240
|
-
self.x = Math::atan(self.x)
|
241
|
-
self.x = self.x * 180 / Math::PI if self.deg
|
242
|
-
end
|
243
|
-
def rp
|
244
|
-
begin
|
245
|
-
throw if self.x == 0
|
246
|
-
self.l = self.x
|
247
|
-
x = self.x
|
248
|
-
y = self.y
|
249
|
-
self.x = Math::sqrt(x*x + y*y)
|
250
|
-
self.y = Math::atan(y/x)
|
251
|
-
if x < 0 # Q2 & Q3
|
252
|
-
self.y += Math::PI
|
253
|
-
elsif x >= 0 and y < 0 # Q4
|
254
|
-
self.y += 2 * Math::PI
|
255
|
-
end
|
256
|
-
self.y = self.y * 180 / Math::PI if self.deg
|
257
|
-
rescue
|
258
|
-
return "Error"
|
259
|
-
end
|
260
|
-
end
|
261
|
-
def pr
|
262
|
-
self.l = self.x
|
263
|
-
r = self.x
|
264
|
-
t = self.y
|
265
|
-
t = t * Math::PI / 180 if self.deg
|
266
|
-
self.x = r * Math::cos(t)
|
267
|
-
self.y = r * Math::sin(t)
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
begin # BASIC SETUP
|
272
|
-
@stk = Stack.new(0, 0, 0, 0, 0)
|
273
|
-
@reg = %w[0 0 0 0 0 0 0 0 0 0]
|
274
|
-
@fix = 4
|
275
|
-
@sci = 6
|
276
|
-
@dot = true
|
277
|
-
@mod = "Deg"
|
278
|
-
@hlp = true
|
279
|
-
|
280
|
-
load(Dir.home+'/.t-rex.conf') if File.exist?(Dir.home+'/.t-rex.conf')
|
281
|
-
@mod == "Deg" ? @stk.deg = true : @stk.deg = false
|
282
|
-
|
283
|
-
@history = [""]
|
284
|
-
|
285
|
-
Curses.init_screen
|
286
|
-
Curses.start_color
|
287
|
-
Curses.curs_set(0)
|
288
|
-
Curses.noecho
|
289
|
-
Curses.cbreak
|
290
|
-
Curses.stdscr.keypad = true
|
291
|
-
end
|
292
|
-
|
293
|
-
# FUNCTIONS
|
294
|
-
def getchr # PROCESS KEY PRESSES
|
295
|
-
c = STDIN.getch(min: 0, time: 1)
|
296
|
-
case c
|
297
|
-
when "\e" # ANSI escape sequences
|
298
|
-
case $stdin.getc
|
299
|
-
when '[' # CSI
|
300
|
-
case $stdin.getc
|
301
|
-
when 'A' then chr = "UP"
|
302
|
-
when 'B' then chr = "DOWN"
|
303
|
-
when 'C' then chr = "RIGHT"
|
304
|
-
when 'D' then chr = "LEFT"
|
305
|
-
when 'Z' then chr = "S-TAB"
|
306
|
-
when '2' then chr = "INS" ; STDIN.getc
|
307
|
-
when '3' then chr = "DEL" ; STDIN.getc
|
308
|
-
when '5' then chr = "PgUP" ; STDIN.getc
|
309
|
-
when '6' then chr = "PgDOWN" ; STDIN.getc
|
310
|
-
when '7' then chr = "HOME" ; STDIN.getc
|
311
|
-
when '8' then chr = "END" ; STDIN.getc
|
312
|
-
end
|
313
|
-
end
|
314
|
-
when "", "" then chr = "BACK"
|
315
|
-
when "" then chr = "WBACK"
|
316
|
-
when "" then chr = "LDEL"
|
317
|
-
when "" then chr = "C-X"
|
318
|
-
when "" then chr = "C-Q"
|
319
|
-
when "" then chr = "C-N"
|
320
|
-
when "" then chr = "C-G"
|
321
|
-
when "" then chr = "C-L"
|
322
|
-
when " " then chr = "C-I"
|
323
|
-
when "" then chr = "C-O"
|
324
|
-
when "" then chr = "C-A"
|
325
|
-
when "" then chr = "C-R"
|
326
|
-
when "" then chr = "C-D"
|
327
|
-
when "" then chr = "C-C"
|
328
|
-
when "" then chr = "C-T"
|
329
|
-
when "" then chr = "C-^"
|
330
|
-
when "\r" then chr = "ENTER"
|
331
|
-
when "\t" then chr = "TAB"
|
332
|
-
when /./ then chr = c
|
333
|
-
end
|
334
|
-
return chr
|
335
|
-
end
|
336
|
-
def main_getkey(c) # GET KEY FROM USER
|
337
|
-
c == "" ? chr = getchr : chr = c
|
338
|
-
case chr
|
339
|
-
when 'ENTER'
|
340
|
-
@stk.l = @stk.x
|
341
|
-
@stk.y, @stk.z, @stk.t = @stk.x, @stk.y, @stk.z
|
342
|
-
when "'"
|
343
|
-
@dot = !@dot
|
344
|
-
when 'UP' # Roll stack up
|
345
|
-
@stk.rup
|
346
|
-
when 'DOWN' # Roll stack down
|
347
|
-
@stk.rdn
|
348
|
-
when '<', 'LEFT', 'RIGHT' # x<>y
|
349
|
-
@stk.xy
|
350
|
-
when '+'
|
351
|
-
@stk.add
|
352
|
-
when '-'
|
353
|
-
@stk.subtract
|
354
|
-
when '*'
|
355
|
-
@stk.multiply
|
356
|
-
when '/'
|
357
|
-
e = @stk.divide
|
358
|
-
error ("Error: Divide by zero") if e == "Error"
|
359
|
-
when '\\' # \ (modulo)
|
360
|
-
@stk.mod
|
361
|
-
when '%' # 100*x/y
|
362
|
-
e = @stk.percent
|
363
|
-
error ("Error: Divide by zero") if e == "Error"
|
364
|
-
when 'h' # Change sign
|
365
|
-
@stk.chs
|
366
|
-
when 'p' # pi
|
367
|
-
@stk.l = @stk.x
|
368
|
-
@stk.pi
|
369
|
-
when '^' # y^x
|
370
|
-
@stk.pow
|
371
|
-
when 'C-^' # y^(1/x)
|
372
|
-
e = @stk.root
|
373
|
-
error ("Error: Divide by zero") if e == "Error"
|
374
|
-
when 'x' # 1/x
|
375
|
-
e = @stk.recip
|
376
|
-
error ("Error: Divide by zero") if e == "Error"
|
377
|
-
when 'C-X' # x^2
|
378
|
-
@stk.sqr
|
379
|
-
when 'q' # Square root
|
380
|
-
e = @stk.sqrt
|
381
|
-
error ("Error: Imaginary number") if e == "Error"
|
382
|
-
when 'C-Q' # x^3
|
383
|
-
@stk.cube
|
384
|
-
when 'n' # ln(x)
|
385
|
-
e = @stk.ln
|
386
|
-
error ("Error: Negative x") if e == "Error"
|
387
|
-
when 'C-N' # e^x
|
388
|
-
@stk.ex
|
389
|
-
when 'g' # log(x)
|
390
|
-
e = @stk.log
|
391
|
-
error ("Error: Negative x") if e == "Error"
|
392
|
-
when 'C-G' # 10^x
|
393
|
-
@stk.tenx
|
394
|
-
when 'l' # Recall Lastx (l) to x
|
395
|
-
@stk.lift
|
396
|
-
@stk.x = @stk.l
|
397
|
-
when 'C-L' # Break/redraw
|
398
|
-
@break = true
|
399
|
-
when 'i'
|
400
|
-
@stk.sin
|
401
|
-
when 'C-I'
|
402
|
-
@stk.asin
|
403
|
-
when 'o'
|
404
|
-
@stk.cos
|
405
|
-
when 'C-O'
|
406
|
-
@stk.acos
|
407
|
-
when 'a'
|
408
|
-
@stk.tan
|
409
|
-
when 'C-A'
|
410
|
-
@stk.atan
|
411
|
-
when 'r' # Rad mode
|
412
|
-
@mod = "Rad"
|
413
|
-
@stk.deg = false
|
414
|
-
when 'C-R' # R->P
|
415
|
-
e = @stk.rp
|
416
|
-
error ("Error: Divide by zero") if e == "Error"
|
417
|
-
when 'd' # Deg mode
|
418
|
-
@mod = "Deg"
|
419
|
-
@stk.deg = true
|
420
|
-
when 'C-D' # P->R
|
421
|
-
@stk.pr
|
422
|
-
when 'c', 'BACK'
|
423
|
-
@stk.x = 0
|
424
|
-
when 'C-C' # Clear stack
|
425
|
-
@stk.x = 0
|
426
|
-
@stk.y = 0
|
427
|
-
@stk.z = 0
|
428
|
-
@stk.t = 0
|
429
|
-
@stk.l = 0
|
430
|
-
when 'M'
|
431
|
-
@reg = %w[0 0 0 0 0 0 0 0 0 0]
|
432
|
-
when 'S' # Store to Reg
|
433
|
-
@w_x.clr
|
434
|
-
@w_x.p(" Store x in Reg #(0-9)")
|
435
|
-
r = getchr
|
436
|
-
if r =~ /[0-9]/
|
437
|
-
@reg[r.to_i] = @stk.x
|
438
|
-
end
|
439
|
-
when 'R' # Recall from Reg
|
440
|
-
@w_x.clr
|
441
|
-
@w_x.p(" Recall from Reg #(0-9)")
|
442
|
-
r = getchr
|
443
|
-
if r =~ /[0-9]/
|
444
|
-
@stk.lift
|
445
|
-
@stk.x = @reg[r.to_i].to_f
|
446
|
-
end
|
447
|
-
when 's' # Set Sci size/limit
|
448
|
-
@w_x.clr
|
449
|
-
@w_x.p(" Sci notation limit (2-9)")
|
450
|
-
r = getchr
|
451
|
-
if r =~ /[2-9]/
|
452
|
-
@sci = r.to_i
|
453
|
-
end
|
454
|
-
when 'f' # Set Fix size
|
455
|
-
@w_x.clr
|
456
|
-
@w_x.p(" Fixed decimals (0-9)")
|
457
|
-
r = getchr
|
458
|
-
if r =~ /[0-9]/
|
459
|
-
@fix = r.to_i
|
460
|
-
end
|
461
|
-
when 'u' # Undo
|
462
|
-
unless @u.empty?
|
463
|
-
@stk = @u.last.dup
|
464
|
-
@u.pop
|
465
|
-
@undo = true
|
466
|
-
end
|
467
|
-
when 'y'
|
468
|
-
begin
|
469
|
-
@w_x.color = 7
|
470
|
-
@w_x.fill
|
471
|
-
system("echo '#{@stk.x}' | xclip")
|
472
|
-
sleep(0.1)
|
473
|
-
@w_x.color = 6
|
474
|
-
rescue
|
475
|
-
@w_x.clr
|
476
|
-
@w_x.p(" Install xclip to yank")
|
477
|
-
getchr
|
478
|
-
end
|
479
|
-
when 'Y'
|
480
|
-
begin
|
481
|
-
@w_x.color = 5
|
482
|
-
@w_x.fill
|
483
|
-
mem = ""
|
484
|
-
10.times do |i|
|
485
|
-
reg = @reg[i]
|
486
|
-
mem += "#{reg}\n"
|
487
|
-
end
|
488
|
-
system("echo '#{mem}' | xclip")
|
489
|
-
sleep(0.1)
|
490
|
-
@w_x.color = 6
|
491
|
-
rescue
|
492
|
-
@w_x.clr
|
493
|
-
@w_x.p(" Install xclip to yank")
|
494
|
-
getchr
|
495
|
-
end
|
496
|
-
when 'H'
|
497
|
-
@hlp = !@hlp
|
498
|
-
@w_hlp.fill
|
499
|
-
help if @hlp
|
500
|
-
when '@' # Ruby console
|
501
|
-
@w_hlp.fill
|
502
|
-
console(" Ruby: ")
|
503
|
-
@w_hlp.fill
|
504
|
-
help if @hlp
|
505
|
-
when 'Q' # Exit
|
506
|
-
exit 0
|
507
|
-
when /[0-9.,-]/ # Go to entry mode for x
|
508
|
-
number, c = entry(chr)
|
509
|
-
if number != ""
|
510
|
-
@stk.l = @stk.x
|
511
|
-
@stk.lift unless @stk.x == 0
|
512
|
-
@stk.x = number
|
513
|
-
end
|
514
|
-
main_getkey(c) if %w[< + - * / \ % ^ x C-X q C-Q n C-N g C-G i C-I o C-O a C-A c C-C].include?(c)
|
515
|
-
end
|
516
|
-
end
|
517
|
-
def console(pretext) # A SIMPLE READLINE-LIKE ROUTINE
|
518
|
-
Curses.curs_set(1)
|
519
|
-
Curses.echo
|
520
|
-
@w_hlp.color = 9
|
521
|
-
stk = 0
|
522
|
-
pos = @history[stk].length
|
523
|
-
@w_hlp.setpos(0,0)
|
524
|
-
chr = ""
|
525
|
-
while chr != "C-C"
|
526
|
-
@w_hlp.setpos(@w_hlp.cury,0)
|
527
|
-
text = pretext + @history[stk]
|
528
|
-
text += " " * (@w_hlp.maxx - text.length) if text.length < @w_hlp.maxx
|
529
|
-
@w_hlp.p(text)
|
530
|
-
@w_hlp.setpos(0,pretext.length + pos)
|
531
|
-
@w_hlp.refresh
|
532
|
-
chr = getchr
|
533
|
-
case chr
|
534
|
-
when 'UP'
|
535
|
-
unless stk == @history.length - 1
|
536
|
-
stk += 1
|
537
|
-
pos = @history[stk].length
|
538
|
-
end
|
539
|
-
when 'DOWN'
|
540
|
-
unless stk == 0
|
541
|
-
stk -= 1
|
542
|
-
pos = @history[stk].length
|
543
|
-
end
|
544
|
-
when 'RIGHT'
|
545
|
-
pos += 1 unless pos > @history[stk].length
|
546
|
-
when 'LEFT'
|
547
|
-
pos -= 1 unless pos == 0
|
548
|
-
when 'HOME'
|
549
|
-
pos = 0
|
550
|
-
when 'END'
|
551
|
-
pos = @history[stk].length
|
552
|
-
when 'DEL'
|
553
|
-
@history[stk][pos] = ""
|
554
|
-
when 'BACK'
|
555
|
-
unless pos == 0
|
556
|
-
pos -= 1
|
557
|
-
@history[stk][pos] = ""
|
558
|
-
end
|
559
|
-
when 'WBACK'
|
560
|
-
unless pos == 0
|
561
|
-
until @history[stk][pos - 1] == " " or pos == 0
|
562
|
-
pos -= 1
|
563
|
-
@history[stk][pos] = ""
|
564
|
-
end
|
565
|
-
if @history[stk][pos - 1] == " "
|
566
|
-
pos -= 1
|
567
|
-
@history[stk][pos] = ""
|
568
|
-
end
|
569
|
-
end
|
570
|
-
when 'LDEL'
|
571
|
-
@history[stk] = ""
|
572
|
-
pos = 0
|
573
|
-
when /^.$/
|
574
|
-
@history[stk].insert(pos,chr)
|
575
|
-
pos += 1
|
576
|
-
when 'ENTER'
|
577
|
-
@w_hlp.fill
|
578
|
-
@w_hlp.p(text)
|
579
|
-
@w_hlp.setpos(0,pretext.length + pos)
|
580
|
-
@w_hlp.refresh
|
581
|
-
@w_hlp.p("\n ")
|
582
|
-
curstr = @history[stk]
|
583
|
-
@history.uniq!
|
584
|
-
@history.compact!
|
585
|
-
@history.delete("")
|
586
|
-
begin
|
587
|
-
x = @stk.x
|
588
|
-
y = @stk.y
|
589
|
-
z = @stk.z
|
590
|
-
t = @stk.t
|
591
|
-
l = @stk.l
|
592
|
-
eval(curstr)
|
593
|
-
@stk.x = x
|
594
|
-
@stk.y = y
|
595
|
-
@stk.z = z
|
596
|
-
@stk.t = t
|
597
|
-
@stk.l = l
|
598
|
-
@w_hlp.p("\n\n")
|
599
|
-
pstack
|
600
|
-
rescue StandardError => e
|
601
|
-
@w_hlp.p("\n Error: #{e.inspect}\n")
|
602
|
-
end
|
603
|
-
@history.unshift("")
|
604
|
-
stk = 0
|
605
|
-
pos = @history[stk].length
|
606
|
-
chr = ""
|
607
|
-
@w_hlp.setpos(0,0)
|
608
|
-
end
|
609
|
-
end
|
610
|
-
@w_hlp.color = 11
|
611
|
-
Curses.curs_set(0)
|
612
|
-
Curses.noecho
|
613
|
-
end
|
614
|
-
def entry(chr)
|
615
|
-
Curses.curs_set(1)
|
616
|
-
Curses.echo
|
617
|
-
num = chr
|
618
|
-
pos = 1
|
619
|
-
@w_x.color = 7
|
620
|
-
while %w[0 1 2 3 4 5 6 7 8 9 . , h RIGHT LEFT HOME END DEL BACK WBACK LDEL].include?(chr)
|
621
|
-
@w_x.clr
|
622
|
-
@w_x.setpos(0,0)
|
623
|
-
@w_x.p(num)
|
624
|
-
@w_x.setpos(0,pos)
|
625
|
-
@w_x.refresh
|
626
|
-
chr = getchr
|
627
|
-
case chr
|
628
|
-
when 'RIGHT'
|
629
|
-
pos += 1 unless pos >= num.length
|
630
|
-
when 'LEFT'
|
631
|
-
pos -= 1 unless pos == 0
|
632
|
-
when 'HOME'
|
633
|
-
pos = 0
|
634
|
-
when 'END'
|
635
|
-
pos = num.length
|
636
|
-
when 'DEL'
|
637
|
-
num[pos] = ""
|
638
|
-
when 'BACK'
|
639
|
-
unless pos == 0
|
640
|
-
pos -= 1
|
641
|
-
num[pos] = ""
|
642
|
-
end
|
643
|
-
when 'WBACK'
|
644
|
-
unless pos == 0
|
645
|
-
until num[pos - 1] == " " or pos == 0
|
646
|
-
pos -= 1
|
647
|
-
num[pos] = ""
|
648
|
-
end
|
649
|
-
if num[pos - 1] == " "
|
650
|
-
pos -= 1
|
651
|
-
num[pos] = ""
|
652
|
-
end
|
653
|
-
end
|
654
|
-
when 'LDEL'
|
655
|
-
num = ""
|
656
|
-
pos = 0
|
657
|
-
when 'h'
|
658
|
-
if num[0] == "-"
|
659
|
-
num[0] = ""
|
660
|
-
pos -= 1
|
661
|
-
else
|
662
|
-
num.insert(0, "-")
|
663
|
-
pos += 1
|
664
|
-
end
|
665
|
-
when /[0-9.,]/
|
666
|
-
num.insert(pos,chr)
|
667
|
-
pos += 1
|
668
|
-
end
|
669
|
-
end
|
670
|
-
num = "" if %w[DOWN UP].include?(chr)
|
671
|
-
num.gsub!(/,/, '.')
|
672
|
-
num != "" ? number = num.to_f : number = ""
|
673
|
-
Curses.curs_set(0)
|
674
|
-
Curses.noecho
|
675
|
-
@w_x.color = 6
|
676
|
-
return number, chr
|
677
|
-
end
|
678
|
-
def num_format(n)
|
679
|
-
if n.abs >= 10 ** @sci.to_i
|
680
|
-
n = "%.#{@sci}g" % n
|
681
|
-
elsif n.abs <= 10 ** (1 / @sci.to_i) and n > 10
|
682
|
-
n = "%.#{@sci}g" % n
|
683
|
-
else
|
684
|
-
n = n.round(@fix)
|
685
|
-
n = "%.#{@fix}f" % n
|
686
|
-
m = n[/^-/]
|
687
|
-
m = "" if m == nil
|
688
|
-
n.sub!(/-/, '')
|
689
|
-
i = n[/\d*/]
|
690
|
-
i.gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1,")
|
691
|
-
f = n.sub(/\d*\.(\d*)/, '\1')
|
692
|
-
n = m + i + "." + f
|
693
|
-
if not @dot
|
694
|
-
n.gsub!(/,/, ' ')
|
695
|
-
n.sub!(/\./, ',')
|
696
|
-
end
|
697
|
-
end
|
698
|
-
return n
|
699
|
-
end
|
700
|
-
def pstack
|
701
|
-
x = num_format(@stk.x)
|
702
|
-
y = num_format(@stk.y)
|
703
|
-
z = num_format(@stk.z)
|
704
|
-
t = num_format(@stk.t)
|
705
|
-
l = num_format(@stk.l)
|
706
|
-
@w_l.setpos(0,0)
|
707
|
-
@w_l.p(l.rjust(30))
|
708
|
-
@w_yzt.setpos(0,0)
|
709
|
-
@w_yzt.p(t.rjust(30) + z.rjust(30) + y.rjust(30))
|
710
|
-
@w_x.setpos(0,0)
|
711
|
-
@w_x.p(x.rjust(30))
|
712
|
-
end
|
713
|
-
def pregs
|
714
|
-
@w_reg.setpos(1,0)
|
715
|
-
10.times do |i|
|
716
|
-
r = num_format(@reg[i].to_f)
|
717
|
-
@w_reg.p(" R##{i}" + "#{r}".rjust(27) + " ")
|
718
|
-
end
|
719
|
-
end
|
720
|
-
def error(err)
|
721
|
-
@w_x.clr
|
722
|
-
@w_x.p(err.rjust(30))
|
723
|
-
getchr
|
724
|
-
end
|
725
|
-
def cmd
|
726
|
-
text = <<CMDTEXT
|
727
|
-
|
728
|
-
r|↓| r|↑| x|<|>y |+| |-| |*| |/| |\\| |%| c|h|s |p|i
|
729
|
-
y√x x^2 x^3 e^x 10^x redrw
|
730
|
-
y|^|x 1/|x| s|q|rt l|n| lo|g| |l|astx
|
731
|
-
asin acos atan R→P P→R cstk
|
732
|
-
s|i|n c|o|s t|a|n |r|ad |d|eg |c|lx
|
733
|
-
|
734
|
-
|S|to |R|cl |s|ci |f|ix |u|ndo |H|lp |Q|uit
|
735
|
-
CMDTEXT
|
736
|
-
text = text.split("\n")
|
737
|
-
text.each_with_index do |t,i|
|
738
|
-
if i.even?
|
739
|
-
@w_cmd.color = 8
|
740
|
-
@w_cmd.p(t)
|
741
|
-
else
|
742
|
-
t = t.split("|")
|
743
|
-
t.each_with_index do |c,j|
|
744
|
-
if j.even?
|
745
|
-
@w_cmd.color = 9
|
746
|
-
@w_cmd.p(c)
|
747
|
-
else
|
748
|
-
@w_cmd.color = 10
|
749
|
-
@w_cmd.p(c)
|
750
|
-
end
|
751
|
-
end
|
752
|
-
@w_cmd.p("\n")
|
753
|
-
end
|
754
|
-
@w_cmd.p("\n")
|
755
|
-
end
|
756
|
-
end
|
757
|
-
def help
|
758
|
-
help = <<HELPTEXT
|
759
|
-
|
760
|
-
T-REX - Terminal Rpn calculator EXperiment. GitHub: https://github.com/isene/T-REX
|
761
|
-
|
762
|
-
This is a Reverse Polish Notation calculator similar to the traditional Hewlett
|
763
|
-
Packard calculators. See https://www.hpmuseum.org/rpn.htm for info on RPN.
|
764
|
-
|
765
|
-
The stack is shown to the top left. The X, Y, Z and T registers comprise the
|
766
|
-
operating stack. L is the "Last X" register showing the previous value in X.
|
767
|
-
Toggle US and European number formats by pressing '.
|
768
|
-
|
769
|
-
Functions available are shown under the stack registers. The orange symbol
|
770
|
-
corresponds to the key to be pressed. For functions above each label (grey
|
771
|
-
functions), press the Control key (Ctrl) and the orange key (asin = Ctrl+i).
|
772
|
-
|
773
|
-
For Rectangular to Polar conversions:
|
774
|
-
R-P: X value in x, Y in y - yields "θ" in y and "r" in x.
|
775
|
-
P-R: "θ" in y and "r" in x - yeilds X in x and Y in y.
|
776
|
-
|
777
|
-
Use the "f" key to set the fixed number of decimal places. Use the "s" key to set
|
778
|
-
the limit for viewing numbers in the "scientific" notation (e.g. 5e+06 for 5000000).
|
779
|
-
|
780
|
-
Content of registers #0-#9 are shown below the functions.
|
781
|
-
Store/recall using capital "S"/"R". "M" clears the regs.
|
782
|
-
|
783
|
-
Copy/yank the X register to clipboard with "y". Use "Y" to yank all the memory regs.
|
784
|
-
|
785
|
-
You can undo all the way to the beginning of the session.
|
786
|
-
|
787
|
-
The 'H' key toggles the help text in the right pane.
|
788
|
-
|
789
|
-
The stack, register contents, modes and help text settings are saved on Quit.
|
790
|
-
|
791
|
-
Additionally, for a world of possibilities, you can access the "Ruby mode" via '@'.
|
792
|
-
Here you can address the stack directly, e.g. x = y + (z / t). Quit Ruby mode with Ctrl-C.
|
793
|
-
|
794
|
-
HELPTEXT
|
795
|
-
@w_hlp.p(help)
|
796
|
-
end
|
797
|
-
def conf_write # WRITE TO .t-rex.conf
|
798
|
-
conf = "@fix = #{@fix}\n"
|
799
|
-
conf += "@sci = #{@sci}\n"
|
800
|
-
@dot ? d = "true" : d = "false"
|
801
|
-
conf += "@dot = #{d}\n"
|
802
|
-
conf += "@mod = \"#{@mod}\"\n"
|
803
|
-
conf += "@stk = Stack.new(#{@stk.x}, #{@stk.y}, #{@stk.z}, #{@stk.t}, #{@stk.l})\n"
|
804
|
-
conf += "@reg = %w[#{@reg[0]} #{@reg[1]} #{@reg[2]} #{@reg[3]} #{@reg[4]} #{@reg[5]} #{@reg[6]} #{@reg[7]} #{@reg[8]} #{@reg[9]}]\n"
|
805
|
-
@hlp ? h = "true" : h = "false"
|
806
|
-
conf += "@hlp = #{h}\n"
|
807
|
-
File.write(Dir.home+'/.t-rex.conf', conf)
|
808
|
-
end
|
809
|
-
|
810
|
-
# MAIN PROGRAM
|
811
|
-
loop do # OUTER LOOP - (catching refreshes via 'b')
|
812
|
-
@break = false # Initialize @break variable (set if user hits 'b')
|
813
|
-
begin # Create the windows/panels
|
814
|
-
maxx = Curses.cols
|
815
|
-
maxy = Curses.lines
|
816
|
-
init_pair( 1, 235, 235) # stdscr
|
817
|
-
Curses.stdscr.color = 1
|
818
|
-
Curses.stdscr.fill
|
819
|
-
# Curses::Window.new(h,w,y,x)
|
820
|
-
@w_inf = Curses::Window.new( 1, 32, 1, 1)
|
821
|
-
@w_lbl = Curses::Window.new( 5, 2, 2, 1)
|
822
|
-
@w_l = Curses::Window.new( 1, 30, 2, 3)
|
823
|
-
@w_yzt = Curses::Window.new( 3, 30, 3, 3)
|
824
|
-
@w_x = Curses::Window.new( 1, 30, 6, 3)
|
825
|
-
@w_cmd = Curses::Window.new(12, 32, 8, 1)
|
826
|
-
@w_reg = Curses::Window.new(maxy - 22, 32, 21, 1)
|
827
|
-
@w_hlp = Curses::Window.new(maxy - 2, maxx - 35, 1, 34)
|
828
|
-
|
829
|
-
init_pair( 2, 88, 238) # @w_inf
|
830
|
-
init_pair( 3, 60, 238) # @w_lbl
|
831
|
-
init_pair( 4, 246, 236) # @w_l
|
832
|
-
init_pair( 5, 250, 234) # @w_yzt
|
833
|
-
init_pair( 6, 7, 0) # @w_x
|
834
|
-
init_pair( 7, 0, 250) # @w_xi
|
835
|
-
init_pair( 8, 242, 0) # @w_cmd ctrl- & @w_reg
|
836
|
-
init_pair( 9, 111, 0) # @w_cmd
|
837
|
-
init_pair(10, 214, 0) # @w_cmd key
|
838
|
-
init_pair(11, 238, 0) # @w_hlp
|
839
|
-
|
840
|
-
@w_inf.color = 2
|
841
|
-
@w_lbl.color = 3
|
842
|
-
@w_l.color = 4
|
843
|
-
@w_yzt.color = 5
|
844
|
-
@w_x.color = 6
|
845
|
-
@w_x.attr = Curses::A_BOLD
|
846
|
-
@w_cmd.color = 8
|
847
|
-
@w_cmd.attr = Curses::A_BOLD
|
848
|
-
@w_reg.color = 8
|
849
|
-
@w_hlp.color = 11
|
850
|
-
|
851
|
-
@w_lbl.p(" L T Z Y X")
|
852
|
-
@w_cmd.fill; cmd
|
853
|
-
@w_reg.fill
|
854
|
-
@w_hlp.fill
|
855
|
-
help if @hlp
|
856
|
-
|
857
|
-
@u = []
|
858
|
-
@undo = false
|
859
|
-
|
860
|
-
loop do # INNER, CORE LOOP
|
861
|
-
|
862
|
-
@w_inf.clr
|
863
|
-
@w_inf.p(" #{@mod} Sci=#{@sci} Fix=#{@fix}".ljust(32))
|
864
|
-
pstack
|
865
|
-
pregs
|
866
|
-
@t = @stk.dup
|
867
|
-
main_getkey("") # Get key from user
|
868
|
-
@u.push(@t.dup) if @t != @stk and @undo == false
|
869
|
-
@undo = false
|
870
|
-
|
871
|
-
break if @break # Break to outer loop, redrawing windows, if user hit 'r'
|
872
|
-
break if Curses.cols != maxx or Curses.lines != maxy # break on terminal resize
|
873
|
-
end
|
874
|
-
ensure # On exit: close curses, clear terminal
|
875
|
-
conf_write
|
876
|
-
close_screen
|
877
|
-
end
|
878
|
-
end
|
879
|
-
|
880
|
-
# vim: set sw=2 sts=2 et fdm=syntax fdn=2 fcs=fold\:\ :
|