naksh 0.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.
Files changed (137) hide show
  1. data/AUTHORS +1 -0
  2. data/COPYING +674 -0
  3. data/COPYING-DOCS +15 -0
  4. data/README.md +45 -0
  5. data/Rakefile +129 -0
  6. data/TODO +19 -0
  7. data/bin/naksh +2 -0
  8. data/data/default.mo +0 -0
  9. data/data/default.po +16 -0
  10. data/data/default2.mo +0 -0
  11. data/data/default2.po +27 -0
  12. data/data/starter.pot +29 -0
  13. data/docs/bash_flow.dia +0 -0
  14. data/docs/gtk_manual.txt +13 -0
  15. data/docs/master_plan.dia +0 -0
  16. data/docs/master_plan.png +0 -0
  17. data/docs/master_plan.svg +74 -0
  18. data/docs/master_plan.svgz +0 -0
  19. data/docs/userguide/en/about.xml +42 -0
  20. data/docs/userguide/en/gnu-fdl-1.2.xml +543 -0
  21. data/docs/userguide/en/naksh.xml +881 -0
  22. data/docs/userguide/en/naksh_start_window.png +0 -0
  23. data/docs/userguide/en/old_naksh.xml +180 -0
  24. data/docs/userguide/en/userguide-en.omf +37 -0
  25. data/lib/naksh.rb +165 -0
  26. data/lib/naksh/buffer.rb +153 -0
  27. data/lib/naksh/command_handling.rb +117 -0
  28. data/lib/naksh/commands/bash/README +2 -0
  29. data/lib/naksh/commands/bash/echo.nkc.rb +50 -0
  30. data/lib/naksh/commands/bsd.rb +25 -0
  31. data/lib/naksh/commands/dos.rb +25 -0
  32. data/lib/naksh/commands/fuse.rb +25 -0
  33. data/lib/naksh/commands/gnu.rb +30 -0
  34. data/lib/naksh/commands/gnu/README +2 -0
  35. data/lib/naksh/commands/gnu/cat.nkc.rb +50 -0
  36. data/lib/naksh/commands/gnu/cd.nkc.rb +11 -0
  37. data/lib/naksh/commands/gnu/echo.documentation.json +57 -0
  38. data/lib/naksh/commands/gnu/echo.documentation.rb +60 -0
  39. data/lib/naksh/commands/gnu/echo.nkc.rb +52 -0
  40. data/lib/naksh/commands/gnu/ls.nkc.rb +11 -0
  41. data/lib/naksh/commands/gnu/mv.nkc.rb +15 -0
  42. data/lib/naksh/commands/gnu/pwd.nkc.rb +11 -0
  43. data/lib/naksh/commands/naksh/addpath.nkc.rb +15 -0
  44. data/lib/naksh/commands/naksh/broken.nkc.rb +10 -0
  45. data/lib/naksh/commands/naksh/empty.nkc.rb +4 -0
  46. data/lib/naksh/commands/naksh/exit.nkc.rb +10 -0
  47. data/lib/naksh/commands/naksh/help.nkc.rb +21 -0
  48. data/lib/naksh/commands/naksh/man.nkc.rb +8 -0
  49. data/lib/naksh/commands/ruby.rb +31 -0
  50. data/lib/naksh/commands/unix.rb +131 -0
  51. data/lib/naksh/configuration/gconf.rb +51 -0
  52. data/lib/naksh/configuration/hash.rb +38 -0
  53. data/lib/naksh/defaults.rb +40 -0
  54. data/lib/naksh/history.rb +85 -0
  55. data/lib/naksh/interfaces.rb +59 -0
  56. data/lib/naksh/interfaces/fox.rb +49 -0
  57. data/lib/naksh/interfaces/gtk.rb +103 -0
  58. data/lib/naksh/interfaces/gtk/abtwin.rb +53 -0
  59. data/lib/naksh/interfaces/gtk/gnomeapp.rb +31 -0
  60. data/lib/naksh/interfaces/gtk/helpwin.rb +70 -0
  61. data/lib/naksh/interfaces/gtk/io.rb +94 -0
  62. data/lib/naksh/interfaces/gtk/mainwin.rb +56 -0
  63. data/lib/naksh/interfaces/gtk/mainwin/console.rb +121 -0
  64. data/lib/naksh/interfaces/gtk/mainwin/main_menu.rb +143 -0
  65. data/lib/naksh/interfaces/gtk/optwin.rb +78 -0
  66. data/lib/naksh/interfaces/tab.rb +58 -0
  67. data/lib/naksh/interfaces/wxw.rb +75 -0
  68. data/lib/naksh/interfaces/wxw/abtwin.rb +38 -0
  69. data/lib/naksh/interfaces/wxw/helpwin.rb +40 -0
  70. data/lib/naksh/interfaces/wxw/io.rb +61 -0
  71. data/lib/naksh/interfaces/wxw/mainwin.rb +42 -0
  72. data/lib/naksh/interfaces/wxw/mainwin/main_menu.rb +126 -0
  73. data/lib/naksh/interfaces/wxw/mainwin/sessions.rb +49 -0
  74. data/lib/naksh/interfaces/wxw/optwin.rb +37 -0
  75. data/lib/naksh/path_entry.rb +101 -0
  76. data/lib/naksh/regexp.rb +31 -0
  77. data/lib/naksh/session.rb +72 -0
  78. data/lib/naksh/stdlibext.rb +48 -0
  79. data/lib/naksh/syntax.rb +57 -0
  80. data/lib/naksh/syntax/bash.rb +219 -0
  81. data/lib/naksh/syntax/bash/antlr/bottomup.g +24 -0
  82. data/lib/naksh/syntax/bash/antlr/topdown.g +52 -0
  83. data/lib/naksh/syntax/bash/dhaka/evaluator.rb +353 -0
  84. data/lib/naksh/syntax/bash/dhaka/grammar.rb +71 -0
  85. data/lib/naksh/syntax/bash/dhaka/lexer.rb +52 -0
  86. data/lib/naksh/syntax/bash/treetop/bash.treetop +17 -0
  87. data/lib/old/abbr_call.rb +39 -0
  88. data/lib/old/autocomplete.rb +29 -0
  89. data/lib/old/command.rb +106 -0
  90. data/lib/old/command_holder.rb +75 -0
  91. data/lib/old/commands.rb +24 -0
  92. data/lib/old/old_executor.rb +95 -0
  93. data/lib/old/options.rb +31 -0
  94. data/lib/old/rush.rb +113 -0
  95. data/lib/old/sortissimo.rb +205 -0
  96. data/lib/old/systems.rb +25 -0
  97. data/lib/old/systems/ruby.rb +26 -0
  98. data/lib/old/un.rb +240 -0
  99. data/lib/rust/Rakefile +6 -0
  100. data/lib/rust/commands/builtins.rb +46 -0
  101. data/lib/rust/commands/builtins/cd.rb +17 -0
  102. data/lib/rust/commands/builtins/exit.rb +13 -0
  103. data/lib/rust/commands/builtins/help.rb +14 -0
  104. data/lib/rust/commands/builtins/parser.rb +13 -0
  105. data/lib/rust/commands/builtins/pwd.rb +13 -0
  106. data/lib/rust/commands/builtins/type.rb +13 -0
  107. data/lib/rust/commands/commands/ls.rb +13 -0
  108. data/lib/rust/commands/commands/read.rb +13 -0
  109. data/lib/rust/commands/commands/rm.rb +14 -0
  110. data/lib/rust/commands/commands/test.rb +20 -0
  111. data/lib/rust/helpers/array.rb +10 -0
  112. data/lib/rust/helpers/command_center.rb +78 -0
  113. data/lib/rust/helpers/constants.rb +58 -0
  114. data/lib/rust/helpers/io.rb +132 -0
  115. data/lib/rust/helpers/parser.rb +45 -0
  116. data/lib/rust/helpers/rush_control.rb +40 -0
  117. data/lib/rust/helpers/string.rb +50 -0
  118. data/lib/rust/helpers/trollop.rb +475 -0
  119. data/lib/rust/parsers/bash.rb +220 -0
  120. data/lib/rust/parsers/bash/stdlibext.rb +32 -0
  121. data/lib/rust/parsers/ren.rb +57 -0
  122. data/lib/rust/rust.rb +75 -0
  123. data/lib/rust/syntax/command.rb +23 -0
  124. data/lib/rust/syntax/paths.rb +31 -0
  125. data/lib/rust/syntax/pipes.rb +148 -0
  126. data/naksh.gemspec +55 -0
  127. data/test/naksh/arg_parser.rspec.rb +27 -0
  128. data/test/naksh/commands/bash/echo.rspec.rb +32 -0
  129. data/test/naksh/commands/sortlist +127 -0
  130. data/test/naksh/external_command.rspec.rb +46 -0
  131. data/test/naksh/send_error.rspec.rb +60 -0
  132. data/test/naksh/suggest.rspec.rb +38 -0
  133. data/test/naksh/syntax/bash.rspec.rb +69 -0
  134. data/test/naksh/syntax/bash/execute.rspec.rb +51 -0
  135. data/test/naksh/syntax/rspec.rb +63 -0
  136. data/test/run_rspecs.rb +20 -0
  137. metadata +217 -0
