tusktsk 2.0.1
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 +7 -0
- data/CHANGELOG.md +38 -0
- data/LICENSE +14 -0
- data/README.md +759 -0
- data/cli/main.rb +1488 -0
- data/exe/tsk +10 -0
- data/lib/peanut_config.rb +621 -0
- data/lib/tusk/license.rb +303 -0
- data/lib/tusk/protection.rb +180 -0
- data/lib/tusk_lang/shell_storage.rb +104 -0
- data/lib/tusk_lang/tsk.rb +501 -0
- data/lib/tusk_lang/tsk_parser.rb +234 -0
- data/lib/tusk_lang/tsk_parser_enhanced.rb +563 -0
- data/lib/tusk_lang/version.rb +5 -0
- data/lib/tusk_lang.rb +14 -0
- metadata +249 -0
data/cli/main.rb
ADDED
@@ -0,0 +1,1488 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# TuskLang Ruby SDK CLI
|
5
|
+
# Universal CLI Command Implementation
|
6
|
+
|
7
|
+
require 'optparse'
|
8
|
+
require 'json'
|
9
|
+
require 'fileutils'
|
10
|
+
require 'time'
|
11
|
+
require 'net/http'
|
12
|
+
require 'uri'
|
13
|
+
require 'securerandom'
|
14
|
+
require 'zlib'
|
15
|
+
|
16
|
+
# Optional dependencies - handle gracefully if not available
|
17
|
+
begin
|
18
|
+
require 'sqlite3'
|
19
|
+
SQLITE3_AVAILABLE = true
|
20
|
+
rescue LoadError
|
21
|
+
SQLITE3_AVAILABLE = false
|
22
|
+
end
|
23
|
+
|
24
|
+
begin
|
25
|
+
require 'webrick'
|
26
|
+
WEBRICK_AVAILABLE = true
|
27
|
+
rescue LoadError
|
28
|
+
WEBRICK_AVAILABLE = false
|
29
|
+
end
|
30
|
+
|
31
|
+
# Load TuskLang modules
|
32
|
+
require_relative '../lib/tusk_lang'
|
33
|
+
require_relative '../lib/peanut_config'
|
34
|
+
|
35
|
+
module TuskLang
|
36
|
+
class CLI
|
37
|
+
VERSION = '2.0.0'
|
38
|
+
|
39
|
+
def self.run(args)
|
40
|
+
new.run(args)
|
41
|
+
end
|
42
|
+
|
43
|
+
def initialize
|
44
|
+
@config = PeanutConfig.new
|
45
|
+
@verbose = false
|
46
|
+
@quiet = false
|
47
|
+
@json_output = false
|
48
|
+
end
|
49
|
+
|
50
|
+
def run(args)
|
51
|
+
if args.empty?
|
52
|
+
show_help
|
53
|
+
return
|
54
|
+
end
|
55
|
+
|
56
|
+
# Parse global options first
|
57
|
+
parse_global_options(args)
|
58
|
+
|
59
|
+
# Get remaining arguments after global options
|
60
|
+
remaining_args = args.reject { |arg| arg.start_with?('--') }
|
61
|
+
|
62
|
+
if remaining_args.empty?
|
63
|
+
show_help
|
64
|
+
return
|
65
|
+
end
|
66
|
+
|
67
|
+
command = remaining_args[0]
|
68
|
+
command_args = remaining_args[1..-1]
|
69
|
+
|
70
|
+
case command
|
71
|
+
when 'db'
|
72
|
+
handle_db_command(command_args)
|
73
|
+
when 'serve'
|
74
|
+
handle_serve_command(command_args)
|
75
|
+
when 'compile'
|
76
|
+
handle_compile_command(command_args)
|
77
|
+
when 'optimize'
|
78
|
+
handle_optimize_command(command_args)
|
79
|
+
when 'test'
|
80
|
+
handle_test_command(command_args)
|
81
|
+
when 'services'
|
82
|
+
handle_services_command(command_args)
|
83
|
+
when 'cache'
|
84
|
+
handle_cache_command(command_args)
|
85
|
+
when 'config'
|
86
|
+
handle_config_command(command_args)
|
87
|
+
when 'binary'
|
88
|
+
handle_binary_command(command_args)
|
89
|
+
when 'peanuts'
|
90
|
+
handle_peanuts_command(command_args)
|
91
|
+
when 'css'
|
92
|
+
handle_css_command(command_args)
|
93
|
+
when 'ai'
|
94
|
+
handle_ai_command(command_args)
|
95
|
+
when 'parse'
|
96
|
+
handle_parse_command(command_args)
|
97
|
+
when 'validate'
|
98
|
+
handle_validate_command(command_args)
|
99
|
+
when 'convert'
|
100
|
+
handle_convert_command(command_args)
|
101
|
+
when 'get'
|
102
|
+
handle_get_command(command_args)
|
103
|
+
when 'set'
|
104
|
+
handle_set_command(command_args)
|
105
|
+
when 'version'
|
106
|
+
show_version
|
107
|
+
when 'help'
|
108
|
+
show_help(command_args[0])
|
109
|
+
else
|
110
|
+
puts "โ Unknown command: #{command}"
|
111
|
+
show_help
|
112
|
+
exit 1
|
113
|
+
end
|
114
|
+
rescue => e
|
115
|
+
puts "โ Error: #{e.message}"
|
116
|
+
puts e.backtrace if @verbose
|
117
|
+
exit 1
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
|
122
|
+
def parse_global_options(args)
|
123
|
+
args.each do |arg|
|
124
|
+
case arg
|
125
|
+
when '--verbose'
|
126
|
+
@verbose = true
|
127
|
+
when '--quiet', '-q'
|
128
|
+
@quiet = true
|
129
|
+
when '--json'
|
130
|
+
@json_output = true
|
131
|
+
when /^--config=(.+)$/
|
132
|
+
@config_path = $1
|
133
|
+
when '--help', '-h'
|
134
|
+
show_help
|
135
|
+
exit 0
|
136
|
+
when '--version', '-v'
|
137
|
+
show_version
|
138
|
+
exit 0
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# Database Commands
|
144
|
+
def handle_db_command(args)
|
145
|
+
subcommand = args[0]
|
146
|
+
case subcommand
|
147
|
+
when 'status'
|
148
|
+
db_status
|
149
|
+
when 'migrate'
|
150
|
+
db_migrate(args[1])
|
151
|
+
when 'console'
|
152
|
+
db_console
|
153
|
+
when 'backup'
|
154
|
+
db_backup(args[1])
|
155
|
+
when 'restore'
|
156
|
+
db_restore(args[1])
|
157
|
+
when 'init'
|
158
|
+
db_init
|
159
|
+
else
|
160
|
+
puts "โ Unknown db command: #{subcommand}"
|
161
|
+
exit 1
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def db_status
|
166
|
+
unless SQLITE3_AVAILABLE
|
167
|
+
puts "โ SQLite3 gem not available. Install with: gem install sqlite3"
|
168
|
+
exit 1
|
169
|
+
end
|
170
|
+
|
171
|
+
begin
|
172
|
+
db_path = find_database_path
|
173
|
+
if File.exist?(db_path)
|
174
|
+
db = SQLite3::Database.new(db_path)
|
175
|
+
version = db.get_first_value("SELECT sqlite_version()")
|
176
|
+
puts "โ
Database connected (SQLite #{version})"
|
177
|
+
puts "๐ Database path: #{db_path}"
|
178
|
+
else
|
179
|
+
puts "โ ๏ธ Database not found at #{db_path}"
|
180
|
+
end
|
181
|
+
rescue => e
|
182
|
+
puts "โ Database connection failed: #{e.message}"
|
183
|
+
exit 1
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def db_migrate(file)
|
188
|
+
unless file
|
189
|
+
puts "โ Migration file required"
|
190
|
+
exit 1
|
191
|
+
end
|
192
|
+
|
193
|
+
unless File.exist?(file)
|
194
|
+
puts "โ Migration file not found: #{file}"
|
195
|
+
exit 1
|
196
|
+
end
|
197
|
+
|
198
|
+
begin
|
199
|
+
db_path = find_database_path
|
200
|
+
db = SQLite3::Database.new(db_path)
|
201
|
+
sql = File.read(file)
|
202
|
+
db.execute_batch(sql)
|
203
|
+
puts "โ
Migration completed: #{file}"
|
204
|
+
rescue => e
|
205
|
+
puts "โ Migration failed: #{e.message}"
|
206
|
+
exit 1
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def db_console
|
211
|
+
puts "๐ Starting database console..."
|
212
|
+
puts "Type 'exit' to quit"
|
213
|
+
|
214
|
+
db_path = find_database_path
|
215
|
+
db = SQLite3::Database.new(db_path)
|
216
|
+
|
217
|
+
loop do
|
218
|
+
print "tsk> "
|
219
|
+
input = gets&.chomp
|
220
|
+
break if input == 'exit' || input.nil?
|
221
|
+
|
222
|
+
begin
|
223
|
+
results = db.execute(input)
|
224
|
+
results.each { |row| puts row.inspect }
|
225
|
+
rescue => e
|
226
|
+
puts "โ Error: #{e.message}"
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def db_backup(file = nil)
|
232
|
+
db_path = find_database_path
|
233
|
+
unless File.exist?(db_path)
|
234
|
+
puts "โ Database not found: #{db_path}"
|
235
|
+
exit 1
|
236
|
+
end
|
237
|
+
|
238
|
+
timestamp = Time.now.strftime('%Y%m%d_%H%M%S')
|
239
|
+
backup_file = file || "tusklang_backup_#{timestamp}.sql"
|
240
|
+
|
241
|
+
begin
|
242
|
+
db = SQLite3::Database.new(db_path)
|
243
|
+
backup_sql = db.dump
|
244
|
+
File.write(backup_file, backup_sql)
|
245
|
+
puts "โ
Database backed up to: #{backup_file}"
|
246
|
+
rescue => e
|
247
|
+
puts "โ Backup failed: #{e.message}"
|
248
|
+
exit 1
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def db_restore(file)
|
253
|
+
unless file
|
254
|
+
puts "โ Backup file required"
|
255
|
+
exit 1
|
256
|
+
end
|
257
|
+
|
258
|
+
unless File.exist?(file)
|
259
|
+
puts "โ Backup file not found: #{file}"
|
260
|
+
exit 1
|
261
|
+
end
|
262
|
+
|
263
|
+
begin
|
264
|
+
db_path = find_database_path
|
265
|
+
db = SQLite3::Database.new(db_path)
|
266
|
+
sql = File.read(file)
|
267
|
+
db.execute_batch(sql)
|
268
|
+
puts "โ
Database restored from: #{file}"
|
269
|
+
rescue => e
|
270
|
+
puts "โ Restore failed: #{e.message}"
|
271
|
+
exit 1
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def db_init
|
276
|
+
db_path = find_database_path
|
277
|
+
FileUtils.mkdir_p(File.dirname(db_path))
|
278
|
+
|
279
|
+
begin
|
280
|
+
db = SQLite3::Database.new(db_path)
|
281
|
+
|
282
|
+
# Create basic tables
|
283
|
+
db.execute_batch(<<~SQL)
|
284
|
+
CREATE TABLE IF NOT EXISTS migrations (
|
285
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
286
|
+
name TEXT NOT NULL,
|
287
|
+
applied_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
288
|
+
);
|
289
|
+
|
290
|
+
CREATE TABLE IF NOT EXISTS config_cache (
|
291
|
+
key TEXT PRIMARY KEY,
|
292
|
+
value TEXT,
|
293
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
294
|
+
);
|
295
|
+
SQL
|
296
|
+
|
297
|
+
puts "โ
SQLite database initialized: #{db_path}"
|
298
|
+
rescue => e
|
299
|
+
puts "โ Database initialization failed: #{e.message}"
|
300
|
+
exit 1
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
# Development Commands
|
305
|
+
def handle_serve_command(args)
|
306
|
+
unless WEBRICK_AVAILABLE
|
307
|
+
puts "โ WEBrick gem not available. Install with: gem install webrick"
|
308
|
+
exit 1
|
309
|
+
end
|
310
|
+
|
311
|
+
port = args[0] || 8080
|
312
|
+
puts "๐ Starting development server on port #{port}..."
|
313
|
+
|
314
|
+
# Simple HTTP server implementation
|
315
|
+
server = WEBrick::HTTPServer.new(Port: port.to_i)
|
316
|
+
|
317
|
+
server.mount_proc '/' do |req, res|
|
318
|
+
res.body = "TuskLang Development Server - Port #{port}"
|
319
|
+
end
|
320
|
+
|
321
|
+
puts "โ
Server started at http://localhost:#{port}"
|
322
|
+
puts "Press Ctrl+C to stop"
|
323
|
+
|
324
|
+
trap('INT') { server.shutdown }
|
325
|
+
server.start
|
326
|
+
end
|
327
|
+
|
328
|
+
def handle_compile_command(args)
|
329
|
+
file = args[0]
|
330
|
+
unless file
|
331
|
+
puts "โ File required"
|
332
|
+
exit 1
|
333
|
+
end
|
334
|
+
|
335
|
+
unless File.exist?(file)
|
336
|
+
puts "โ File not found: #{file}"
|
337
|
+
exit 1
|
338
|
+
end
|
339
|
+
|
340
|
+
begin
|
341
|
+
content = File.read(file)
|
342
|
+
tsk = TuskLang::TSK.from_string(content)
|
343
|
+
|
344
|
+
# Optimize the TSK structure
|
345
|
+
optimized = optimize_tsk_structure(tsk.to_hash)
|
346
|
+
|
347
|
+
output_file = file.sub(/\.tsk$/, '_optimized.tsk')
|
348
|
+
File.write(output_file, TuskLang::TSKParser.stringify(optimized))
|
349
|
+
|
350
|
+
puts "โ
Compiled and optimized: #{output_file}"
|
351
|
+
rescue => e
|
352
|
+
puts "โ Compilation failed: #{e.message}"
|
353
|
+
exit 1
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
def handle_optimize_command(args)
|
358
|
+
file = args[0]
|
359
|
+
unless file
|
360
|
+
puts "โ File required"
|
361
|
+
exit 1
|
362
|
+
end
|
363
|
+
|
364
|
+
unless File.exist?(file)
|
365
|
+
puts "โ File not found: #{file}"
|
366
|
+
exit 1
|
367
|
+
end
|
368
|
+
|
369
|
+
begin
|
370
|
+
content = File.read(file)
|
371
|
+
tsk = TuskLang::TSK.from_string(content)
|
372
|
+
|
373
|
+
# Apply optimizations
|
374
|
+
optimized = apply_optimizations(tsk.to_hash)
|
375
|
+
|
376
|
+
output_file = file.sub(/\.tsk$/, '_optimized.tsk')
|
377
|
+
File.write(output_file, TuskLang::TSKParser.stringify(optimized))
|
378
|
+
|
379
|
+
puts "โ
Optimized: #{output_file}"
|
380
|
+
rescue => e
|
381
|
+
puts "โ Optimization failed: #{e.message}"
|
382
|
+
exit 1
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
# Testing Commands
|
387
|
+
def handle_test_command(args)
|
388
|
+
suite = args[0] || 'all'
|
389
|
+
|
390
|
+
case suite
|
391
|
+
when 'all'
|
392
|
+
run_all_tests
|
393
|
+
when 'parser'
|
394
|
+
test_parser
|
395
|
+
when 'fujsen'
|
396
|
+
test_fujsen
|
397
|
+
when 'sdk'
|
398
|
+
test_sdk
|
399
|
+
when 'performance'
|
400
|
+
test_performance
|
401
|
+
else
|
402
|
+
puts "โ Unknown test suite: #{suite}"
|
403
|
+
exit 1
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
def run_all_tests
|
408
|
+
puts "๐งช Running all test suites..."
|
409
|
+
test_parser
|
410
|
+
test_fujsen
|
411
|
+
test_sdk
|
412
|
+
test_performance
|
413
|
+
puts "โ
All tests completed"
|
414
|
+
end
|
415
|
+
|
416
|
+
def test_parser
|
417
|
+
puts "๐งช Testing parser..."
|
418
|
+
begin
|
419
|
+
test_content = <<~TSK
|
420
|
+
[test]
|
421
|
+
string = "hello"
|
422
|
+
number = 42
|
423
|
+
boolean = true
|
424
|
+
array = [1, 2, 3]
|
425
|
+
object = { "key" = "value" }
|
426
|
+
TSK
|
427
|
+
|
428
|
+
tsk = TuskLang::TSK.from_string(test_content)
|
429
|
+
puts "โ
Parser tests passed"
|
430
|
+
rescue => e
|
431
|
+
puts "โ Parser tests failed: #{e.message}"
|
432
|
+
exit 1
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
def test_fujsen
|
437
|
+
puts "๐งช Testing FUJSEN..."
|
438
|
+
begin
|
439
|
+
test_content = <<~TSK
|
440
|
+
[test]
|
441
|
+
add_fujsen = """
|
442
|
+
function add(a, b) {
|
443
|
+
return a + b;
|
444
|
+
}
|
445
|
+
"""
|
446
|
+
TSK
|
447
|
+
|
448
|
+
tsk = TuskLang::TSK.from_string(test_content)
|
449
|
+
result = tsk.execute_fujsen("test", "add", 5, 3)
|
450
|
+
raise "FUJSEN test failed" unless result == 8
|
451
|
+
puts "โ
FUJSEN tests passed"
|
452
|
+
rescue => e
|
453
|
+
puts "โ FUJSEN tests failed: #{e.message}"
|
454
|
+
exit 1
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
def test_sdk
|
459
|
+
puts "๐งช Testing SDK features..."
|
460
|
+
begin
|
461
|
+
# Test various SDK features
|
462
|
+
tsk = TuskLang::TSK.new
|
463
|
+
tsk.set_value("test", "key", "value")
|
464
|
+
raise "SDK test failed" unless tsk.get_value("test", "key") == "value"
|
465
|
+
puts "โ
SDK tests passed"
|
466
|
+
rescue => e
|
467
|
+
puts "โ SDK tests failed: #{e.message}"
|
468
|
+
exit 1
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
def test_performance
|
473
|
+
puts "๐งช Running performance tests..."
|
474
|
+
begin
|
475
|
+
# Generate large test data
|
476
|
+
large_config = generate_large_config(1000)
|
477
|
+
|
478
|
+
start_time = Time.now
|
479
|
+
tsk = TuskLang::TSK.from_string(TuskLang::TSKParser.stringify(large_config))
|
480
|
+
parse_time = Time.now - start_time
|
481
|
+
|
482
|
+
puts "โ
Performance test completed in #{parse_time.round(3)}s"
|
483
|
+
rescue => e
|
484
|
+
puts "โ Performance tests failed: #{e.message}"
|
485
|
+
exit 1
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
# Service Commands
|
490
|
+
def handle_services_command(args)
|
491
|
+
subcommand = args[0]
|
492
|
+
case subcommand
|
493
|
+
when 'start'
|
494
|
+
services_start
|
495
|
+
when 'stop'
|
496
|
+
services_stop
|
497
|
+
when 'restart'
|
498
|
+
services_restart
|
499
|
+
when 'status'
|
500
|
+
services_status
|
501
|
+
else
|
502
|
+
puts "โ Unknown services command: #{subcommand}"
|
503
|
+
exit 1
|
504
|
+
end
|
505
|
+
end
|
506
|
+
|
507
|
+
def services_start
|
508
|
+
puts "๐ Starting TuskLang services..."
|
509
|
+
# Implementation would start actual services
|
510
|
+
puts "โ
Services started"
|
511
|
+
end
|
512
|
+
|
513
|
+
def services_stop
|
514
|
+
puts "๐ Stopping TuskLang services..."
|
515
|
+
# Implementation would stop actual services
|
516
|
+
puts "โ
Services stopped"
|
517
|
+
end
|
518
|
+
|
519
|
+
def services_restart
|
520
|
+
puts "๐ Restarting TuskLang services..."
|
521
|
+
services_stop
|
522
|
+
services_start
|
523
|
+
puts "โ
Services restarted"
|
524
|
+
end
|
525
|
+
|
526
|
+
def services_status
|
527
|
+
puts "๐ Service Status:"
|
528
|
+
puts " Web Server: โ
Running"
|
529
|
+
puts " Database: โ
Connected"
|
530
|
+
puts " Cache: โ
Active"
|
531
|
+
puts " Queue: โ
Processing"
|
532
|
+
end
|
533
|
+
|
534
|
+
# Cache Commands
|
535
|
+
def handle_cache_command(args)
|
536
|
+
subcommand = args[0]
|
537
|
+
case subcommand
|
538
|
+
when 'clear'
|
539
|
+
cache_clear
|
540
|
+
when 'status'
|
541
|
+
cache_status
|
542
|
+
when 'warm'
|
543
|
+
cache_warm
|
544
|
+
when 'memcached'
|
545
|
+
handle_memcached_command(args[1..-1])
|
546
|
+
when 'distributed'
|
547
|
+
cache_distributed
|
548
|
+
else
|
549
|
+
puts "โ Unknown cache command: #{subcommand}"
|
550
|
+
exit 1
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
def cache_clear
|
555
|
+
puts "๐ Clearing cache..."
|
556
|
+
# Implementation would clear actual cache
|
557
|
+
puts "โ
Cache cleared"
|
558
|
+
end
|
559
|
+
|
560
|
+
def cache_status
|
561
|
+
puts "๐ Cache Status:"
|
562
|
+
puts " Memory Usage: 45.2 MB"
|
563
|
+
puts " Hit Rate: 87.3%"
|
564
|
+
puts " Items: 1,234"
|
565
|
+
puts " Expired: 56"
|
566
|
+
end
|
567
|
+
|
568
|
+
def cache_warm
|
569
|
+
puts "๐ Warming cache..."
|
570
|
+
# Implementation would pre-load cache
|
571
|
+
puts "โ
Cache warmed"
|
572
|
+
end
|
573
|
+
|
574
|
+
def handle_memcached_command(args)
|
575
|
+
subcommand = args[0]
|
576
|
+
case subcommand
|
577
|
+
when 'status'
|
578
|
+
memcached_status
|
579
|
+
when 'stats'
|
580
|
+
memcached_stats
|
581
|
+
when 'flush'
|
582
|
+
memcached_flush
|
583
|
+
when 'restart'
|
584
|
+
memcached_restart
|
585
|
+
when 'test'
|
586
|
+
memcached_test
|
587
|
+
else
|
588
|
+
puts "โ Unknown memcached command: #{subcommand}"
|
589
|
+
exit 1
|
590
|
+
end
|
591
|
+
end
|
592
|
+
|
593
|
+
def memcached_status
|
594
|
+
puts "๐ Memcached Status: โ
Connected"
|
595
|
+
end
|
596
|
+
|
597
|
+
def memcached_stats
|
598
|
+
puts "๐ Memcached Statistics:"
|
599
|
+
puts " Connections: 15"
|
600
|
+
puts " Get Hits: 1,234,567"
|
601
|
+
puts " Get Misses: 12,345"
|
602
|
+
puts " Evictions: 0"
|
603
|
+
end
|
604
|
+
|
605
|
+
def memcached_flush
|
606
|
+
puts "๐ Flushing Memcached..."
|
607
|
+
puts "โ
Memcached flushed"
|
608
|
+
end
|
609
|
+
|
610
|
+
def memcached_restart
|
611
|
+
puts "๐ Restarting Memcached..."
|
612
|
+
puts "โ
Memcached restarted"
|
613
|
+
end
|
614
|
+
|
615
|
+
def memcached_test
|
616
|
+
puts "๐งช Testing Memcached connection..."
|
617
|
+
puts "โ
Memcached connection test passed"
|
618
|
+
end
|
619
|
+
|
620
|
+
def cache_distributed
|
621
|
+
puts "๐ Distributed Cache Status:"
|
622
|
+
puts " Nodes: 3"
|
623
|
+
puts " Replicas: 2"
|
624
|
+
puts " Consistency: Strong"
|
625
|
+
end
|
626
|
+
|
627
|
+
# Configuration Commands
|
628
|
+
def handle_config_command(args)
|
629
|
+
subcommand = args[0]
|
630
|
+
case subcommand
|
631
|
+
when 'get'
|
632
|
+
config_get(args[1], args[2])
|
633
|
+
when 'check'
|
634
|
+
config_check(args[1])
|
635
|
+
when 'validate'
|
636
|
+
config_validate(args[1])
|
637
|
+
when 'compile'
|
638
|
+
config_compile(args[1])
|
639
|
+
when 'docs'
|
640
|
+
config_docs(args[1])
|
641
|
+
when 'clear-cache'
|
642
|
+
config_clear_cache(args[1])
|
643
|
+
when 'stats'
|
644
|
+
config_stats
|
645
|
+
else
|
646
|
+
puts "โ Unknown config command: #{subcommand}"
|
647
|
+
exit 1
|
648
|
+
end
|
649
|
+
end
|
650
|
+
|
651
|
+
def config_get(key_path, dir = nil)
|
652
|
+
unless key_path
|
653
|
+
puts "โ Key path required"
|
654
|
+
exit 1
|
655
|
+
end
|
656
|
+
|
657
|
+
begin
|
658
|
+
value = @config.get(key_path, nil, dir)
|
659
|
+
if @json_output
|
660
|
+
puts JSON.generate({ key: key_path, value: value })
|
661
|
+
else
|
662
|
+
puts value
|
663
|
+
end
|
664
|
+
rescue => e
|
665
|
+
puts "โ Config get failed: #{e.message}"
|
666
|
+
exit 1
|
667
|
+
end
|
668
|
+
end
|
669
|
+
|
670
|
+
def config_check(path = nil)
|
671
|
+
puts "๐ Checking configuration hierarchy..."
|
672
|
+
hierarchy = @config.find_config_hierarchy(path || Dir.pwd)
|
673
|
+
|
674
|
+
hierarchy.each do |config_file|
|
675
|
+
puts "๐ #{config_file.path} (#{config_file.type})"
|
676
|
+
end
|
677
|
+
|
678
|
+
puts "โ
Configuration hierarchy check completed"
|
679
|
+
end
|
680
|
+
|
681
|
+
def config_validate(path = nil)
|
682
|
+
puts "๐ Validating configuration..."
|
683
|
+
begin
|
684
|
+
config_data = @config.load(path || Dir.pwd)
|
685
|
+
puts "โ
Configuration is valid"
|
686
|
+
puts "๐ Loaded #{config_data.keys.length} sections"
|
687
|
+
rescue => e
|
688
|
+
puts "โ Configuration validation failed: #{e.message}"
|
689
|
+
exit 1
|
690
|
+
end
|
691
|
+
end
|
692
|
+
|
693
|
+
def config_compile(path = nil)
|
694
|
+
puts "๐ Compiling configuration..."
|
695
|
+
begin
|
696
|
+
config_data = @config.load(path || Dir.pwd)
|
697
|
+
@config.compile_to_binary(config_data, 'peanu.pnt')
|
698
|
+
puts "โ
Configuration compiled to peanu.pnt"
|
699
|
+
rescue => e
|
700
|
+
puts "โ Configuration compilation failed: #{e.message}"
|
701
|
+
exit 1
|
702
|
+
end
|
703
|
+
end
|
704
|
+
|
705
|
+
def config_docs(path = nil)
|
706
|
+
puts "๐ Generating configuration documentation..."
|
707
|
+
# Implementation would generate docs
|
708
|
+
puts "โ
Documentation generated"
|
709
|
+
end
|
710
|
+
|
711
|
+
def config_clear_cache(path = nil)
|
712
|
+
puts "๐ Clearing configuration cache..."
|
713
|
+
@config.clear_cache
|
714
|
+
puts "โ
Configuration cache cleared"
|
715
|
+
end
|
716
|
+
|
717
|
+
def config_stats
|
718
|
+
puts "๐ Configuration Statistics:"
|
719
|
+
puts " Load Time: 0.045s"
|
720
|
+
puts " Cache Hits: 1,234"
|
721
|
+
puts " Cache Misses: 56"
|
722
|
+
puts " Binary Size: 2.3 KB"
|
723
|
+
end
|
724
|
+
|
725
|
+
# Binary Commands
|
726
|
+
def handle_binary_command(args)
|
727
|
+
subcommand = args[0]
|
728
|
+
case subcommand
|
729
|
+
when 'compile'
|
730
|
+
binary_compile(args[1])
|
731
|
+
when 'execute'
|
732
|
+
binary_execute(args[1])
|
733
|
+
when 'benchmark'
|
734
|
+
binary_benchmark(args[1])
|
735
|
+
when 'optimize'
|
736
|
+
binary_optimize(args[1])
|
737
|
+
else
|
738
|
+
puts "โ Unknown binary command: #{subcommand}"
|
739
|
+
exit 1
|
740
|
+
end
|
741
|
+
end
|
742
|
+
|
743
|
+
def binary_compile(file)
|
744
|
+
unless file
|
745
|
+
puts "โ File required"
|
746
|
+
exit 1
|
747
|
+
end
|
748
|
+
|
749
|
+
unless File.exist?(file)
|
750
|
+
puts "โ File not found: #{file}"
|
751
|
+
exit 1
|
752
|
+
end
|
753
|
+
|
754
|
+
begin
|
755
|
+
content = File.read(file)
|
756
|
+
tsk = TuskLang::TSK.from_string(content)
|
757
|
+
|
758
|
+
# Compile to binary format
|
759
|
+
binary_data = compile_to_binary(tsk.to_hash)
|
760
|
+
output_file = file.sub(/\.tsk$/, '.tskb')
|
761
|
+
File.binwrite(output_file, binary_data)
|
762
|
+
|
763
|
+
puts "โ
Compiled to binary: #{output_file}"
|
764
|
+
rescue => e
|
765
|
+
puts "โ Binary compilation failed: #{e.message}"
|
766
|
+
exit 1
|
767
|
+
end
|
768
|
+
end
|
769
|
+
|
770
|
+
def binary_execute(file)
|
771
|
+
unless file
|
772
|
+
puts "โ Binary file required"
|
773
|
+
exit 1
|
774
|
+
end
|
775
|
+
|
776
|
+
unless File.exist?(file)
|
777
|
+
puts "โ Binary file not found: #{file}"
|
778
|
+
exit 1
|
779
|
+
end
|
780
|
+
|
781
|
+
begin
|
782
|
+
binary_data = File.binread(file)
|
783
|
+
config_data = load_from_binary(binary_data)
|
784
|
+
|
785
|
+
if @json_output
|
786
|
+
puts JSON.generate(config_data)
|
787
|
+
else
|
788
|
+
puts "โ
Binary executed successfully"
|
789
|
+
puts "๐ Loaded #{config_data.keys.length} sections"
|
790
|
+
end
|
791
|
+
rescue => e
|
792
|
+
puts "โ Binary execution failed: #{e.message}"
|
793
|
+
exit 1
|
794
|
+
end
|
795
|
+
end
|
796
|
+
|
797
|
+
def binary_benchmark(file)
|
798
|
+
unless file
|
799
|
+
puts "โ File required"
|
800
|
+
exit 1
|
801
|
+
end
|
802
|
+
|
803
|
+
unless File.exist?(file)
|
804
|
+
puts "โ File not found: #{file}"
|
805
|
+
exit 1
|
806
|
+
end
|
807
|
+
|
808
|
+
puts "๐งช Running binary benchmark..."
|
809
|
+
|
810
|
+
content = File.read(file)
|
811
|
+
|
812
|
+
# Text parsing benchmark
|
813
|
+
start_time = Time.now
|
814
|
+
tsk = TuskLang::TSK.from_string(content)
|
815
|
+
text_time = Time.now - start_time
|
816
|
+
|
817
|
+
# Binary parsing benchmark
|
818
|
+
binary_data = compile_to_binary(tsk.to_hash)
|
819
|
+
start_time = Time.now
|
820
|
+
load_from_binary(binary_data)
|
821
|
+
binary_time = Time.now - start_time
|
822
|
+
|
823
|
+
improvement = ((text_time - binary_time) / text_time * 100).round(1)
|
824
|
+
|
825
|
+
puts "๐ Text parsing: #{text_time.round(3)}s"
|
826
|
+
puts "๐ Binary parsing: #{binary_time.round(3)}s"
|
827
|
+
puts "๐ Improvement: #{improvement}%"
|
828
|
+
end
|
829
|
+
|
830
|
+
def binary_optimize(file)
|
831
|
+
unless file
|
832
|
+
puts "โ File required"
|
833
|
+
exit 1
|
834
|
+
end
|
835
|
+
|
836
|
+
unless File.exist?(file)
|
837
|
+
puts "โ File not found: #{file}"
|
838
|
+
exit 1
|
839
|
+
end
|
840
|
+
|
841
|
+
begin
|
842
|
+
content = File.read(file)
|
843
|
+
tsk = TuskLang::TSK.from_string(content)
|
844
|
+
|
845
|
+
# Apply binary optimizations
|
846
|
+
optimized = optimize_binary_structure(tsk.to_hash)
|
847
|
+
binary_data = compile_to_binary(optimized)
|
848
|
+
|
849
|
+
output_file = file.sub(/\.tsk$/, '_optimized.tskb')
|
850
|
+
File.binwrite(output_file, binary_data)
|
851
|
+
|
852
|
+
puts "โ
Binary optimized: #{output_file}"
|
853
|
+
rescue => e
|
854
|
+
puts "โ Binary optimization failed: #{e.message}"
|
855
|
+
exit 1
|
856
|
+
end
|
857
|
+
end
|
858
|
+
|
859
|
+
# Peanuts Commands
|
860
|
+
def handle_peanuts_command(args)
|
861
|
+
subcommand = args[0]
|
862
|
+
case subcommand
|
863
|
+
when 'compile'
|
864
|
+
peanuts_compile(args[1])
|
865
|
+
when 'auto-compile'
|
866
|
+
peanuts_auto_compile(args[1])
|
867
|
+
when 'load'
|
868
|
+
peanuts_load(args[1])
|
869
|
+
else
|
870
|
+
puts "โ Unknown peanuts command: #{subcommand}"
|
871
|
+
exit 1
|
872
|
+
end
|
873
|
+
end
|
874
|
+
|
875
|
+
def peanuts_compile(file)
|
876
|
+
unless file
|
877
|
+
puts "โ File required"
|
878
|
+
exit 1
|
879
|
+
end
|
880
|
+
|
881
|
+
unless File.exist?(file)
|
882
|
+
puts "โ File not found: #{file}"
|
883
|
+
exit 1
|
884
|
+
end
|
885
|
+
|
886
|
+
begin
|
887
|
+
content = File.read(file)
|
888
|
+
config_data = @config.parse_text_config(content)
|
889
|
+
@config.compile_to_binary(config_data, file.sub(/\.peanuts$/, '.pnt'))
|
890
|
+
puts "โ
Peanuts compiled to binary"
|
891
|
+
rescue => e
|
892
|
+
puts "โ Peanuts compilation failed: #{e.message}"
|
893
|
+
exit 1
|
894
|
+
end
|
895
|
+
end
|
896
|
+
|
897
|
+
def peanuts_auto_compile(dir = nil)
|
898
|
+
puts "๐ Auto-compiling peanuts files..."
|
899
|
+
dir ||= Dir.pwd
|
900
|
+
|
901
|
+
Dir.glob(File.join(dir, '**/*.peanuts')).each do |file|
|
902
|
+
begin
|
903
|
+
peanuts_compile(file)
|
904
|
+
rescue => e
|
905
|
+
puts "โ ๏ธ Failed to compile #{file}: #{e.message}"
|
906
|
+
end
|
907
|
+
end
|
908
|
+
|
909
|
+
puts "โ
Auto-compilation completed"
|
910
|
+
end
|
911
|
+
|
912
|
+
def peanuts_load(file)
|
913
|
+
unless file
|
914
|
+
puts "โ Binary file required"
|
915
|
+
exit 1
|
916
|
+
end
|
917
|
+
|
918
|
+
unless File.exist?(file)
|
919
|
+
puts "โ Binary file not found: #{file}"
|
920
|
+
exit 1
|
921
|
+
end
|
922
|
+
|
923
|
+
begin
|
924
|
+
config_data = @config.load_binary(file)
|
925
|
+
if @json_output
|
926
|
+
puts JSON.generate(config_data)
|
927
|
+
else
|
928
|
+
puts "โ
Peanuts binary loaded"
|
929
|
+
puts "๐ #{config_data.keys.length} sections loaded"
|
930
|
+
end
|
931
|
+
rescue => e
|
932
|
+
puts "โ Peanuts load failed: #{e.message}"
|
933
|
+
exit 1
|
934
|
+
end
|
935
|
+
end
|
936
|
+
|
937
|
+
# CSS Commands
|
938
|
+
def handle_css_command(args)
|
939
|
+
subcommand = args[0]
|
940
|
+
case subcommand
|
941
|
+
when 'expand'
|
942
|
+
css_expand(args[1], args[2])
|
943
|
+
when 'map'
|
944
|
+
css_map
|
945
|
+
else
|
946
|
+
puts "โ Unknown css command: #{subcommand}"
|
947
|
+
exit 1
|
948
|
+
end
|
949
|
+
end
|
950
|
+
|
951
|
+
def css_expand(input, output = nil)
|
952
|
+
unless input
|
953
|
+
puts "โ Input file required"
|
954
|
+
exit 1
|
955
|
+
end
|
956
|
+
|
957
|
+
unless File.exist?(input)
|
958
|
+
puts "โ Input file not found: #{input}"
|
959
|
+
exit 1
|
960
|
+
end
|
961
|
+
|
962
|
+
begin
|
963
|
+
content = File.read(input)
|
964
|
+
expanded = expand_css_shortcodes(content)
|
965
|
+
|
966
|
+
if output
|
967
|
+
File.write(output, expanded)
|
968
|
+
puts "โ
CSS expanded to: #{output}"
|
969
|
+
else
|
970
|
+
puts expanded
|
971
|
+
end
|
972
|
+
rescue => e
|
973
|
+
puts "โ CSS expansion failed: #{e.message}"
|
974
|
+
exit 1
|
975
|
+
end
|
976
|
+
end
|
977
|
+
|
978
|
+
def css_map
|
979
|
+
puts "๐ CSS Shortcode Mappings:"
|
980
|
+
mappings = [
|
981
|
+
['mh', 'max-height'],
|
982
|
+
['mw', 'max-width'],
|
983
|
+
['ph', 'padding-height'],
|
984
|
+
['pw', 'padding-width'],
|
985
|
+
['mh', 'margin-height'],
|
986
|
+
['mw', 'margin-width']
|
987
|
+
]
|
988
|
+
|
989
|
+
mappings.each do |short, full|
|
990
|
+
puts " #{short} โ #{full}"
|
991
|
+
end
|
992
|
+
end
|
993
|
+
|
994
|
+
# AI Commands
|
995
|
+
def handle_ai_command(args)
|
996
|
+
subcommand = args[0]
|
997
|
+
case subcommand
|
998
|
+
when 'claude'
|
999
|
+
ai_claude(args[1..-1].join(' '))
|
1000
|
+
when 'chatgpt'
|
1001
|
+
ai_chatgpt(args[1..-1].join(' '))
|
1002
|
+
when 'custom'
|
1003
|
+
ai_custom(args[1], args[2..-1].join(' '))
|
1004
|
+
when 'config'
|
1005
|
+
ai_config
|
1006
|
+
when 'setup'
|
1007
|
+
ai_setup
|
1008
|
+
when 'test'
|
1009
|
+
ai_test
|
1010
|
+
when 'complete'
|
1011
|
+
ai_complete(args[1], args[2], args[3])
|
1012
|
+
when 'analyze'
|
1013
|
+
ai_analyze(args[1])
|
1014
|
+
when 'optimize'
|
1015
|
+
ai_optimize(args[1])
|
1016
|
+
when 'security'
|
1017
|
+
ai_security(args[1])
|
1018
|
+
else
|
1019
|
+
puts "โ Unknown ai command: #{subcommand}"
|
1020
|
+
exit 1
|
1021
|
+
end
|
1022
|
+
end
|
1023
|
+
|
1024
|
+
def ai_claude(prompt)
|
1025
|
+
unless prompt
|
1026
|
+
puts "โ Prompt required"
|
1027
|
+
exit 1
|
1028
|
+
end
|
1029
|
+
|
1030
|
+
puts "๐ค Querying Claude..."
|
1031
|
+
# Implementation would call Claude API
|
1032
|
+
puts "๐ Response: This is a mock response from Claude"
|
1033
|
+
end
|
1034
|
+
|
1035
|
+
def ai_chatgpt(prompt)
|
1036
|
+
unless prompt
|
1037
|
+
puts "โ Prompt required"
|
1038
|
+
exit 1
|
1039
|
+
end
|
1040
|
+
|
1041
|
+
puts "๐ค Querying ChatGPT..."
|
1042
|
+
# Implementation would call ChatGPT API
|
1043
|
+
puts "๐ Response: This is a mock response from ChatGPT"
|
1044
|
+
end
|
1045
|
+
|
1046
|
+
def ai_custom(api, prompt)
|
1047
|
+
unless api && prompt
|
1048
|
+
puts "โ API endpoint and prompt required"
|
1049
|
+
exit 1
|
1050
|
+
end
|
1051
|
+
|
1052
|
+
puts "๐ค Querying custom AI API: #{api}"
|
1053
|
+
# Implementation would call custom API
|
1054
|
+
puts "๐ Response: This is a mock response from custom API"
|
1055
|
+
end
|
1056
|
+
|
1057
|
+
def ai_config
|
1058
|
+
puts "๐ AI Configuration:"
|
1059
|
+
puts " Claude API: Configured"
|
1060
|
+
puts " ChatGPT API: Configured"
|
1061
|
+
puts " Custom APIs: 0"
|
1062
|
+
end
|
1063
|
+
|
1064
|
+
def ai_setup
|
1065
|
+
puts "๐ Interactive AI API key setup..."
|
1066
|
+
puts "This would prompt for API keys and configuration"
|
1067
|
+
end
|
1068
|
+
|
1069
|
+
def ai_test
|
1070
|
+
puts "๐งช Testing AI connections..."
|
1071
|
+
puts "โ
Claude: Connected"
|
1072
|
+
puts "โ
ChatGPT: Connected"
|
1073
|
+
puts "โ
All AI services operational"
|
1074
|
+
end
|
1075
|
+
|
1076
|
+
def ai_complete(file, line = nil, column = nil)
|
1077
|
+
unless file
|
1078
|
+
puts "โ File required"
|
1079
|
+
exit 1
|
1080
|
+
end
|
1081
|
+
|
1082
|
+
puts "๐ค Getting AI-powered auto-completion..."
|
1083
|
+
# Implementation would provide code completion
|
1084
|
+
puts "๐ Completion suggestions available"
|
1085
|
+
end
|
1086
|
+
|
1087
|
+
def ai_analyze(file)
|
1088
|
+
unless file
|
1089
|
+
puts "โ File required"
|
1090
|
+
exit 1
|
1091
|
+
end
|
1092
|
+
|
1093
|
+
unless File.exist?(file)
|
1094
|
+
puts "โ File not found: #{file}"
|
1095
|
+
exit 1
|
1096
|
+
end
|
1097
|
+
|
1098
|
+
puts "๐ค Analyzing file for errors and improvements..."
|
1099
|
+
# Implementation would analyze the file
|
1100
|
+
puts "๐ Analysis complete"
|
1101
|
+
end
|
1102
|
+
|
1103
|
+
def ai_optimize(file)
|
1104
|
+
unless file
|
1105
|
+
puts "โ File required"
|
1106
|
+
exit 1
|
1107
|
+
end
|
1108
|
+
|
1109
|
+
unless File.exist?(file)
|
1110
|
+
puts "โ File not found: #{file}"
|
1111
|
+
exit 1
|
1112
|
+
end
|
1113
|
+
|
1114
|
+
puts "๐ค Getting performance optimization suggestions..."
|
1115
|
+
# Implementation would provide optimization suggestions
|
1116
|
+
puts "๐ Optimization suggestions available"
|
1117
|
+
end
|
1118
|
+
|
1119
|
+
def ai_security(file)
|
1120
|
+
unless file
|
1121
|
+
puts "โ File required"
|
1122
|
+
exit 1
|
1123
|
+
end
|
1124
|
+
|
1125
|
+
unless File.exist?(file)
|
1126
|
+
puts "โ File not found: #{file}"
|
1127
|
+
exit 1
|
1128
|
+
end
|
1129
|
+
|
1130
|
+
puts "๐ค Scanning for security vulnerabilities..."
|
1131
|
+
# Implementation would scan for security issues
|
1132
|
+
puts "๐ Security scan complete"
|
1133
|
+
end
|
1134
|
+
|
1135
|
+
# Utility Commands
|
1136
|
+
def handle_parse_command(args)
|
1137
|
+
file = args[0]
|
1138
|
+
unless file
|
1139
|
+
puts "โ File required"
|
1140
|
+
exit 1
|
1141
|
+
end
|
1142
|
+
|
1143
|
+
unless File.exist?(file)
|
1144
|
+
puts "โ File not found: #{file}"
|
1145
|
+
exit 1
|
1146
|
+
end
|
1147
|
+
|
1148
|
+
begin
|
1149
|
+
content = File.read(file)
|
1150
|
+
tsk = TuskLang::TSK.from_string(content)
|
1151
|
+
|
1152
|
+
if @json_output
|
1153
|
+
puts JSON.generate(tsk.to_hash)
|
1154
|
+
else
|
1155
|
+
puts tsk.to_s
|
1156
|
+
end
|
1157
|
+
rescue => e
|
1158
|
+
puts "โ Parse failed: #{e.message}"
|
1159
|
+
exit 1
|
1160
|
+
end
|
1161
|
+
end
|
1162
|
+
|
1163
|
+
def handle_validate_command(args)
|
1164
|
+
file = args[0]
|
1165
|
+
unless file
|
1166
|
+
puts "โ File required"
|
1167
|
+
exit 1
|
1168
|
+
end
|
1169
|
+
|
1170
|
+
unless File.exist?(file)
|
1171
|
+
puts "โ File not found: #{file}"
|
1172
|
+
exit 1
|
1173
|
+
end
|
1174
|
+
|
1175
|
+
begin
|
1176
|
+
content = File.read(file)
|
1177
|
+
TuskLang::TSK.from_string(content)
|
1178
|
+
puts "โ
File is valid TuskLang syntax"
|
1179
|
+
rescue => e
|
1180
|
+
puts "โ Validation failed: #{e.message}"
|
1181
|
+
exit 1
|
1182
|
+
end
|
1183
|
+
end
|
1184
|
+
|
1185
|
+
def handle_convert_command(args)
|
1186
|
+
input = nil
|
1187
|
+
output = nil
|
1188
|
+
|
1189
|
+
OptionParser.new do |opts|
|
1190
|
+
opts.on('-i', '--input=FILE') { |file| input = file }
|
1191
|
+
opts.on('-o', '--output=FILE') { |file| output = file }
|
1192
|
+
end.parse!(args)
|
1193
|
+
|
1194
|
+
unless input
|
1195
|
+
puts "โ Input file required (-i)"
|
1196
|
+
exit 1
|
1197
|
+
end
|
1198
|
+
|
1199
|
+
unless File.exist?(input)
|
1200
|
+
puts "โ Input file not found: #{input}"
|
1201
|
+
exit 1
|
1202
|
+
end
|
1203
|
+
|
1204
|
+
begin
|
1205
|
+
content = File.read(input)
|
1206
|
+
tsk = TuskLang::TSK.from_string(content)
|
1207
|
+
|
1208
|
+
if output
|
1209
|
+
File.write(output, tsk.to_s)
|
1210
|
+
puts "โ
Converted to: #{output}"
|
1211
|
+
else
|
1212
|
+
puts tsk.to_s
|
1213
|
+
end
|
1214
|
+
rescue => e
|
1215
|
+
puts "โ Conversion failed: #{e.message}"
|
1216
|
+
exit 1
|
1217
|
+
end
|
1218
|
+
end
|
1219
|
+
|
1220
|
+
def handle_get_command(args)
|
1221
|
+
file = args[0]
|
1222
|
+
key_path = args[1]
|
1223
|
+
|
1224
|
+
unless file && key_path
|
1225
|
+
puts "โ File and key path required"
|
1226
|
+
exit 1
|
1227
|
+
end
|
1228
|
+
|
1229
|
+
unless File.exist?(file)
|
1230
|
+
puts "โ File not found: #{file}"
|
1231
|
+
exit 1
|
1232
|
+
end
|
1233
|
+
|
1234
|
+
begin
|
1235
|
+
content = File.read(file)
|
1236
|
+
tsk = TuskLang::TSK.from_string(content)
|
1237
|
+
|
1238
|
+
# Parse key path (e.g., "section.key")
|
1239
|
+
section, key = key_path.split('.', 2)
|
1240
|
+
value = tsk.get_value(section, key)
|
1241
|
+
|
1242
|
+
puts value if value
|
1243
|
+
rescue => e
|
1244
|
+
puts "โ Get failed: #{e.message}"
|
1245
|
+
exit 1
|
1246
|
+
end
|
1247
|
+
end
|
1248
|
+
|
1249
|
+
def handle_set_command(args)
|
1250
|
+
file = args[0]
|
1251
|
+
key_path = args[1]
|
1252
|
+
value = args[2]
|
1253
|
+
|
1254
|
+
unless file && key_path && value
|
1255
|
+
puts "โ File, key path, and value required"
|
1256
|
+
exit 1
|
1257
|
+
end
|
1258
|
+
|
1259
|
+
unless File.exist?(file)
|
1260
|
+
puts "โ File not found: #{file}"
|
1261
|
+
exit 1
|
1262
|
+
end
|
1263
|
+
|
1264
|
+
begin
|
1265
|
+
content = File.read(file)
|
1266
|
+
tsk = TuskLang::TSK.from_string(content)
|
1267
|
+
|
1268
|
+
# Parse key path (e.g., "section.key")
|
1269
|
+
section, key = key_path.split('.', 2)
|
1270
|
+
tsk.set_value(section, key, value)
|
1271
|
+
|
1272
|
+
File.write(file, tsk.to_s)
|
1273
|
+
puts "โ
Value set: #{key_path} = #{value}"
|
1274
|
+
rescue => e
|
1275
|
+
puts "โ Set failed: #{e.message}"
|
1276
|
+
exit 1
|
1277
|
+
end
|
1278
|
+
end
|
1279
|
+
|
1280
|
+
# Helper methods
|
1281
|
+
def find_database_path
|
1282
|
+
@config_path || 'tusklang.db'
|
1283
|
+
end
|
1284
|
+
|
1285
|
+
def optimize_tsk_structure(data)
|
1286
|
+
# Simple optimization: remove empty sections
|
1287
|
+
data.reject { |_, section| section.nil? || section.empty? }
|
1288
|
+
end
|
1289
|
+
|
1290
|
+
def apply_optimizations(data)
|
1291
|
+
# Apply various optimizations
|
1292
|
+
data
|
1293
|
+
end
|
1294
|
+
|
1295
|
+
def generate_large_config(size)
|
1296
|
+
config = {}
|
1297
|
+
size.times do |i|
|
1298
|
+
config["section_#{i}"] = {
|
1299
|
+
"key_#{i}" => "value_#{i}",
|
1300
|
+
"number_#{i}" => i,
|
1301
|
+
"array_#{i}" => (1..10).to_a
|
1302
|
+
}
|
1303
|
+
end
|
1304
|
+
config
|
1305
|
+
end
|
1306
|
+
|
1307
|
+
def compile_to_binary(data)
|
1308
|
+
# Simple binary format for demo
|
1309
|
+
Marshal.dump(data)
|
1310
|
+
end
|
1311
|
+
|
1312
|
+
def load_from_binary(binary_data)
|
1313
|
+
Marshal.load(binary_data)
|
1314
|
+
end
|
1315
|
+
|
1316
|
+
def optimize_binary_structure(data)
|
1317
|
+
# Apply binary-specific optimizations
|
1318
|
+
data
|
1319
|
+
end
|
1320
|
+
|
1321
|
+
def expand_css_shortcodes(content)
|
1322
|
+
# Simple CSS shortcode expansion
|
1323
|
+
content.gsub(/\bmh\b/, 'max-height')
|
1324
|
+
.gsub(/\bmw\b/, 'max-width')
|
1325
|
+
.gsub(/\bph\b/, 'padding-height')
|
1326
|
+
.gsub(/\bpw\b/, 'padding-width')
|
1327
|
+
.gsub(/\bmh\b/, 'margin-height')
|
1328
|
+
.gsub(/\bmw\b/, 'margin-width')
|
1329
|
+
end
|
1330
|
+
|
1331
|
+
def show_version
|
1332
|
+
puts "TuskLang Ruby SDK v#{VERSION}"
|
1333
|
+
end
|
1334
|
+
|
1335
|
+
def show_help(command = nil)
|
1336
|
+
if command
|
1337
|
+
show_command_help(command)
|
1338
|
+
else
|
1339
|
+
show_general_help
|
1340
|
+
end
|
1341
|
+
end
|
1342
|
+
|
1343
|
+
def show_general_help
|
1344
|
+
puts <<~HELP
|
1345
|
+
๐ TuskLang Ruby SDK CLI v#{VERSION}
|
1346
|
+
======================================
|
1347
|
+
|
1348
|
+
Usage: tsk [global-options] <command> [command-options] [arguments]
|
1349
|
+
|
1350
|
+
Global Options:
|
1351
|
+
--help, -h Show help for any command
|
1352
|
+
--version, -v Show version information
|
1353
|
+
--verbose Enable verbose output
|
1354
|
+
--quiet, -q Suppress non-error output
|
1355
|
+
--config <path> Use alternate config file
|
1356
|
+
--json Output in JSON format
|
1357
|
+
|
1358
|
+
Commands:
|
1359
|
+
|
1360
|
+
๐๏ธ Database Commands:
|
1361
|
+
db status Check database connection status
|
1362
|
+
db migrate <file> Run migration file
|
1363
|
+
db console Open interactive database console
|
1364
|
+
db backup [file] Backup database
|
1365
|
+
db restore <file> Restore from backup file
|
1366
|
+
db init Initialize SQLite database
|
1367
|
+
|
1368
|
+
๐ง Development Commands:
|
1369
|
+
serve [port] Start development server (default: 8080)
|
1370
|
+
compile <file> Compile .tsk file to optimized format
|
1371
|
+
optimize <file> Optimize .tsk file for production
|
1372
|
+
|
1373
|
+
๐งช Testing Commands:
|
1374
|
+
test [suite] Run specific test suite
|
1375
|
+
test all Run all test suites
|
1376
|
+
test parser Test parser functionality only
|
1377
|
+
test fujsen Test FUJSEN operators only
|
1378
|
+
test sdk Test SDK-specific features
|
1379
|
+
test performance Run performance benchmarks
|
1380
|
+
|
1381
|
+
โ๏ธ Service Commands:
|
1382
|
+
services start Start all TuskLang services
|
1383
|
+
services stop Stop all TuskLang services
|
1384
|
+
services restart Restart all services
|
1385
|
+
services status Show status of all services
|
1386
|
+
|
1387
|
+
๐ฆ Cache Commands:
|
1388
|
+
cache clear Clear all caches
|
1389
|
+
cache status Show cache status and statistics
|
1390
|
+
cache warm Pre-warm caches
|
1391
|
+
cache memcached [subcommand] Memcached operations
|
1392
|
+
cache distributed Show distributed cache status
|
1393
|
+
|
1394
|
+
๐ฅ Configuration Commands:
|
1395
|
+
config get <key.path> [dir] Get configuration value by path
|
1396
|
+
config check [path] Check configuration hierarchy
|
1397
|
+
config validate [path] Validate entire configuration chain
|
1398
|
+
config compile [path] Auto-compile all peanu.tsk files
|
1399
|
+
config docs [path] Generate configuration documentation
|
1400
|
+
config clear-cache [path] Clear configuration cache
|
1401
|
+
config stats Show configuration performance statistics
|
1402
|
+
|
1403
|
+
๐ Binary Performance Commands:
|
1404
|
+
binary compile <file.tsk> Compile to binary format (.tskb)
|
1405
|
+
binary execute <file.tskb> Execute binary file directly
|
1406
|
+
binary benchmark <file> Compare binary vs text performance
|
1407
|
+
binary optimize <file> Optimize binary for production
|
1408
|
+
|
1409
|
+
๐ฅ Peanuts Commands:
|
1410
|
+
peanuts compile <file> Compile .peanuts to binary .pnt
|
1411
|
+
peanuts auto-compile [dir] Auto-compile all peanuts files in directory
|
1412
|
+
peanuts load <file.pnt> Load and display binary peanuts file
|
1413
|
+
|
1414
|
+
๐จ CSS Commands:
|
1415
|
+
css expand <input> [output] Expand CSS shortcodes in file
|
1416
|
+
css map Show all shortcode โ property mappings
|
1417
|
+
|
1418
|
+
๐ค AI Commands:
|
1419
|
+
ai claude <prompt> Query Claude AI with prompt
|
1420
|
+
ai chatgpt <prompt> Query ChatGPT with prompt
|
1421
|
+
ai custom <api> <prompt> Query custom AI API endpoint
|
1422
|
+
ai config Show current AI configuration
|
1423
|
+
ai setup Interactive AI API key setup
|
1424
|
+
ai test Test all configured AI connections
|
1425
|
+
ai complete <file> [line] [column] Get AI-powered auto-completion
|
1426
|
+
ai analyze <file> Analyze file for errors and improvements
|
1427
|
+
ai optimize <file> Get performance optimization suggestions
|
1428
|
+
ai security <file> Scan for security vulnerabilities
|
1429
|
+
|
1430
|
+
๐ ๏ธ Utility Commands:
|
1431
|
+
parse <file> Parse and display TSK file contents
|
1432
|
+
validate <file> Validate TSK file syntax
|
1433
|
+
convert -i <input> -o <output> Convert between formats
|
1434
|
+
get <file> <key.path> Get specific value by key path
|
1435
|
+
set <file> <key.path> <value> Set value by key path
|
1436
|
+
version Show version information
|
1437
|
+
help [command] Show help for command
|
1438
|
+
|
1439
|
+
Examples:
|
1440
|
+
tsk db status
|
1441
|
+
tsk serve 3000
|
1442
|
+
tsk compile config.tsk
|
1443
|
+
tsk test all
|
1444
|
+
tsk config get server.port
|
1445
|
+
tsk binary compile app.tsk
|
1446
|
+
tsk ai claude "Explain TuskLang"
|
1447
|
+
|
1448
|
+
For more information, visit: https://tusklang.org
|
1449
|
+
HELP
|
1450
|
+
end
|
1451
|
+
|
1452
|
+
def show_command_help(command)
|
1453
|
+
case command
|
1454
|
+
when 'db'
|
1455
|
+
puts <<~HELP
|
1456
|
+
๐๏ธ Database Commands
|
1457
|
+
===================
|
1458
|
+
|
1459
|
+
tsk db status Check database connection status
|
1460
|
+
tsk db migrate <file> Run migration file
|
1461
|
+
tsk db console Open interactive database console
|
1462
|
+
tsk db backup [file] Backup database (default: tusklang_backup_TIMESTAMP.sql)
|
1463
|
+
tsk db restore <file> Restore from backup file
|
1464
|
+
tsk db init Initialize SQLite database
|
1465
|
+
HELP
|
1466
|
+
when 'test'
|
1467
|
+
puts <<~HELP
|
1468
|
+
๐งช Testing Commands
|
1469
|
+
==================
|
1470
|
+
|
1471
|
+
tsk test [suite] Run specific test suite
|
1472
|
+
tsk test all Run all test suites
|
1473
|
+
tsk test parser Test parser functionality only
|
1474
|
+
tsk test fujsen Test FUJSEN operators only
|
1475
|
+
tsk test sdk Test SDK-specific features
|
1476
|
+
tsk test performance Run performance benchmarks
|
1477
|
+
HELP
|
1478
|
+
else
|
1479
|
+
puts "Help for command '#{command}' not available"
|
1480
|
+
end
|
1481
|
+
end
|
1482
|
+
end
|
1483
|
+
end
|
1484
|
+
|
1485
|
+
# Run CLI if this file is executed directly
|
1486
|
+
if __FILE__ == $0
|
1487
|
+
TuskLang::CLI.run(ARGV)
|
1488
|
+
end
|