troshka 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/bin/troshka ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../lib/troshka'
3
+
4
+ Troshka::App.new.start
5
+
@@ -0,0 +1,59 @@
1
+ module Troshka
2
+
3
+ class App
4
+ def initialize
5
+ @qt_app = Qt::Application.new []
6
+
7
+ @editor = Editor.new
8
+ @editor.app = self
9
+
10
+ @output = Output.new
11
+ @output.app = self
12
+
13
+ @detail = Detail.new
14
+ @detail.app = self
15
+
16
+ @splitterh = Qt::Splitter.new
17
+ @splitterv = Qt::Splitter.new
18
+ @shell = Shell.new
19
+ end
20
+
21
+ def complete(word, line)
22
+ Bond.agent.call word, line
23
+ end
24
+
25
+ def run(text)
26
+ out = @shell.run text
27
+ @editor.text = ""
28
+ out[:text] = text
29
+ @output.add out
30
+ @output.scrollToBottom
31
+ @detail.view out[:obj]
32
+ end
33
+
34
+ def replace_code(text)
35
+ @editor.text = text
36
+ @editor.move_to_end
37
+ @editor.setFocus
38
+ end
39
+
40
+ def start
41
+ Bond.start
42
+
43
+ @splitterv.set_orientation Qt::Horizontal
44
+ @splitterh.set_orientation Qt::Vertical
45
+ @splitterh.resize 600,400
46
+
47
+ @splitterh.add_widget @splitterv
48
+ @splitterv.add_widget @output
49
+ @splitterv.add_widget @detail
50
+
51
+ @splitterh.add_widget @editor
52
+ @editor.setFocus
53
+ @splitterh.show
54
+
55
+ @qt_app.exec
56
+ end
57
+ end
58
+
59
+ end
@@ -0,0 +1,25 @@
1
+ module Troshka
2
+
3
+ class Detail < Qt::StackedWidget
4
+ attr_accessor :app
5
+
6
+ def initialize
7
+ super
8
+ @w = [DetailArrayHash.new, DetailAnything.new]
9
+ @w.each {|i| addWidget i}
10
+ self.setCurrentIndex 1
11
+ end
12
+
13
+ def view(obj)
14
+ case obj
15
+ when Array, Hash
16
+ @w[0].view obj
17
+ self.setCurrentIndex 0
18
+ else
19
+ @w[1].view obj
20
+ self.setCurrentIndex 1
21
+ end
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,9 @@
1
+ module Troshka
2
+
3
+ class DetailAnything < Qt::TextEdit
4
+ def view(obj)
5
+ self.text = obj.to_s
6
+ end
7
+ end
8
+
9
+ end
@@ -0,0 +1,86 @@
1
+ module Troshka
2
+
3
+ class DetailArrayHash < Qt::TreeWidget
4
+ attr_accessor :app
5
+
6
+ def initialize
7
+ super
8
+ self.setHeaderLabels ['Index', 'Value']
9
+ end
10
+
11
+ def view(obj)
12
+ self.clear
13
+ viewObject obj
14
+ end
15
+
16
+ private
17
+
18
+ def viewObject(obj, idx=nil, parent=nil)
19
+ case obj
20
+ when Array
21
+ viewArray obj, idx, parent
22
+ when Hash
23
+ viewHash obj, idx, parent
24
+ else
25
+ viewAnything obj, idx, parent
26
+ end
27
+ end
28
+
29
+ def insert(item, parent=nil)
30
+ if not parent.is_a? Qt::TreeWidgetItem
31
+ self.addTopLevelItem item
32
+ else
33
+ parent.insertChild parent.childCount, item
34
+ end
35
+ end
36
+
37
+ def viewArray(obj, idx, parent)
38
+ if parent.nil?
39
+ item = :root
40
+ else
41
+ item = Qt::TreeWidgetItem.new
42
+ item.setText 0, idx.to_s
43
+ item.setText 1, "Array #{obj.size} items"
44
+ item.setForeground 1, Qt::Brush.new(Qt::Color.new 128, 128, 128)
45
+ insert item, parent
46
+ end
47
+
48
+ obj.each_with_index do |o,idx|
49
+ viewObject o, idx, item
50
+ end
51
+
52
+ item
53
+ end
54
+
55
+ def viewHash(obj, idx, parent)
56
+ if parent.nil?
57
+ item = :root
58
+ else
59
+ item = Qt::TreeWidgetItem.new
60
+ item.setText 0, idx.to_s
61
+ item.setText 1, "Hash #{obj.size} items"
62
+ brush = Qt::Brush.new(Qt::Color.new 229, 229, 255)
63
+ item.setBackground 0, brush
64
+ item.setBackground 1, brush
65
+ insert item, parent
66
+ end
67
+
68
+ obj.each do |k,v|
69
+ viewObject v, k, item
70
+ end
71
+
72
+ item
73
+ end
74
+
75
+ def viewAnything(obj, idx, parent=nil)
76
+ item = Qt::TreeWidgetItem.new
77
+ item.setText 0, idx.to_s
78
+ item.setText 1, obj.to_s
79
+ item.setForeground 1, Qt::Brush.new(Qt::Color.new 0, 0, 229)
80
+ insert item, parent
81
+ item
82
+ end
83
+
84
+ end
85
+
86
+ end
@@ -0,0 +1,113 @@
1
+ module Troshka
2
+
3
+ class Editor < Qsci::Scintilla
4
+ attr_accessor :app
5
+
6
+ def initialize
7
+ super
8
+ build
9
+ end
10
+
11
+ def user_list_activated(&block)
12
+ connect(SIGNAL "userListActivated(int, const QString)") {|id, text| block.(self,text)}
13
+ end
14
+
15
+ def keyPressEvent(x)
16
+ if x.key==Qt::Key_Space && x.modifiers==Qt::Control_Modifier
17
+ pos = column
18
+ word = current_word
19
+ list = @app.complete(word[:word], current_line)
20
+ unless list.empty?
21
+ list.sort!
22
+
23
+ hint = list.first.dup
24
+ hint.chop! while current_line.rindex(hint).nil?
25
+ @auto = word[:word_end]+1-hint.size, word[:word_end]
26
+
27
+ setCursorPosition(line, word[:word_end]-hint.size)
28
+ show_user_list 1, list
29
+ setCursorPosition(line, pos)
30
+ end
31
+ elsif x.key==Qt::Key_Return && x.modifiers==Qt::Control_Modifier
32
+ @app.run text
33
+ else
34
+ super x
35
+ end
36
+ end
37
+
38
+ def position
39
+ # SCI_GETCURRENTPOS
40
+ SendScintilla(2008, 0, 0)
41
+ end
42
+
43
+ def line_end_position(line)
44
+ # SCI_GETLINEENDPOSITION
45
+ SendScintilla(2136, line, 0)
46
+ end
47
+
48
+ def move_to_end
49
+ setCursorPosition lines, line_end_position(lines)
50
+ end
51
+
52
+ def select_word
53
+ word = current_word
54
+ setSelection line, word[:word_begin], line, word[:word_end]+1
55
+ end
56
+
57
+ def select_auto
58
+ setSelection line, @auto.first, line, @auto.last + 1
59
+ end
60
+
61
+ def select_line
62
+ setSelection line, 0, line, lineLength(line)
63
+ end
64
+
65
+ def line
66
+ # SCI_LINEFROMPOSITION
67
+ SendScintilla(2166,position,0)
68
+ end
69
+
70
+ def column
71
+ # SCI_GETCOLUMN = 2129
72
+ SendScintilla(2129,position,0)
73
+ end
74
+
75
+ def insert_and_advance(text)
76
+ insert text
77
+ setCursorPosition(line, column + text.length)
78
+ end
79
+
80
+ def current_line
81
+ text line
82
+ end
83
+
84
+ def current_word
85
+ word_begin = current_line.rindex(word_separator, column-1)+1 rescue 0
86
+ word_end = current_line.index(word_separator, column)-1 rescue current_line.size-1
87
+
88
+ word = current_line[word_begin..word_end]
89
+ {word_begin: word_begin, word_end: word_end, word: word}
90
+ end
91
+
92
+ def word_separator
93
+ " "
94
+ end
95
+
96
+ def build
97
+ @lexer = Qsci::LexerRuby.new
98
+ self.setAutoIndent true
99
+ self.setIndentationGuides true
100
+ self.setIndentationWidth 2
101
+ self.setFolding Qsci::Scintilla::PlainFoldStyle
102
+ self.setLexer @lexer
103
+ self.setMarginWidth 1, 0
104
+
105
+ self.user_list_activated do |editor, text|
106
+ editor.select_auto
107
+ editor.replaceSelectedText text
108
+ end
109
+ end
110
+
111
+ end
112
+
113
+ end
@@ -0,0 +1,58 @@
1
+ module Troshka
2
+
3
+ class Output < Qt::ListWidget
4
+ attr_accessor :app
5
+
6
+ def initialize
7
+ super
8
+ build
9
+ end
10
+
11
+ def item_double_click(&block)
12
+ connect(SIGNAL "itemDoubleClicked(QListWidgetItem*)") {|item| block.(item)}
13
+ end
14
+
15
+ def add(obj)
16
+ iCode = Qt::ListWidgetItem.new
17
+ iCode.setText obj[:text]
18
+ iCode.setData Qt::UserRole, Qt::Variant.new("code")
19
+ iCode.setForeground Qt::Brush.new(Qt::Color.new 0, 0, 255)
20
+ self.addItem iCode
21
+
22
+ if obj[:exception]
23
+ iEx = Qt::ListWidgetItem.new
24
+ iEx.setText "#{obj[:exception].class}: #{obj[:exception].message}"
25
+ iEx.setData Qt::UserRole, Qt::Variant.new("exception")
26
+ iEx.setBackground Qt::Brush.new(Qt::Color.new 255, 0, 0)
27
+ self.addItem iEx
28
+ else
29
+ unless obj[:output].empty?
30
+ obj[:output].chop! if obj[:output][-1]=="\n"
31
+ iOut = Qt::ListWidgetItem.new
32
+ iOut.setText obj[:output]
33
+ iOut.setBackground Qt::Brush.new(Qt::Color.new 229, 229, 255)
34
+ iOut.setData Qt::UserRole, Qt::Variant.new("output")
35
+ self.addItem iOut
36
+ end
37
+
38
+ obj[:obj] = "nil" if obj[:obj].nil?
39
+ iObj = Qt::ListWidgetItem.new
40
+ iObj.setText obj[:obj].to_s
41
+ iObj.setData Qt::UserRole, Qt::Variant.new("obj")
42
+ iObj.setBackground Qt::Brush.new(Qt::Color.new 255, 255, 229)
43
+ self.addItem iObj
44
+ end
45
+
46
+ self.item(self.count-1).setSelected true
47
+ end
48
+
49
+ def build
50
+ item_double_click do |item|
51
+ if item.data(Qt::UserRole).toString == "code"
52
+ @app.replace_code item.text
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ end
@@ -0,0 +1,27 @@
1
+ module Troshka
2
+
3
+ class Shell
4
+ def initialize
5
+ @binding = TOPLEVEL_BINDING
6
+ $stdout = StringIO.new
7
+ end
8
+
9
+ def run(str)
10
+ obj = eval(str, @binding, "(girb)")
11
+ exception = nil
12
+
13
+ $stdout.rewind
14
+ output = $stdout.read
15
+ $stdout.truncate(0)
16
+ $stdout.rewind
17
+ rescue Exception => e
18
+ output = nil
19
+ obj = nil
20
+ exception = e
21
+ ensure
22
+ return {output: output, obj: obj, exception: exception}
23
+ end
24
+
25
+ end
26
+
27
+ end
data/lib/troshka.rb ADDED
@@ -0,0 +1,5 @@
1
+ %w{Qt4 qscintilla bond stringio}.each {|lib| require "#{lib}"}
2
+
3
+ %w{app detail detail_anything detail_array_hash editor output shell version}.each do |lib|
4
+ require_relative "./troshka/#{lib}"
5
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: troshka
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Patricio Ros
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bond
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: ! " Troshka is an GUI Ruby console. It's an alternative to irb and\n
31
+ \ other Ruby REPLs. \n Troshka is written in Ruby and GUI uses Qt bindings.\n"
32
+ email: patricioros.dev@gmail.com
33
+ executables:
34
+ - troshka
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - lib/troshka/output.rb
39
+ - lib/troshka/detail_anything.rb
40
+ - lib/troshka/detail.rb
41
+ - lib/troshka/editor.rb
42
+ - lib/troshka/app.rb
43
+ - lib/troshka/detail_array_hash.rb
44
+ - lib/troshka/shell.rb
45
+ - lib/troshka.rb
46
+ - bin/troshka
47
+ homepage: https://github.com/pmros/troshka
48
+ licenses: []
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: 1.9.0
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements:
66
+ - QtRuby
67
+ - QScintilla
68
+ rubyforge_project:
69
+ rubygems_version: 1.8.23
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: A GUI Ruby console
73
+ test_files: []