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
ADDED
@@ -0,0 +1,760 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
#
|
4
|
+
# Title: T-REX (Terminal - Rpn EXperiment)
|
5
|
+
# Language: Pure Ruby, best viewed in VIM
|
6
|
+
# Author: Geir Isene <g@isene.com> http://isene.com/
|
7
|
+
# Github: https://github.com/isene/t-rex/
|
8
|
+
# License: I release all copyright claims. This code is in the public domain.
|
9
|
+
# Permission is granted to use, copy modify, distribute, and sell
|
10
|
+
# this software for any purpose. I make no guarantee about the
|
11
|
+
# suitability of this software for any purpose and I am not liable
|
12
|
+
# for any damages resulting from its use. Further, I am under no
|
13
|
+
# obligation to maintain or extend this software. It is provided
|
14
|
+
# on an 'as is' basis without any expressed or implied warranty.
|
15
|
+
@version = "2.0" # Full rewrite with rcurses, face lift, new functionality, bug fixes
|
16
|
+
|
17
|
+
require 'rcurses'
|
18
|
+
include Rcurses::Input
|
19
|
+
|
20
|
+
def help # HELP text
|
21
|
+
help = <<HELPTEXT
|
22
|
+
|
23
|
+
T-REX - Terminal Rpn calculator EXperiment. GitHub: https://github.com/isene/T-REX
|
24
|
+
This is a Reverse Polish Notation calculator similar to the traditional Hewlett
|
25
|
+
Packard calculators. See https://www.hpmuseum.org/rpn.htm for info on RPN.
|
26
|
+
|
27
|
+
The stack is shown to the top left. The X, Y, Z and T registers comprise the
|
28
|
+
operating stack. L is the "Last X" register showing the previous value in X.
|
29
|
+
Toggle US and European number formats by pressing '.
|
30
|
+
|
31
|
+
Functions available are shown under the stack registers. The orange symbol
|
32
|
+
corresponds to the key to be pressed. For functions above each label (grey
|
33
|
+
functions), press the Control key (Ctrl) and the orange key (asin = Ctrl+i).
|
34
|
+
|
35
|
+
For Rectangular to Polar conversions:
|
36
|
+
R-P: X value in x, Y in y - yields "θ" in y and "r" in x.
|
37
|
+
P-R: "θ" in y and "r" in x - yeilds X in x and Y in y.
|
38
|
+
|
39
|
+
Use the "f" key to set the fixed number of decimal places. Use the "s" key to set
|
40
|
+
the limit for viewing numbers in the "scientific" notation (e.g. 5e+06 for 5000000).
|
41
|
+
|
42
|
+
Content of registers #0-#9 are shown below the functions.
|
43
|
+
Store/recall using capital "S"/"R". "M" clears the regs.
|
44
|
+
|
45
|
+
Copy/yank the X register to clipboard with "y". Use "Y" to yank all the memory regs.
|
46
|
+
|
47
|
+
You can undo (with "u") all the way to the beginning of the session.
|
48
|
+
|
49
|
+
The 'H' key toggles between the help text in the right pane or a continuous printout.
|
50
|
+
Save the full printout to ~/t-rex.txt with "Ctrl-P".
|
51
|
+
|
52
|
+
The stack, register contents, modes and help text settings are saved on Quit.
|
53
|
+
|
54
|
+
Additionally, you can access the "Ruby mode" via '@'. Here you can address the stack
|
55
|
+
directly, e.g. 'x = y + (z / t); puts x'. Quit Ruby mode with ESC.
|
56
|
+
|
57
|
+
Alternative keys: Left/Right keys (in addition to "<") exchanges X and Y registers.
|
58
|
+
Backspace clears the x register.
|
59
|
+
HELPTEXT
|
60
|
+
if @hlp
|
61
|
+
@p_hlp.fg = 239
|
62
|
+
@p_hlp.ix = 0
|
63
|
+
@p_hlp.puts(help)
|
64
|
+
else
|
65
|
+
@p_hlp.ix = @history.length - @h + 3
|
66
|
+
histprint
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class Stack # STACK class
|
71
|
+
attr_accessor :x, :y, :z, :t, :l, :deg
|
72
|
+
|
73
|
+
def initialize(x, y, z, t, l)
|
74
|
+
self.x = x.to_f
|
75
|
+
self.y = y.to_f
|
76
|
+
self.z = z.to_f
|
77
|
+
self.t = t.to_f
|
78
|
+
self.l = l.to_f
|
79
|
+
end
|
80
|
+
def lift
|
81
|
+
self.y, self.z, self.t = self.x, self.y, self.z
|
82
|
+
end
|
83
|
+
def drop
|
84
|
+
self.y, self.z = self.z, self.t
|
85
|
+
end
|
86
|
+
def rdn
|
87
|
+
self.x, self.y, self.z, self.t = self.y, self.z, self.t, self.x
|
88
|
+
end
|
89
|
+
def rup
|
90
|
+
self.x, self.y, self.z, self.t = self.t, self.x, self.y, self.z
|
91
|
+
end
|
92
|
+
def xy
|
93
|
+
self.x, self.y = self.y, self.x
|
94
|
+
end
|
95
|
+
def add
|
96
|
+
self.l = self.x
|
97
|
+
self.x = self.y + self.x
|
98
|
+
self.drop
|
99
|
+
end
|
100
|
+
def subtract
|
101
|
+
self.l = self.x
|
102
|
+
self.x = self.y - self.x
|
103
|
+
self.drop
|
104
|
+
end
|
105
|
+
def multiply
|
106
|
+
self.l = self.x
|
107
|
+
self.x = self.y * self.x
|
108
|
+
self.drop
|
109
|
+
end
|
110
|
+
def divide
|
111
|
+
begin
|
112
|
+
throw if self.x == 0
|
113
|
+
self.l = self.x
|
114
|
+
self.x = self.y / self.x
|
115
|
+
self.drop
|
116
|
+
rescue
|
117
|
+
return "Error"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
def mod
|
121
|
+
begin
|
122
|
+
throw if self.x == 0
|
123
|
+
self.l = self.x
|
124
|
+
self.x = self.y % self.x
|
125
|
+
self.drop
|
126
|
+
rescue
|
127
|
+
return "Error"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
def percent
|
131
|
+
begin
|
132
|
+
throw if self.y == 0
|
133
|
+
self.l = self.x
|
134
|
+
self.x = 100*(self.x / self.y)
|
135
|
+
self.drop
|
136
|
+
rescue
|
137
|
+
return "Error"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
def chs
|
141
|
+
self.x = -self.x
|
142
|
+
end
|
143
|
+
def pi
|
144
|
+
self.l = self.x
|
145
|
+
self.lift
|
146
|
+
self.x = Math::PI
|
147
|
+
end
|
148
|
+
def pow
|
149
|
+
self.l = self.x
|
150
|
+
self.x = self.y ** self.x
|
151
|
+
self.drop
|
152
|
+
end
|
153
|
+
def root
|
154
|
+
begin
|
155
|
+
self.l = self.x
|
156
|
+
self.x = self.y ** (1 / self.x)
|
157
|
+
self.drop
|
158
|
+
rescue
|
159
|
+
return "Error"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
def recip
|
163
|
+
begin
|
164
|
+
throw if self.x == 0
|
165
|
+
self.l = self.x
|
166
|
+
self.x = 1 / self.x
|
167
|
+
rescue
|
168
|
+
return "Error"
|
169
|
+
end
|
170
|
+
end
|
171
|
+
def sqr
|
172
|
+
self.l = self.x
|
173
|
+
self.x = self.x ** 2
|
174
|
+
end
|
175
|
+
def sqrt
|
176
|
+
self.l = self.x
|
177
|
+
begin
|
178
|
+
self.x = Math::sqrt(self.x)
|
179
|
+
rescue
|
180
|
+
return "Error"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
def cube
|
184
|
+
self.l = self.x
|
185
|
+
self.x = self.x ** 3
|
186
|
+
end
|
187
|
+
def ln
|
188
|
+
self.l = self.x
|
189
|
+
begin
|
190
|
+
self.x = Math::log(self.x)
|
191
|
+
rescue
|
192
|
+
return "Error"
|
193
|
+
end
|
194
|
+
end
|
195
|
+
def ex
|
196
|
+
self.l = self.x
|
197
|
+
self.x = Math::exp(self.x)
|
198
|
+
end
|
199
|
+
def log
|
200
|
+
self.l = self.x
|
201
|
+
begin
|
202
|
+
self.x = Math::log10(self.x)
|
203
|
+
rescue
|
204
|
+
return "Error"
|
205
|
+
end
|
206
|
+
end
|
207
|
+
def tenx
|
208
|
+
self.l = self.x
|
209
|
+
self.x = 10 ** self.x
|
210
|
+
end
|
211
|
+
def sin
|
212
|
+
self.l = self.x
|
213
|
+
self.x = self.x * Math::PI / 180 if self.deg
|
214
|
+
self.x = Math::sin(self.x)
|
215
|
+
end
|
216
|
+
def cos
|
217
|
+
self.l = self.x
|
218
|
+
self.x = self.x * Math::PI / 180 if self.deg
|
219
|
+
self.x = Math::cos(self.x)
|
220
|
+
end
|
221
|
+
def tan
|
222
|
+
self.l = self.x
|
223
|
+
self.x = self.x * Math::PI / 180 if self.deg
|
224
|
+
self.x = Math::tan(self.x)
|
225
|
+
end
|
226
|
+
def asin
|
227
|
+
self.l = self.x
|
228
|
+
begin
|
229
|
+
self.x = Math::asin(self.x)
|
230
|
+
self.x = self.x * 180 / Math::PI if self.deg
|
231
|
+
rescue
|
232
|
+
return "Error"
|
233
|
+
end
|
234
|
+
end
|
235
|
+
def acos
|
236
|
+
self.l = self.x
|
237
|
+
begin
|
238
|
+
self.x = Math::acos(self.x)
|
239
|
+
self.x = self.x * 180 / Math::PI if self.deg
|
240
|
+
rescue
|
241
|
+
return "Error"
|
242
|
+
end
|
243
|
+
end
|
244
|
+
def atan
|
245
|
+
self.l = self.x
|
246
|
+
self.x = Math::atan(self.x)
|
247
|
+
self.x = self.x * 180 / Math::PI if self.deg
|
248
|
+
end
|
249
|
+
def rp
|
250
|
+
begin
|
251
|
+
throw if self.x == 0
|
252
|
+
self.l = self.x
|
253
|
+
x = self.x
|
254
|
+
y = self.y
|
255
|
+
self.x = Math::sqrt(x*x + y*y)
|
256
|
+
self.y = Math::atan(y/x)
|
257
|
+
if x < 0 # Q2 & Q3
|
258
|
+
self.y += Math::PI
|
259
|
+
elsif x >= 0 and y < 0 # Q4
|
260
|
+
self.y += 2 * Math::PI
|
261
|
+
end
|
262
|
+
self.y = self.y * 180 / Math::PI if self.deg
|
263
|
+
rescue
|
264
|
+
return "Error"
|
265
|
+
end
|
266
|
+
end
|
267
|
+
def pr
|
268
|
+
self.l = self.x
|
269
|
+
r = self.x
|
270
|
+
t = self.y
|
271
|
+
t = t * Math::PI / 180 if self.deg
|
272
|
+
self.x = r * Math::cos(t)
|
273
|
+
self.y = r * Math::sin(t)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
begin # BASIC setup
|
278
|
+
@stk = Stack.new(0, 0, 0, 0, 0)
|
279
|
+
@reg = %w[0 0 0 0 0 0 0 0 0 0]
|
280
|
+
@fix = 4
|
281
|
+
@sci = 6
|
282
|
+
@dot = true
|
283
|
+
@mod = "Deg"
|
284
|
+
@hlp = true
|
285
|
+
|
286
|
+
load(Dir.home+'/.t-rex.conf') if File.exist?(Dir.home+'/.t-rex.conf')
|
287
|
+
@mod == "Deg" ? @stk.deg = true : @stk.deg = false
|
288
|
+
|
289
|
+
@history = [" "]
|
290
|
+
@u = []
|
291
|
+
@undo = false
|
292
|
+
end
|
293
|
+
|
294
|
+
begin # PANE setup
|
295
|
+
@h, @w = IO.console.winsize
|
296
|
+
|
297
|
+
# pane = Rcurses::Pane.new( x, y, width, height, fg, bg)
|
298
|
+
@p_bck = Rcurses::Pane.new( 1, 1, @w, @h, 235, 235) # Back
|
299
|
+
@p_inf = Rcurses::Pane.new( 2, 2, 32, 1, 168, 238) # Info-line
|
300
|
+
@p_lbl = Rcurses::Pane.new( 2, 3, 1, 5, 250, 238) # LTZYX lables
|
301
|
+
@p_key = Rcurses::Pane.new( 2, 9, 32, 11, 0, 0) # Key panel
|
302
|
+
@p_reg = Rcurses::Pane.new( 2, 21, 32, @h - 21, 242, 0) # Regs
|
303
|
+
@p_hlp = Rcurses::Pane.new( 35, 2, @w - 35, @h - 2, 239, 0) # Help
|
304
|
+
@p_l = Rcurses::Pane.new( 4, 3, 30, 1, 60, 235) # L
|
305
|
+
@p_t = Rcurses::Pane.new( 4, 4, 30, 1, 68, 233) # T
|
306
|
+
@p_z = Rcurses::Pane.new( 4, 5, 30, 1, 75, 233) # Z
|
307
|
+
@p_y = Rcurses::Pane.new( 4, 6, 30, 1, 117, 233) # Y
|
308
|
+
@p_x = Rcurses::Pane.new( 4, 7, 30, 1, 7, 0) # X
|
309
|
+
|
310
|
+
@p_lbl.align = "r"
|
311
|
+
@p_l.align = "r"
|
312
|
+
@p_t.align = "r"
|
313
|
+
@p_z.align = "r"
|
314
|
+
@p_y.align = "r"
|
315
|
+
@p_x.align = "r"
|
316
|
+
|
317
|
+
@p_lbl.text = "ltzyx".i
|
318
|
+
|
319
|
+
class String
|
320
|
+
def t ; self.fg(111) ; end
|
321
|
+
def k ; self.fg(214) ; end
|
322
|
+
def s ; self.fg(242) ; end
|
323
|
+
end
|
324
|
+
|
325
|
+
keys = "\n"
|
326
|
+
keys += " r".t + "↓".k + " r".t + "↑".k + " x".t + "<".k + ">y".t
|
327
|
+
keys += " + - * / \\ %".k + " c".t + "h".k + "s".t + " p".k + "i".t
|
328
|
+
keys += "\n\n"
|
329
|
+
keys += " y√x x^2 x^3 e^x 10^x redrw".s
|
330
|
+
keys += "\n"
|
331
|
+
keys += " y".t + "^".k + "x".t + " 1/".t + "x".k + " s".t + "q".k + "rt".t
|
332
|
+
keys += " l".t + "n".k + " lo".t + "g".k + " l".k + "astx".t
|
333
|
+
keys += "\n\n"
|
334
|
+
keys += " asin acos atan R→P P→R cstk".s
|
335
|
+
keys += "\n"
|
336
|
+
keys += " s".t + "i".k + "n".t + " c".t + "o".k + "s".t + " t".t + "a".k + "n".t
|
337
|
+
keys += " r".k + "ad".t + " d".k + "eg".t + " c".k + "lx".t
|
338
|
+
keys += "\n\n"
|
339
|
+
keys += " S".k + "to".t + " R".k + "cl".t + " s".k + "ci".t + " f".k + "ix".t
|
340
|
+
keys += " u".k + "ndo".t + " H".k + "lp".t + " Q".k + "uit".t
|
341
|
+
@p_key.text = keys
|
342
|
+
end
|
343
|
+
|
344
|
+
# FUNCTIONS
|
345
|
+
def history(entry)
|
346
|
+
@history.push(entry.b, " #{@stk.t}".i, " #{@stk.z}".i, " #{@stk.y}".i, " #{@stk.x}".i.b, " ")
|
347
|
+
end
|
348
|
+
def histprint
|
349
|
+
print = @history.join("\n ")
|
350
|
+
@p_hlp.ix = 0 if @p_hlp.ix < 0
|
351
|
+
@p_hlp.fg = 145
|
352
|
+
@p_hlp.puts(print)
|
353
|
+
return print
|
354
|
+
end
|
355
|
+
def num_format(n) # THE NUMBER FORMAT FUNCTION
|
356
|
+
if n.abs >= 10 ** @sci.to_i
|
357
|
+
n = "%.#{@sci}g" % n
|
358
|
+
elsif n.abs <= 10 ** (1 / @sci.to_i) and n > 10
|
359
|
+
n = "%.#{@sci}g" % n
|
360
|
+
else
|
361
|
+
n = n.round(@fix)
|
362
|
+
n = "%.#{@fix}f" % n
|
363
|
+
m = n[/^-/]
|
364
|
+
m = "" if m == nil
|
365
|
+
n.sub!(/-/, '')
|
366
|
+
i = n[/\d*/]
|
367
|
+
i.gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1,")
|
368
|
+
f = n.sub(/\d*\.(\d*)/, '\1')
|
369
|
+
n = m + i + "." + f
|
370
|
+
if not @dot
|
371
|
+
n.gsub!(/,/, ' ')
|
372
|
+
n.sub!(/\./, ',')
|
373
|
+
end
|
374
|
+
end
|
375
|
+
return n
|
376
|
+
end
|
377
|
+
def main_getkey(c) # GET KEY FROM USER
|
378
|
+
c == "" ? chr = getchr : chr = c
|
379
|
+
case chr
|
380
|
+
when 'ENTER'
|
381
|
+
@stk.l = @stk.x
|
382
|
+
@stk.y, @stk.z, @stk.t = @stk.x, @stk.y, @stk.z
|
383
|
+
history("ENTER")
|
384
|
+
when "'"
|
385
|
+
@dot = !@dot
|
386
|
+
when 'UP' # Roll stack up
|
387
|
+
@stk.rup
|
388
|
+
history("↑")
|
389
|
+
when 'DOWN' # Roll stack down
|
390
|
+
@stk.rdn
|
391
|
+
history("↓")
|
392
|
+
when '<', 'LEFT', 'RIGHT' # x<>y
|
393
|
+
@stk.xy
|
394
|
+
history("x<>y")
|
395
|
+
when '+'
|
396
|
+
@stk.add
|
397
|
+
history("+")
|
398
|
+
when '-'
|
399
|
+
@stk.subtract
|
400
|
+
history("-")
|
401
|
+
when '*'
|
402
|
+
@stk.multiply
|
403
|
+
history("*")
|
404
|
+
when '/'
|
405
|
+
e = @stk.divide
|
406
|
+
history("/")
|
407
|
+
error ("Error: Divide by zero") if e == "Error"
|
408
|
+
when '\\' # \ (modulo)
|
409
|
+
@stk.mod
|
410
|
+
history("MOD")
|
411
|
+
when '%' # 100*x/y
|
412
|
+
e = @stk.percent
|
413
|
+
history("%")
|
414
|
+
error ("Error: Divide by zero") if e == "Error"
|
415
|
+
when 'h' # Change sign
|
416
|
+
@stk.chs
|
417
|
+
history("chs")
|
418
|
+
when 'p' # pi
|
419
|
+
@stk.l = @stk.x
|
420
|
+
@stk.pi
|
421
|
+
history("pi")
|
422
|
+
when '^' # y^x
|
423
|
+
@stk.pow
|
424
|
+
history("y^x")
|
425
|
+
when 'C-^' # y^(1/x)
|
426
|
+
e = @stk.root
|
427
|
+
history("y^(1/x)")
|
428
|
+
error ("Error: Divide by zero") if e == "Error"
|
429
|
+
when 'x' # 1/x
|
430
|
+
e = @stk.recip
|
431
|
+
history("1/x")
|
432
|
+
error ("Error: Divide by zero") if e == "Error"
|
433
|
+
when 'C-X' # x^2
|
434
|
+
@stk.sqr
|
435
|
+
history("x^2")
|
436
|
+
when 'q' # Square root
|
437
|
+
e = @stk.sqrt
|
438
|
+
history("sqrt")
|
439
|
+
error ("Error: Imaginary number") if e == "Error"
|
440
|
+
when 'C-Q' # x^3
|
441
|
+
@stk.cube
|
442
|
+
history("x^3")
|
443
|
+
when 'n' # ln(x)
|
444
|
+
e = @stk.ln
|
445
|
+
history("ln")
|
446
|
+
error ("Error: Negative x") if e == "Error"
|
447
|
+
when 'C-N' # e^x
|
448
|
+
@stk.ex
|
449
|
+
history("e^x")
|
450
|
+
when 'g' # log(x)
|
451
|
+
e = @stk.log
|
452
|
+
history("log")
|
453
|
+
error ("Error: Negative x") if e == "Error"
|
454
|
+
when 'C-G' # 10^x
|
455
|
+
@stk.tenx
|
456
|
+
history("10^x")
|
457
|
+
when 'l' # Recall Lastx (l) to x
|
458
|
+
@stk.lift
|
459
|
+
@stk.x = @stk.l
|
460
|
+
history("lastx")
|
461
|
+
when 'C-L' # Redraw
|
462
|
+
refresh
|
463
|
+
when 'i'
|
464
|
+
@stk.sin
|
465
|
+
history("sin")
|
466
|
+
when 'TAB' # Same as 'C-I'
|
467
|
+
e = @stk.asin
|
468
|
+
history("asin")
|
469
|
+
error ("Error: Number out of domain") if e == "Error"
|
470
|
+
when 'o'
|
471
|
+
@stk.cos
|
472
|
+
history("cos")
|
473
|
+
when 'C-O'
|
474
|
+
e = @stk.acos
|
475
|
+
history("acos")
|
476
|
+
error ("Error: Number out of domain") if e == "Error"
|
477
|
+
when 'a'
|
478
|
+
@stk.tan
|
479
|
+
history("tan")
|
480
|
+
when 'C-A'
|
481
|
+
@stk.atan
|
482
|
+
history("atan")
|
483
|
+
when 'r' # Rad mode
|
484
|
+
@mod = "Rad"
|
485
|
+
@stk.deg = false
|
486
|
+
history("Rad")
|
487
|
+
when 'C-R' # R->P
|
488
|
+
e = @stk.rp
|
489
|
+
history("R->P")
|
490
|
+
error ("Error: Divide by zero") if e == "Error"
|
491
|
+
when 'd' # Deg mode
|
492
|
+
@mod = "Deg"
|
493
|
+
@stk.deg = true
|
494
|
+
history("Deg")
|
495
|
+
when 'C-D' # P->R
|
496
|
+
@stk.pr
|
497
|
+
history("P->R")
|
498
|
+
when 'c', 'BACK'
|
499
|
+
@stk.x = 0
|
500
|
+
when 'C-C' # Clear stack
|
501
|
+
@stk.x = 0
|
502
|
+
@stk.y = 0
|
503
|
+
@stk.z = 0
|
504
|
+
@stk.t = 0
|
505
|
+
@stk.l = 0
|
506
|
+
history("CLR")
|
507
|
+
when 'M'
|
508
|
+
@reg = %w[0 0 0 0 0 0 0 0 0 0]
|
509
|
+
when 'S' # Store to Reg
|
510
|
+
@p_x.puts(" Store x in Reg #(0-9)")
|
511
|
+
r = getchr
|
512
|
+
if r =~ /[0-9]/
|
513
|
+
@reg[r.to_i] = @stk.x
|
514
|
+
end
|
515
|
+
history("STO #{r}")
|
516
|
+
when 'R' # Recall from Reg
|
517
|
+
@p_x.puts(" Recall from Reg #(0-9)")
|
518
|
+
r = getchr
|
519
|
+
if r =~ /[0-9]/
|
520
|
+
@stk.lift
|
521
|
+
@stk.x = @reg[r.to_i].to_f
|
522
|
+
end
|
523
|
+
history("RCL #{r}")
|
524
|
+
when 's' # Set Sci size/limit
|
525
|
+
@p_x.puts(" Sci notation limit (2-9)")
|
526
|
+
s = getchr
|
527
|
+
if s =~ /[2-9]/
|
528
|
+
@sci = s.to_i
|
529
|
+
end
|
530
|
+
history("Sci #{s}")
|
531
|
+
when 'f' # Set Fix size
|
532
|
+
@p_x.puts(" Fixed decimals (0-9)")
|
533
|
+
f = getchr
|
534
|
+
if f =~ /[0-9]/
|
535
|
+
@fix = f.to_i
|
536
|
+
end
|
537
|
+
history("Fix #{f}")
|
538
|
+
when 'u' # Undo
|
539
|
+
unless @u.empty?
|
540
|
+
@stk = @u.last.dup
|
541
|
+
@u.pop
|
542
|
+
@undo = true
|
543
|
+
end
|
544
|
+
history("UNDO")
|
545
|
+
when 'y'
|
546
|
+
begin
|
547
|
+
@p_x.bg = 250
|
548
|
+
@p_x.refresh
|
549
|
+
system("echo '#{@stk.x}' | xclip")
|
550
|
+
sleep(0.1)
|
551
|
+
@p_x.bg = 0
|
552
|
+
@p_x.refresh
|
553
|
+
rescue
|
554
|
+
@p_x.text = " Install xclip to yank"
|
555
|
+
@p_x.refresh
|
556
|
+
getchr
|
557
|
+
end
|
558
|
+
when 'Y'
|
559
|
+
begin
|
560
|
+
@p_x.bg = 244
|
561
|
+
@p_x.refresh
|
562
|
+
mem = ""
|
563
|
+
10.times do |i|
|
564
|
+
reg = @reg[i]
|
565
|
+
mem += "#{reg}\n"
|
566
|
+
end
|
567
|
+
system("echo '#{mem}' | xclip")
|
568
|
+
sleep(0.1)
|
569
|
+
@p_x.bg = 0
|
570
|
+
@p_x.refresh
|
571
|
+
rescue
|
572
|
+
@p_x.text = " Install xclip to yank"
|
573
|
+
@p_x.refresh
|
574
|
+
getchr
|
575
|
+
end
|
576
|
+
when 'H' # Toggle help/histprint
|
577
|
+
@hlp = !@hlp
|
578
|
+
when 'C-B'
|
579
|
+
if !@hlp
|
580
|
+
loop do
|
581
|
+
@p_hlp.ix -= @h + 3
|
582
|
+
histprint
|
583
|
+
break if getchr != 'C-B'
|
584
|
+
end
|
585
|
+
end
|
586
|
+
when 'C-P'
|
587
|
+
cont = histprint.pure
|
588
|
+
File.write(Dir.home+'/t-rex.txt', cont)
|
589
|
+
error ("History written to t-rex.txt")
|
590
|
+
when '@' # Ruby console
|
591
|
+
@p_hlp.fg = 168
|
592
|
+
loop do
|
593
|
+
@p_hlp.puts("")
|
594
|
+
@p_hlp.prompt = " Ruby: "
|
595
|
+
@p_hlp.editline
|
596
|
+
Rcurses::Cursor.set(4,36)
|
597
|
+
x = @stk.x
|
598
|
+
y = @stk.y
|
599
|
+
z = @stk.z
|
600
|
+
t = @stk.t
|
601
|
+
l = @stk.l
|
602
|
+
begin
|
603
|
+
eval(@p_hlp.text)
|
604
|
+
rescue
|
605
|
+
end
|
606
|
+
break if getchr == "ESC"
|
607
|
+
end
|
608
|
+
@p_hlp.fg = 239
|
609
|
+
getchr
|
610
|
+
@hlp ? help : @p_hlp.puts("")
|
611
|
+
when 'Q' # QUIT
|
612
|
+
exit 0
|
613
|
+
when /[0-9.,]/ # Go to entry mode for x
|
614
|
+
@stk.lift
|
615
|
+
pstack
|
616
|
+
number, c = entry(chr)
|
617
|
+
if number != ""
|
618
|
+
@stk.l = @stk.x
|
619
|
+
@stk.lift unless @stk.x == 0
|
620
|
+
@stk.x = number
|
621
|
+
end
|
622
|
+
history(number.to_s)
|
623
|
+
@stk.drop if c == "ENTER"
|
624
|
+
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)
|
625
|
+
@stk.drop
|
626
|
+
main_getkey(c)
|
627
|
+
end
|
628
|
+
end
|
629
|
+
end
|
630
|
+
def entry(chr) # X REGISTER ENTRY
|
631
|
+
num = chr
|
632
|
+
pos = 1
|
633
|
+
Rcurses::Cursor.set(7,33)
|
634
|
+
Rcurses::Cursor.show
|
635
|
+
while %w[0 1 2 3 4 5 6 7 8 9 . , h RIGHT LEFT HOME END DEL BACK WBACK LDEL].include?(chr)
|
636
|
+
@p_x.puts(num)
|
637
|
+
chr = getchr
|
638
|
+
case chr
|
639
|
+
when 'RIGHT'
|
640
|
+
pos += 1 unless pos >= num.length
|
641
|
+
when 'LEFT'
|
642
|
+
pos -= 1 unless pos == 0
|
643
|
+
when 'HOME'
|
644
|
+
pos = 0
|
645
|
+
when 'END'
|
646
|
+
pos = num.length
|
647
|
+
when 'DEL'
|
648
|
+
unless pos == 0
|
649
|
+
pos -= 1
|
650
|
+
num[pos] = ""
|
651
|
+
end
|
652
|
+
when 'BACK'
|
653
|
+
unless pos == 0
|
654
|
+
pos -= 1
|
655
|
+
num[pos - 1] = ""
|
656
|
+
end
|
657
|
+
when 'WBACK'
|
658
|
+
unless pos == 0
|
659
|
+
until num[pos - 1] == " " or pos == 0
|
660
|
+
pos -= 1
|
661
|
+
num[pos] = ""
|
662
|
+
end
|
663
|
+
if num[pos - 1] == " "
|
664
|
+
pos -= 1
|
665
|
+
num[pos] = ""
|
666
|
+
end
|
667
|
+
end
|
668
|
+
when 'LDEL'
|
669
|
+
num = ""
|
670
|
+
pos = 0
|
671
|
+
when 'h'
|
672
|
+
if num[0] == "-"
|
673
|
+
num[0] = ""
|
674
|
+
pos -= 1
|
675
|
+
else
|
676
|
+
num.insert(0, "-")
|
677
|
+
pos += 1
|
678
|
+
end
|
679
|
+
when /[0-9.,]/
|
680
|
+
num.insert(pos,chr)
|
681
|
+
pos += 1
|
682
|
+
end
|
683
|
+
Rcurses::Cursor.col(33 - num.length + pos)
|
684
|
+
end
|
685
|
+
num = "" if %w[DOWN UP].include?(chr)
|
686
|
+
num.gsub!(/,/, '.')
|
687
|
+
num != "" ? number = num.to_f : number = ""
|
688
|
+
Rcurses::Cursor.hide
|
689
|
+
return number, chr
|
690
|
+
end
|
691
|
+
def refresh # REFRESH ALL PANES
|
692
|
+
@p_bck.refresh
|
693
|
+
@p_inf.refresh
|
694
|
+
@p_lbl.refresh
|
695
|
+
@p_key.refresh
|
696
|
+
@p_reg.refresh
|
697
|
+
help
|
698
|
+
@p_l.refresh
|
699
|
+
@p_t.refresh
|
700
|
+
@p_z.refresh
|
701
|
+
@p_y.refresh
|
702
|
+
@p_x.refresh
|
703
|
+
end
|
704
|
+
def pstack # PRINT STACK (XYZTL)
|
705
|
+
@p_l.puts(num_format(@stk.l))
|
706
|
+
@p_t.puts(num_format(@stk.t))
|
707
|
+
@p_z.puts(num_format(@stk.z))
|
708
|
+
@p_y.puts(num_format(@stk.y))
|
709
|
+
@p_x.puts(num_format(@stk.x).b)
|
710
|
+
end
|
711
|
+
def pregs # PRINT CONTENT OF REGS (0-9)
|
712
|
+
@p_reg.text = "\n"
|
713
|
+
10.times do |i|
|
714
|
+
r = num_format(@reg[i].to_f)
|
715
|
+
@p_reg.text += " R##{i}".i + "#{r}".rjust(27) + "\n"
|
716
|
+
end
|
717
|
+
@p_reg.refresh
|
718
|
+
end
|
719
|
+
def error(err) # PRINT ERRORS TO X
|
720
|
+
@p_x.puts(err)
|
721
|
+
@history.insert(-2, err)
|
722
|
+
getchr
|
723
|
+
end
|
724
|
+
def conf_write # WRITE TO .t-rex.conf
|
725
|
+
conf = "@fix = #{@fix}\n"
|
726
|
+
conf += "@sci = #{@sci}\n"
|
727
|
+
@dot ? d = "true" : d = "false"
|
728
|
+
conf += "@dot = #{d}\n"
|
729
|
+
conf += "@mod = \"#{@mod}\"\n"
|
730
|
+
conf += "@stk = Stack.new(#{@stk.x}, #{@stk.y}, #{@stk.z}, #{@stk.t}, #{@stk.l})\n"
|
731
|
+
conf += "@reg = %w[#{@reg[0]} #{@reg[1]} #{@reg[2]} #{@reg[3]} #{@reg[4]} #{@reg[5]} #{@reg[6]} #{@reg[7]} #{@reg[8]} #{@reg[9]}]\n"
|
732
|
+
@hlp ? h = "true" : h = "false"
|
733
|
+
conf += "@hlp = #{h}\n"
|
734
|
+
File.write(Dir.home+'/.t-rex.conf', conf)
|
735
|
+
end
|
736
|
+
|
737
|
+
# MAIN PROGRAM
|
738
|
+
refresh
|
739
|
+
Rcurses::Cursor.hide
|
740
|
+
begin # Capture main loop
|
741
|
+
loop do # Main loop
|
742
|
+
@p_inf.puts(" #{@mod} Sci=#{@sci} Fix=#{@fix}".i)
|
743
|
+
pstack
|
744
|
+
pregs
|
745
|
+
@t = @stk.dup
|
746
|
+
main_getkey("") # Get key input from user
|
747
|
+
help
|
748
|
+
@u.push(@t.dup) if @t != @stk and @undo == false
|
749
|
+
@undo = false
|
750
|
+
h1, w1 = IO.console.winsize
|
751
|
+
if h1 != @h or w1 != @w # Refresh on terminal resize
|
752
|
+
@h, @w = IO.console.winsize
|
753
|
+
refresh
|
754
|
+
end
|
755
|
+
end
|
756
|
+
ensure # Write to .t-rex.conf on exit
|
757
|
+
conf_write
|
758
|
+
end
|
759
|
+
|
760
|
+
# vim: set sw=2 sts=2 et fdm=syntax fdn=2 fcs=fold\:\ :
|