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
@@ -0,0 +1,49 @@
1
+ #!/usr/local/bin/ruby
2
+ # 2011 Mahmut Bulut
3
+
4
+ # This file is part of Naksh.
5
+ #
6
+ # Naksh is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Naksh is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Naksh. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ require 'wx'
20
+ require 'naksh/interfaces/tab.rb'
21
+
22
+ module Naksh
23
+ module Interfaces
24
+ module Wxw
25
+
26
+
27
+ def Wxw.tabs
28
+ Tab.tabs
29
+ end
30
+
31
+
32
+ def Wxw.new_tab session=Naksh::Session.new, give_focus=true
33
+ current_tab=Tab.new
34
+ current_tab.textbox = Wx::TextCtrl.new(
35
+ @notebook,
36
+ "11#{current_tab.number.to_s.pad(3,'0')}".to_i(10),
37
+ 'a simple value for console '<<current_tab.number.to_s,
38
+ Wx::DEFAULT_POSITION,
39
+ Wx::DEFAULT_SIZE,
40
+ Wx::TE_MULTILINE,
41
+ Wx::DEFAULT_VALIDATOR,
42
+ "Console #{current_tab.number} TextCtrl")
43
+ @notebook.add_page current_tab.textbox,"Page #{current_tab.number}",give_focus
44
+ true
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,37 @@
1
+ #!/usr/local/bin/ruby
2
+ # 2011 Mahmut Bulut
3
+
4
+ # This file is part of Naksh.
5
+ #
6
+ # Naksh is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Naksh is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Naksh. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ require 'wx'
20
+ require 'wx_sugar'
21
+
22
+ module Naksh
23
+ module Interfaces
24
+ module Wxw
25
+
26
+ @optwin=nil
27
+
28
+
29
+ def Wxw.options
30
+ @optwin
31
+ end
32
+
33
+
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,101 @@
1
+ #!/usr/local/bin/ruby
2
+ # 2011 Mahmut Bulut
3
+
4
+ # This file is part of Naksh.
5
+ #
6
+ # Naksh is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Naksh is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Naksh. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ require 'set'
20
+ require 'pathname'
21
+
22
+
23
+ class NoGuessError<Exception
24
+ end
25
+
26
+ class Pathname
27
+ def is_nkc?
28
+ (file? and /\.nkc\.rb\z/i.match(to_s)) ? true : false
29
+ end
30
+ end
31
+
32
+
33
+ class PathEntry
34
+
35
+ def PathEntry.guess_type(location,include_subfolders=false)
36
+ raise ArgumentError unless location.kind_of? Pathname and location.exist?
37
+ if location.directory?
38
+ types=Set.new
39
+ if include_subfolders
40
+ test_files=location.descendants
41
+ else
42
+ test_files=location.children
43
+ end
44
+ test_files.each do |child|
45
+ if Pathname.new(child).is_nkc?
46
+ types<<:nkc
47
+ else
48
+ types<<:external
49
+ end
50
+ end
51
+ if types.length==2
52
+ return :mixed_dir
53
+ elsif types.include? :nkc
54
+ return :nkc_dir
55
+ elsif types.include? :external
56
+ return :external_dir
57
+ else
58
+ raise RuntimeError
59
+ end
60
+ elsif location.file?
61
+ if location.is_nkc?
62
+ return :nkc
63
+ else
64
+ return :external
65
+ end
66
+ else
67
+ raise ArgumentError,'I can\'t handle anything but files and directories'
68
+ end
69
+ raise RuntimeError,'I should have returned a value by now'
70
+ end
71
+
72
+ # location is a string representing a file path (like /home/user/Documents)
73
+ # type is either :nkc_dir,:nkc,:external_dir,:external, or :mixed_dir
74
+ def initialize(location,type=:guess,naming_convention=false,include_subfolders=false)
75
+ raise ArgumentError unless location.kind_of? String
76
+ @location=Pathname.new(location)
77
+ if type==:guess
78
+ begin
79
+ @type=PathEntry.guess_type(@location)
80
+ rescue
81
+ raise NoGuessError
82
+ end
83
+ else
84
+ raise ArgumentError unless type==:mixed_dir or type==:nkc_dir or type==:nkc or type==:external or type==:external_dir
85
+ @type=type
86
+ end
87
+ raise ArgumentError if naming_convention and not (naming_convention.kind_of? String and (@type==:external or @type==:nkc))
88
+ @naming_convention=naming_convention
89
+ @include_subfolders=include_subfolders
90
+ if not @naming_convention and @type==:nkc
91
+ @name=/\.nkc\.rb\z/.match(@location.basename).pre_match
92
+ end
93
+ end
94
+
95
+ attr_reader :location,:type,:naming_convention,:name
96
+ def include_subfolders?
97
+ @include_subfolders
98
+ end
99
+
100
+ end
101
+
@@ -0,0 +1,31 @@
1
+ #!/usr/local/bin/ruby
2
+ # 2011 Mahmut Bulut
3
+
4
+ # This file is part of Naksh.
5
+ #
6
+ # Naksh is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Naksh is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Naksh. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ def Regexp.from_perl(perl_compatible_regexp)
20
+ raise NotImplementedError
21
+ end
22
+
23
+
24
+ def Regexp.from_posix(posix_compatible_regexp)
25
+ raise NotImplementedError
26
+ end
27
+
28
+
29
+ def Regexp.from_unix_expression(unix_expr)
30
+ raise NotImplementedError
31
+ end
@@ -0,0 +1,72 @@
1
+ #!/usr/local/bin/ruby
2
+ # 2011 Mahmut Bulut
3
+
4
+ # This file is part of Naksh.
5
+ #
6
+ # Naksh is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Naksh is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Naksh. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ module Naksh
20
+
21
+ @sessions = Array.new
22
+ @current_session = nil
23
+
24
+ #an Array of all active sessions, in no significant order
25
+ # however, the order must not be changed during runtime,
26
+ # since the interfaces depend upon it
27
+ def Naksh.sessions
28
+ @sessions
29
+ end
30
+
31
+ # Only one session may be considered 'active' or 'current' at a
32
+ # given time. This could be resolved by associating each session with
33
+ # its own buffer.
34
+ def Naksh.current_session
35
+ @current_session
36
+ end
37
+ def Naksh.current_session= new_current_session
38
+ @current_session=new_current_session
39
+ end
40
+
41
+ #an a subclass of Array which represents a record of entered scripts
42
+ class Session
43
+
44
+
45
+ def initialize(history=History.new,vars=Hash.new)
46
+ @history = history
47
+ @vars = vars
48
+ @id=Naksh.sessions.length
49
+ Naksh.sessions<<self
50
+ Naksh.current_session=self unless Naksh.current_session
51
+ super()
52
+ end
53
+
54
+
55
+ attr_accessor :history,:vars
56
+ attr_reader :id
57
+
58
+ # two Sessions are == if and only if their history and vars are ==
59
+ def == other_session
60
+ return false unless other_session.kind_of? self.class
61
+ return false unless other_session.history==history
62
+ return false unless other_session.vars== vars
63
+ true
64
+ end
65
+
66
+ def fork
67
+ Session.new history,vars
68
+ end
69
+
70
+
71
+ end
72
+ end
@@ -0,0 +1,48 @@
1
+ #!/usr/local/bin/ruby
2
+ # 2011 Mahmut Bulut
3
+
4
+ # This file is part of Naksh.
5
+ #
6
+ # Naksh is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Naksh is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Naksh. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ def Regexp.join(re_list,preserve_options=true)
20
+ raise ArgumentError,"Regexp.join: 1st argument should be an array #{re_list}" unless re_list.respond_to? :collect and re_list.respond_to? :join
21
+ re_list.collect! do |re|
22
+ re= Regexp.new(Regexp.escape(re)) if re.kind_of? String
23
+ re= Regexp.new(re) unless re.kind_of? Regexp
24
+ preserve_options ? re.to_s : '(?:'<<re.source<<')'
25
+ end
26
+ Regexp.compile(re_list.join('').gsub(/\(\?[\w\-]*\:\)/,''))
27
+ end
28
+
29
+
30
+ class Regexp
31
+ def +(other)
32
+ Regexp.join([self,other],false)
33
+ end
34
+ end
35
+
36
+
37
+
38
+ class String
39
+
40
+ #str.pad(minimum_length,str_to_pad_with=' ')
41
+ #return self if length>minimum_length
42
+ def pad(m,d=' ')
43
+ f = m-length
44
+ return self if f<0
45
+ (d*(f/(d.length*1.0)).ceil)[0,f]<< self
46
+ end
47
+
48
+ end
@@ -0,0 +1,57 @@
1
+ #!/usr/local/bin/ruby
2
+ # 2011 Mahmut Bulut
3
+
4
+ # This file is part of Naksh.
5
+ #
6
+ # Naksh is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Naksh is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Naksh. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ module Naksh
20
+
21
+ # REQUIRED METHODS
22
+ # Naksh.syntax.execute
23
+ # Naksh.syntax.try_execute
24
+ # Naksh.syntax.complete?
25
+
26
+ #these are the interpreters
27
+ #they take input and send commands
28
+ #could perform some non-standard commands like basic arithmatic
29
+ module Syntax
30
+
31
+
32
+ # a parse error is sent by the syntax parser when the script
33
+ # doesn't conform with the grammar.
34
+ class ParseError<StandardError
35
+ include Naksh::NonCriticalError
36
+ end
37
+
38
+ end
39
+
40
+ @syntax = nil
41
+
42
+
43
+ # set the current syntax ruleset
44
+ # currently no way to combine syntax rulesets except by method overwriting
45
+ # eg., you could define a command `ren' which joins it's arguments and
46
+ # executes them with the Ren interpreter
47
+ def Naksh.syntax=(new_syntax)
48
+ @syntax=new_syntax
49
+ end
50
+
51
+
52
+ def Naksh.syntax
53
+ @syntax
54
+ end
55
+
56
+
57
+ end
@@ -0,0 +1,219 @@
1
+ #!/usr/local/bin/ruby
2
+ # 2011 Mahmut Bulut, thefed, and Antonio Salazar
3
+
4
+ # This file is part of Naksh.
5
+ #
6
+ # Naksh is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Naksh is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Naksh. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ require 'gettext'
20
+
21
+ module Naksh
22
+ module Syntax
23
+ module Bash
24
+
25
+ #executes a script
26
+ #entrance point
27
+ def Bash.execute script_str
28
+
29
+ #keeps output from commands from showing on the command line
30
+ Naksh.buffer.silence
31
+
32
+ #splits at ';'
33
+ Bash.split_script(Bash.clean_script(script_str)).each do |pipeline|
34
+
35
+ #splits at '|'
36
+ pipeline = Bash.split_pipeline(Bash.clean_pipeline(pipeline))
37
+ pipeline.each_index do |i|
38
+
39
+ #allow direct output if this is the last commmand in the pipeline
40
+ Naksh.buffer.speak if i==pipeline.length-1
41
+
42
+ #split into [command_name,['array','of','space',"separated arguments"]]
43
+ d = Bash.split_command(Bash.clean_command(pipeline[i]))
44
+
45
+ #send command unless the command is all whitespace or something silly
46
+ Naksh.send_command(*d) if d
47
+
48
+ #tell the buffer another command is about to begin
49
+ Naksh.buffer.next unless i==pipeline.length-1
50
+
51
+ end
52
+ end
53
+ true
54
+ end
55
+
56
+
57
+
58
+ # may return false if the script is syntactically incomplete
59
+ # see Bash.try_execute
60
+ def Bash.complete? script_str
61
+ true
62
+ end
63
+
64
+
65
+ # If it can successfully parse the script, it will do so as if
66
+ # you called Bash.execute, and it will return true.
67
+ # If it cannot parse the script, it will either
68
+ # raise a ParseError, as if you called Bash.execute, or
69
+ # return false, indicating that it believes further input is
70
+ # expected.
71
+
72
+ # The basic use case for complete? and try_execute is an unclosed
73
+ # quote
74
+
75
+ # A Naksh syntax module is NOT required to use complete? or
76
+ # try_execute, but it is recommended that is use one of them
77
+
78
+ def Bash.try_execute script_str
79
+ Bash.execute script_str
80
+ true
81
+ end
82
+
83
+
84
+
85
+
86
+ #should call any tidying methods helpful to other steps
87
+ #currently just removes comments
88
+ def Bash.clean_script(script_str)
89
+ Bash.remove_comments(script_str)
90
+ end
91
+
92
+
93
+ #should remove all comments from script
94
+ def Bash.remove_comments(script_str)
95
+ loop do
96
+ start=Bash.find_unescaped_nonstring(script_str,'#')
97
+ return script_str unless start
98
+ close=Bash.find_unescaped_nonstring(script_str,"\n",start)
99
+ return script_str[0..start-1] unless close
100
+ script_str=script_str[0..start-1]<<script_str[close+1..script_str.length]
101
+ end
102
+ end
103
+
104
+
105
+ #splits a script into wholly independant segments
106
+ def Bash.split_script(str)
107
+ Bash.split_unescaped(str,';')
108
+ end
109
+
110
+
111
+ #should call any tidying methods helpful to other steps
112
+ #currently returns input
113
+ def Bash.clean_pipeline(pipe_str)
114
+ pipe_str
115
+ end
116
+
117
+
118
+ #separate commands in a pipeline
119
+ def Bash.split_pipeline(str)
120
+ Bash.split_unescaped(str,'|')
121
+ end
122
+
123
+
124
+ #prepares for Bash.split_command
125
+ #by unifying syntax variations
126
+ #removing excess whitespace, etc
127
+
128
+ #it wraps the actual command in single quotes
129
+ def Bash.clean_command(com_str)
130
+
131
+ #remove leading whitespace
132
+ com_str.sub!(/\A\s+/,'')
133
+
134
+ #need to evaluate variables before this
135
+ com_str.sub!(/\A'([^']+)'(\S*)/,'\'\1\2\'')
136
+ com_str.sub!(/\A"([^"]+)"(\S*)/,'\'\1\2\'')
137
+ com_str.sub!(/\A(\S+)/,'\'\1\'')
138
+
139
+ #I think this section may be useless, not belong here, etc.
140
+ invalid_starting_characters=%w[; | #]
141
+ invalid_starting_characters.each do |chr|
142
+ if (/^/+chr).match(com_str)
143
+ raise ParseError,_('commands cannot begin with the following character: %s')%[chr]
144
+ end
145
+ end
146
+
147
+ com_str
148
+ end
149
+
150
+
151
+ #I couldn't make a good regexp version, but THIS WORKS
152
+ #takes into account escaping (\) and quotation ("')
153
+ def Bash.find_unescaped_nonstring(str,search_char,starting_index=0)
154
+ search_char=search_char.chr if search_char.kind_of? Integer
155
+ raise ArgumentError,"Naksh::Syntax::Bash.find_unescaped_nonstring(#{re.inspect},#{str.inspect})" unless search_char.kind_of? String and str.kind_of? String and search_char.length==1 and starting_index.kind_of? Integer
156
+ return nil if str.length<=starting_index
157
+ escaped=false
158
+ string_open=false
159
+ starting_index.upto str.length-1 do |i|
160
+ next if i<starting_index
161
+ if str[i].chr==search_char
162
+ return i unless escaped or string_open
163
+ elsif str[i].chr=="\\"
164
+ escaped=!escaped
165
+ elsif not escaped and str[i].chr=='\''
166
+ case string_open
167
+ when false
168
+ string_open='\''
169
+ when '\''
170
+ string_open=false
171
+ end
172
+ elsif not escaped and str[i].chr=='"'
173
+ case string_open
174
+ when false
175
+ string_open='"'
176
+ when '"'
177
+ string_open=false
178
+ end
179
+ else
180
+ escaped=false
181
+ end
182
+ end
183
+ #Regexp requires zero-width negative lookbehind
184
+ #/\A(([^\\](\\\\)*)(("[^"]*")|('[^']*'))*/<<re
185
+ nil
186
+ end
187
+
188
+
189
+ def Bash.split_command(com_str)
190
+ return false if not com_str or com_str.empty?
191
+ com_arr=Bash.split_unescaped(com_str,' ')
192
+ com_arr=[com_str,[]] unless com_arr
193
+ raise RuntimeError,'single quotes should have been added around command earlier in processing'<<"\ncommand as recieved = #{com_str.inspect}, class=#{com_str.class}" unless /\A'.*'\z/.match(com_arr[0])
194
+ com_arr[0].replace(com_arr[0][1,com_arr[0].length-2])
195
+ [com_arr[0],com_arr[1,com_arr.length]]
196
+ end
197
+
198
+
199
+
200
+ #returns an Array of Strings,
201
+ #made of str split at every unescaped instance of char
202
+ #not enclosed in an unescaped string delimiter ('")
203
+ def Bash.split_unescaped(str,char)
204
+ result=[]
205
+ split_index=0
206
+ loop do
207
+ split_index=Bash.find_unescaped_nonstring(str,char)
208
+ return result<<str unless split_index
209
+ result<<str[0,split_index] unless split_index.zero?
210
+ str=str[split_index+1,str.length]
211
+ return result if str.empty?
212
+ end
213
+ end
214
+
215
+
216
+
217
+ end
218
+ end
219
+ end