troshka 0.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.
- data/bin/troshka +5 -0
- data/lib/troshka/app.rb +59 -0
- data/lib/troshka/detail.rb +25 -0
- data/lib/troshka/detail_anything.rb +9 -0
- data/lib/troshka/detail_array_hash.rb +86 -0
- data/lib/troshka/editor.rb +113 -0
- data/lib/troshka/output.rb +58 -0
- data/lib/troshka/shell.rb +27 -0
- data/lib/troshka.rb +5 -0
- metadata +73 -0
data/bin/troshka
ADDED
data/lib/troshka/app.rb
ADDED
@@ -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,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
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: []
|