data/lib/rust/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ task :package do |t|
2
+ Dir.chdir('..')
3
+ a = Time.now.strftime("%m-%d-%Y")
4
+ sh "tar -cf ~/Desktop/rust-#{a}.tar new_lib/"
5
+ sh "tar -xf ~/Desktop/rust-#{a}.tar"
6
+ end
@@ -0,0 +1,46 @@
1
+ #!/usr/local/bin/ruby
2
+ #
3
+ # Created by me on 2011-12-16.
4
+ # Copyright (c) 2011. All pwnage reserved.
5
+
6
+ module BuiltinCommands
7
+ class << self
8
+ def register cmd
9
+ @@commands ||= []
10
+ @@commands << cmd
11
+ end
12
+
13
+ def register_builtin cmd
14
+ @@builtins ||= []
15
+ @@builtins << cmd
16
+ end
17
+
18
+ def builtins
19
+ @@builtins
20
+ end
21
+
22
+ def commands
23
+ @@commands
24
+ end
25
+ end
26
+ end
27
+
28
+ Dir[File.join(File.dirname(__FILE__), 'builtins/*')].each {|l| require l }
29
+ Dir[File.join(File.dirname(__FILE__), 'commands/*')].each {|l| require l }
30
+
31
+ module Kernel
32
+ include BuiltinCommands
33
+
34
+ def builtins
35
+ BuiltinCommands.builtins
36
+ end
37
+ alias_method :internals, :builtins
38
+
39
+ def builtin_commands
40
+ BuiltinCommands.commands
41
+ end
42
+
43
+ def add(sym)
44
+ BuiltinCommands.register(sym)
45
+ end
46
+ end
@@ -0,0 +1,17 @@
1
+ #!/usr/local/bin/ruby
2
+ #
3
+ # Created by me on 2011-12-16.
4
+ # Copyright (c) 2011. All pwnage reserved.
5
+
6
+ module BuiltinCommands
7
+ def cd *args
8
+ (err "Too Many Arguments - Try only one"; return) if args.size > 1
9
+ directory = args[0] ? args[0] : ENV['HOME']
10
+ (directory = File.join(Dir.pwd, directory)) unless directory[0].chr =~ /\//
11
+
12
+ Dir.chdir directory
13
+ puts("Changing to #{directory}")
14
+ end
15
+ register_builtin :cd
16
+
17
+ end
@@ -0,0 +1,13 @@
1
+ #!/usr/local/bin/ruby
2
+ #
3
+ # Created by me on 2011-12-26.
4
+ # Copyright (c) 2011. All pwnage reserved.
5
+
6
+ module BuiltinCommands
7
+
8
+ def exit *args
9
+ Kernel.exit
10
+ end
11
+ register_builtin :exit
12
+
13
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/local/bin/ruby
2
+ #
3
+ # Created by me on 2011-12-26.
4
+ # Copyright (c) 2011. All pwnage reserved.
5
+
6
+ module BuiltinCommands
7
+
8
+ def help *args
9
+ puts "INTERNAL COMMANDS"
10
+ puts(builtins.join(', '))
11
+ end
12
+ register_builtin :help
13
+
14
+ end
@@ -0,0 +1,13 @@
1
+ #!/usr/local/bin/ruby
2
+ #
3
+ # Created by me on 2011-12-26.
4
+ # Copyright (c) 2011. All pwnage reserved.
5
+
6
+ module BuiltinCommands
7
+
8
+ def parser *args
9
+ puts($parser)
10
+ end
11
+ register_builtin :parser
12
+
13
+ end
@@ -0,0 +1,13 @@
1
+ #!/usr/local/bin/ruby
2
+ #
3
+ # Created by me on 2011-12-21.
4
+ # Copyright (c) 2011. All pwnage reserved.
5
+
6
+ module BuiltinCommands
7
+
8
+ def pwd *args
9
+ puts(Dir.pwd)
10
+ end
11
+ register_builtin :pwd
12
+
13
+ end
@@ -0,0 +1,13 @@
1
+ #!/usr/local/bin/ruby
2
+ #
3
+ # Created by me on 2011-12-16.
4
+ # Copyright (c) 2011. All pwnage reserved.
5
+
6
+ module BuiltinCommands
7
+
8
+ def type *args
9
+ puts("type")
10
+ end
11
+ register_builtin :type
12
+
13
+ end
@@ -0,0 +1,13 @@
1
+ #!/usr/local/bin/ruby
2
+ #
3
+ # Created by me on 2011-12-26.
4
+ # Copyright (c) 2011. All pwnage reserved.
5
+
6
+ module BuiltinCommands
7
+
8
+ def ls *args
9
+ puts(Dir['*'])
10
+ end
11
+ register :ls
12
+
13
+ end
@@ -0,0 +1,13 @@
1
+ #!/usr/local/bin/ruby
2
+ #
3
+ # Created by me on 2011-12-26.
4
+ # Copyright (c) 2011. All pwnage reserved.
5
+
6
+ module BuiltinCommands
7
+
8
+ def read *args
9
+ puts(open(args[0], "r").read)
10
+ end
11
+ register :read
12
+
13
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/local/bin/ruby
2
+ #
3
+ # Created by me on 2011-12-26.
4
+ # Copyright (c) 2011. All pwnage reserved.
5
+
6
+
7
+ module BuiltinCommands
8
+
9
+ def rm *args
10
+ puts('rm')
11
+ end
12
+ register :rm
13
+
14
+ end
@@ -0,0 +1,20 @@
1
+ #!/usr/local/bin/ruby
2
+ #
3
+ # Created by me on 2011-12-26.
4
+ # Copyright (c) 2011. All pwnage reserved.
5
+
6
+ module BuiltinCommands
7
+
8
+ def test *args
9
+ opts = Trollop::options(args) do
10
+ opt :verbose, "Be as loud as possible"
11
+ opt :out, "Where to save the file", :type => String
12
+ opt :threads, "Set number of threads to use", :default => 5
13
+ end
14
+
15
+ opts[:in] = args[0]
16
+ p opts
17
+ end
18
+ register :test
19
+
20
+ end
@@ -0,0 +1,10 @@
1
+ #!/usr/local/bin/ruby
2
+ #
3
+ # Created by me on 2011-12-21.
4
+ # Copyright (c) 2011. All pwnage reserved.
5
+
6
+ class Array
7
+ def string
8
+ self.map {|l| "'#{l}'" }
9
+ end
10
+ end
@@ -0,0 +1,78 @@
1
+ #!/usr/local/bin/ruby
2
+ #
3
+ # Created by me on 2011-12-17.
4
+ # Copyright (c) 2011. All pwnage reserved.
5
+
6
+ module CommandCenter
7
+ # This is the module where
8
+ # the commands will be evaluated
9
+ # it's good, because it is a nice
10
+ # pure area to do so.
11
+
12
+ ############################
13
+ # USAGE
14
+ #######
15
+ # used by Pipes:Module
16
+ #######
17
+ # CommandCenter.run(args)
18
+ ############################
19
+
20
+ # include the builtin commands
21
+ # by being a part of Kernel:Module
22
+ # (see commands/builtins.rb)
23
+ # and actually requiring the command files
24
+ # within the class << self
25
+
26
+ class << self
27
+ include BuiltinCommands
28
+
29
+ #######
30
+ # is the default command runner
31
+ def run_standard args_as_string
32
+ args = Shellwords.shellwords(args_as_string) # nice little builtin parser
33
+ cmd = args.shift # the command name
34
+
35
+ if builtin_commands.include? cmd.to_sym # self explanatory
36
+ eval(cmd + (args.size > 0 ? args.string.join(', ') : ''))
37
+ # unbinding and binding methods
38
+ # ---> # PLUS it will work with straight ruby!!!! (Not supported yet)
39
+ else # ELSE # it's NOT a builtin command
40
+ exec(cmd, args.join(' ')) # run it like it's highschool XC
41
+ end
42
+ rescue => e
43
+ raise e
44
+ end
45
+
46
+ def run_as_builtin(args)
47
+ arr = args.split(' ')
48
+ cmd = arr.shift
49
+ if builtin_commands.include? cmd.to_sym
50
+ eval(cmd + ' ' + (arr.size > 0 ? arr.string.join(', ') : ''))
51
+ else
52
+ false
53
+ end
54
+ end
55
+
56
+ def run_as_internal(args)
57
+ arr = args.split(' ')
58
+ cmd = arr.shift
59
+ if builtins.include? cmd.to_sym
60
+ # p (cmd + (arr.size > 0 ? ' ' + arr.string.join(', ') : '()'))
61
+ eval(cmd + (arr.size > 0 ? ' ' + arr.string.join(', ') : '()'))
62
+ else
63
+ false
64
+ end
65
+ end
66
+
67
+ def run_as_ruby(line)
68
+ eval(line)
69
+ end
70
+
71
+ def run_as_command(*args)
72
+ cmd = args.shift
73
+ exec(::Paths.find_path(cmd), args.join(' '))
74
+ end
75
+
76
+ end
77
+
78
+ end
@@ -0,0 +1,58 @@
1
+ #!/usr/local/bin/ruby
2
+ #
3
+ # Created by me on 2011-12-07.
4
+ # Copyright (c) 2011. All pwnage reserved.
5
+
6
+ ERASE_CHAR = "\e[P"
7
+
8
+ # Did I mention this is ripped from JEG2's HighLine
9
+
10
+ CLEAR = "\e[0m"
11
+ # The start of an ANSI bold sequence.
12
+ BOLD = "\e[1m"
13
+ # The start of an ANSI dark sequence. (Terminal support uncommon.)
14
+ DARK = "\e[2m"
15
+ # The start of an ANSI underline sequence.
16
+ UNDERLINE = "\e[4m"
17
+ # An alias for UNDERLINE.
18
+ UNDERSCORE = UNDERLINE
19
+ # The start of an ANSI blink sequence. (Terminal support uncommon.)
20
+ BLINK = "\e[5m"
21
+ # The start of an ANSI reverse sequence.
22
+ REVERSE = "\e[7m"
23
+ # The start of an ANSI concealed sequence. (Terminal support uncommon.)
24
+ CONCEALED = "\e[8m"
25
+
26
+ # Set the terminal's foreground ANSI color to black.
27
+ BLACK = "\e[30m"
28
+ # Set the terminal's foreground ANSI color to red.
29
+ RED = "\e[31m"
30
+ # Set the terminal's foreground ANSI color to green.
31
+ GREEN = "\e[32m"
32
+ # Set the terminal's foreground ANSI color to yellow.
33
+ YELLOW = "\e[33m"
34
+ # Set the terminal's foreground ANSI color to blue.
35
+ BLUE = "\e[34m"
36
+ # Set the terminal's foreground ANSI color to magenta.
37
+ MAGENTA = "\e[35m"
38
+ # Set the terminal's foreground ANSI color to cyan.
39
+ CYAN = "\e[36m"
40
+ # Set the terminal's foreground ANSI color to white.
41
+ WHITE = "\e[37m"
42
+
43
+ # Set the terminal's background ANSI color to black.
44
+ ON_BLACK = "\e[40m"
45
+ # Set the terminal's background ANSI color to red.
46
+ ON_RED = "\e[41m"
47
+ # Set the terminal's background ANSI color to green.
48
+ ON_GREEN = "\e[42m"
49
+ # Set the terminal's background ANSI color to yellow.
50
+ ON_YELLOW = "\e[43m"
51
+ # Set the terminal's background ANSI color to blue.
52
+ ON_BLUE = "\e[44m"
53
+ # Set the terminal's background ANSI color to magenta.
54
+ ON_MAGENTA = "\e[45m"
55
+ # Set the terminal's background ANSI color to cyan.
56
+ ON_CYAN = "\e[46m"
57
+ # Set the terminal's background ANSI color to white.
58
+ ON_WHITE = "\e[47m"
@@ -0,0 +1,132 @@
1
+ #!/usr/local/bin/ruby
2
+ #
3
+ # Created by me on 2011-12-13.
4
+ # Copyright (c) 2011. All pwnage reserved.
5
+
6
+ class InOut
7
+ attr_accessor :line, :backspace_limit
8
+
9
+ def initialize(stdin=STDIN, stdout=STDOUT, stderr=STDERR, keys={})
10
+ @in = stdin
11
+ @out = stdout
12
+ @err = stderr
13
+ @keys = keys
14
+ end
15
+
16
+ def tell(text)
17
+ @out.print(text)
18
+ @out.flush
19
+ end
20
+
21
+ ###
22
+ # Stolen from HighLine (by James Edward Grey II and Greg Brown)
23
+ def say(text)
24
+ @out.puts(text)
25
+ @out.flush
26
+ end
27
+
28
+ def ask(something)
29
+ @line = ''
30
+ @backspace_limit = 0
31
+ tell something
32
+
33
+ while character = get_character()
34
+ # check for special keystrokes
35
+ (@keys[character].call; next) if @keys[character]
36
+ # honor backspace and delete
37
+ if character == 127 or character == 8
38
+ @line.slice!(-1, 1)
39
+ @backspace_limit -= 1
40
+
41
+ # Respect tab
42
+ # elsif character == 9
43
+
44
+ else
45
+ @line << character.chr
46
+ @backspace_limit = @line.size
47
+ end
48
+ # looking for carriage return (decimal 13) or
49
+ # newline (decimal 10) in raw input
50
+ break if character == 13 or character == 10
51
+ if character == 127 or character == 8
52
+ # only backspace if we have characters on the line to
53
+ # eliminate, otherwise we'll tromp over the prompt
54
+ if @backspace_limit >= 0 then
55
+ @out.print("\b#{ERASE_CHAR}")
56
+ else
57
+ # do nothing
58
+ end
59
+ else
60
+ @out.print(character.chr)
61
+ end
62
+ @out.flush
63
+ end
64
+ @out.print "\n"
65
+ return @line
66
+ end
67
+
68
+ def err(txt, exception=nil)
69
+ if exception.nil?
70
+ @out.puts("Unexpected error - #{txt}")
71
+ else
72
+ @out.puts("#{txt}\n#{exception.class}: #{exception.message}\n#{exception.backtrace.map {|l| " #{l}\n"}}")
73
+ end
74
+ @out.flush
75
+ end
76
+
77
+ ####
78
+ # Silence him!
79
+ def silence
80
+ @old_in, @old_out, @old_err = @in, @out, @err
81
+ @in, @out, @err = StringIO.new, StringIO.new, StringIO.new
82
+ @silenced = true
83
+ end
84
+
85
+ def silenced?()
86
+ @silenced
87
+ end
88
+
89
+ ####
90
+ # It's cool. He can talk now
91
+ # and we'll set the old stuff to DEAD
92
+ def speak
93
+ @silenced = false
94
+ @in, @out, @err = @old_in, @old_out, @old_err
95
+ [@old_in, @old_out, @old_err].each {|var| }
96
+ end
97
+
98
+ end
99
+
100
+ module Kernel
101
+
102
+ # To be used by any parsers
103
+ # for _all_ I/O
104
+
105
+ def ask(*arr)
106
+ Rust.io.ask(*arr)
107
+ end
108
+
109
+ def tell(*arr)
110
+ Rust.io.tell(*arr)
111
+ end
112
+
113
+ def err(*arr)
114
+ Rust.io.err(*arr)
115
+ end
116
+
117
+ def say(*arr)
118
+ Rust.io.say(*arr)
119
+ end
120
+
121
+ def color( string, *colors )
122
+ colors.map! do |c|
123
+ if c.is_a? Symbol
124
+ self.class.const_get(c.to_s.upcase)
125
+ else
126
+ c
127
+ end
128
+ end
129
+ "#{colors.flatten.join}#{string}#{CLEAR}"
130
+ end
131
+
132
+ end