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.
- data/AUTHORS +1 -0
- data/COPYING +674 -0
- data/COPYING-DOCS +15 -0
- data/README.md +45 -0
- data/Rakefile +129 -0
- data/TODO +19 -0
- data/bin/naksh +2 -0
- data/data/default.mo +0 -0
- data/data/default.po +16 -0
- data/data/default2.mo +0 -0
- data/data/default2.po +27 -0
- data/data/starter.pot +29 -0
- data/docs/bash_flow.dia +0 -0
- data/docs/gtk_manual.txt +13 -0
- data/docs/master_plan.dia +0 -0
- data/docs/master_plan.png +0 -0
- data/docs/master_plan.svg +74 -0
- data/docs/master_plan.svgz +0 -0
- data/docs/userguide/en/about.xml +42 -0
- data/docs/userguide/en/gnu-fdl-1.2.xml +543 -0
- data/docs/userguide/en/naksh.xml +881 -0
- data/docs/userguide/en/naksh_start_window.png +0 -0
- data/docs/userguide/en/old_naksh.xml +180 -0
- data/docs/userguide/en/userguide-en.omf +37 -0
- data/lib/naksh.rb +165 -0
- data/lib/naksh/buffer.rb +153 -0
- data/lib/naksh/command_handling.rb +117 -0
- data/lib/naksh/commands/bash/README +2 -0
- data/lib/naksh/commands/bash/echo.nkc.rb +50 -0
- data/lib/naksh/commands/bsd.rb +25 -0
- data/lib/naksh/commands/dos.rb +25 -0
- data/lib/naksh/commands/fuse.rb +25 -0
- data/lib/naksh/commands/gnu.rb +30 -0
- data/lib/naksh/commands/gnu/README +2 -0
- data/lib/naksh/commands/gnu/cat.nkc.rb +50 -0
- data/lib/naksh/commands/gnu/cd.nkc.rb +11 -0
- data/lib/naksh/commands/gnu/echo.documentation.json +57 -0
- data/lib/naksh/commands/gnu/echo.documentation.rb +60 -0
- data/lib/naksh/commands/gnu/echo.nkc.rb +52 -0
- data/lib/naksh/commands/gnu/ls.nkc.rb +11 -0
- data/lib/naksh/commands/gnu/mv.nkc.rb +15 -0
- data/lib/naksh/commands/gnu/pwd.nkc.rb +11 -0
- data/lib/naksh/commands/naksh/addpath.nkc.rb +15 -0
- data/lib/naksh/commands/naksh/broken.nkc.rb +10 -0
- data/lib/naksh/commands/naksh/empty.nkc.rb +4 -0
- data/lib/naksh/commands/naksh/exit.nkc.rb +10 -0
- data/lib/naksh/commands/naksh/help.nkc.rb +21 -0
- data/lib/naksh/commands/naksh/man.nkc.rb +8 -0
- data/lib/naksh/commands/ruby.rb +31 -0
- data/lib/naksh/commands/unix.rb +131 -0
- data/lib/naksh/configuration/gconf.rb +51 -0
- data/lib/naksh/configuration/hash.rb +38 -0
- data/lib/naksh/defaults.rb +40 -0
- data/lib/naksh/history.rb +85 -0
- data/lib/naksh/interfaces.rb +59 -0
- data/lib/naksh/interfaces/fox.rb +49 -0
- data/lib/naksh/interfaces/gtk.rb +103 -0
- data/lib/naksh/interfaces/gtk/abtwin.rb +53 -0
- data/lib/naksh/interfaces/gtk/gnomeapp.rb +31 -0
- data/lib/naksh/interfaces/gtk/helpwin.rb +70 -0
- data/lib/naksh/interfaces/gtk/io.rb +94 -0
- data/lib/naksh/interfaces/gtk/mainwin.rb +56 -0
- data/lib/naksh/interfaces/gtk/mainwin/console.rb +121 -0
- data/lib/naksh/interfaces/gtk/mainwin/main_menu.rb +143 -0
- data/lib/naksh/interfaces/gtk/optwin.rb +78 -0
- data/lib/naksh/interfaces/tab.rb +58 -0
- data/lib/naksh/interfaces/wxw.rb +75 -0
- data/lib/naksh/interfaces/wxw/abtwin.rb +38 -0
- data/lib/naksh/interfaces/wxw/helpwin.rb +40 -0
- data/lib/naksh/interfaces/wxw/io.rb +61 -0
- data/lib/naksh/interfaces/wxw/mainwin.rb +42 -0
- data/lib/naksh/interfaces/wxw/mainwin/main_menu.rb +126 -0
- data/lib/naksh/interfaces/wxw/mainwin/sessions.rb +49 -0
- data/lib/naksh/interfaces/wxw/optwin.rb +37 -0
- data/lib/naksh/path_entry.rb +101 -0
- data/lib/naksh/regexp.rb +31 -0
- data/lib/naksh/session.rb +72 -0
- data/lib/naksh/stdlibext.rb +48 -0
- data/lib/naksh/syntax.rb +57 -0
- data/lib/naksh/syntax/bash.rb +219 -0
- data/lib/naksh/syntax/bash/antlr/bottomup.g +24 -0
- data/lib/naksh/syntax/bash/antlr/topdown.g +52 -0
- data/lib/naksh/syntax/bash/dhaka/evaluator.rb +353 -0
- data/lib/naksh/syntax/bash/dhaka/grammar.rb +71 -0
- data/lib/naksh/syntax/bash/dhaka/lexer.rb +52 -0
- data/lib/naksh/syntax/bash/treetop/bash.treetop +17 -0
- data/lib/old/abbr_call.rb +39 -0
- data/lib/old/autocomplete.rb +29 -0
- data/lib/old/command.rb +106 -0
- data/lib/old/command_holder.rb +75 -0
- data/lib/old/commands.rb +24 -0
- data/lib/old/old_executor.rb +95 -0
- data/lib/old/options.rb +31 -0
- data/lib/old/rush.rb +113 -0
- data/lib/old/sortissimo.rb +205 -0
- data/lib/old/systems.rb +25 -0
- data/lib/old/systems/ruby.rb +26 -0
- data/lib/old/un.rb +240 -0
- data/lib/rust/Rakefile +6 -0
- data/lib/rust/commands/builtins.rb +46 -0
- data/lib/rust/commands/builtins/cd.rb +17 -0
- data/lib/rust/commands/builtins/exit.rb +13 -0
- data/lib/rust/commands/builtins/help.rb +14 -0
- data/lib/rust/commands/builtins/parser.rb +13 -0
- data/lib/rust/commands/builtins/pwd.rb +13 -0
- data/lib/rust/commands/builtins/type.rb +13 -0
- data/lib/rust/commands/commands/ls.rb +13 -0
- data/lib/rust/commands/commands/read.rb +13 -0
- data/lib/rust/commands/commands/rm.rb +14 -0
- data/lib/rust/commands/commands/test.rb +20 -0
- data/lib/rust/helpers/array.rb +10 -0
- data/lib/rust/helpers/command_center.rb +78 -0
- data/lib/rust/helpers/constants.rb +58 -0
- data/lib/rust/helpers/io.rb +132 -0
- data/lib/rust/helpers/parser.rb +45 -0
- data/lib/rust/helpers/rush_control.rb +40 -0
- data/lib/rust/helpers/string.rb +50 -0
- data/lib/rust/helpers/trollop.rb +475 -0
- data/lib/rust/parsers/bash.rb +220 -0
- data/lib/rust/parsers/bash/stdlibext.rb +32 -0
- data/lib/rust/parsers/ren.rb +57 -0
- data/lib/rust/rust.rb +75 -0
- data/lib/rust/syntax/command.rb +23 -0
- data/lib/rust/syntax/paths.rb +31 -0
- data/lib/rust/syntax/pipes.rb +148 -0
- data/naksh.gemspec +55 -0
- data/test/naksh/arg_parser.rspec.rb +27 -0
- data/test/naksh/commands/bash/echo.rspec.rb +32 -0
- data/test/naksh/commands/sortlist +127 -0
- data/test/naksh/external_command.rspec.rb +46 -0
- data/test/naksh/send_error.rspec.rb +60 -0
- data/test/naksh/suggest.rspec.rb +38 -0
- data/test/naksh/syntax/bash.rspec.rb +69 -0
- data/test/naksh/syntax/bash/execute.rspec.rb +51 -0
- data/test/naksh/syntax/rspec.rb +63 -0
- data/test/run_rspecs.rb +20 -0
- 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
|
+
|
data/lib/naksh/regexp.rb
ADDED
|
@@ -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
|
data/lib/naksh/syntax.rb
ADDED
|
@@ -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
|