canis 0.0.4
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.
- checksums.yaml +7 -0
- data/.gitignore +45 -0
- data/CHANGES +52 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +24 -0
- data/Rakefile +2 -0
- data/canis.gemspec +25 -0
- data/examples/alpmenu.rb +46 -0
- data/examples/app.sample +19 -0
- data/examples/appemail.rb +191 -0
- data/examples/atree.rb +105 -0
- data/examples/bline.rb +181 -0
- data/examples/common/devel.rb +319 -0
- data/examples/common/file.rb +93 -0
- data/examples/data/README.markdown +9 -0
- data/examples/data/brew.txt +38 -0
- data/examples/data/color.2 +37 -0
- data/examples/data/gemlist.txt +59 -0
- data/examples/data/lotr.txt +12 -0
- data/examples/data/ports.txt +136 -0
- data/examples/data/table.txt +37 -0
- data/examples/data/tasks.csv +88 -0
- data/examples/data/tasks.txt +27 -0
- data/examples/data/todo.txt +16 -0
- data/examples/data/todocsv.csv +28 -0
- data/examples/data/unix1.txt +21 -0
- data/examples/data/unix2.txt +11 -0
- data/examples/dbdemo.rb +506 -0
- data/examples/dirtree.rb +177 -0
- data/examples/newtabbedwindow.rb +100 -0
- data/examples/newtesttabp.rb +92 -0
- data/examples/tabular.rb +212 -0
- data/examples/tasks.rb +179 -0
- data/examples/term2.rb +88 -0
- data/examples/testbuttons.rb +307 -0
- data/examples/testcombo.rb +102 -0
- data/examples/testdb.rb +182 -0
- data/examples/testfields.rb +208 -0
- data/examples/testflowlayout.rb +43 -0
- data/examples/testkeypress.rb +98 -0
- data/examples/testlistbox.rb +187 -0
- data/examples/testlistbox1.rb +199 -0
- data/examples/testmessagebox.rb +144 -0
- data/examples/testprogress.rb +116 -0
- data/examples/testree.rb +107 -0
- data/examples/testsplitlayout.rb +53 -0
- data/examples/testsplitlayout1.rb +49 -0
- data/examples/teststacklayout.rb +48 -0
- data/examples/testwsshortcuts.rb +68 -0
- data/examples/testwsshortcuts2.rb +129 -0
- data/lib/canis.rb +16 -0
- data/lib/canis/core/docs/index.txt +104 -0
- data/lib/canis/core/docs/list.txt +16 -0
- data/lib/canis/core/docs/style_help.yml +34 -0
- data/lib/canis/core/docs/tabbedpane.txt +15 -0
- data/lib/canis/core/docs/table.txt +31 -0
- data/lib/canis/core/docs/textpad.txt +48 -0
- data/lib/canis/core/docs/tree.txt +23 -0
- data/lib/canis/core/include/.DS_Store +0 -0
- data/lib/canis/core/include/action.rb +83 -0
- data/lib/canis/core/include/actionmanager.rb +49 -0
- data/lib/canis/core/include/appmethods.rb +179 -0
- data/lib/canis/core/include/bordertitle.rb +49 -0
- data/lib/canis/core/include/canisparser.rb +100 -0
- data/lib/canis/core/include/colorparser.rb +437 -0
- data/lib/canis/core/include/defaultfilerenderer.rb +64 -0
- data/lib/canis/core/include/io.rb +320 -0
- data/lib/canis/core/include/layouts/SplitLayout.rb +161 -0
- data/lib/canis/core/include/layouts/abstractlayout.rb +213 -0
- data/lib/canis/core/include/layouts/flowlayout.rb +104 -0
- data/lib/canis/core/include/layouts/stacklayout.rb +109 -0
- data/lib/canis/core/include/listbindings.rb +89 -0
- data/lib/canis/core/include/listeditable.rb +319 -0
- data/lib/canis/core/include/listoperations.rb +61 -0
- data/lib/canis/core/include/listselectionmodel.rb +388 -0
- data/lib/canis/core/include/multibuffer.rb +173 -0
- data/lib/canis/core/include/ractionevent.rb +73 -0
- data/lib/canis/core/include/rchangeevent.rb +27 -0
- data/lib/canis/core/include/rhistory.rb +95 -0
- data/lib/canis/core/include/rinputdataevent.rb +47 -0
- data/lib/canis/core/include/textdocument.rb +111 -0
- data/lib/canis/core/include/vieditable.rb +175 -0
- data/lib/canis/core/include/widgetmenu.rb +66 -0
- data/lib/canis/core/system/colormap.rb +165 -0
- data/lib/canis/core/system/keydefs.rb +32 -0
- data/lib/canis/core/system/ncurses.rb +237 -0
- data/lib/canis/core/system/panel.rb +129 -0
- data/lib/canis/core/system/window.rb +1081 -0
- data/lib/canis/core/util/ansiparser.rb +119 -0
- data/lib/canis/core/util/app.rb +696 -0
- data/lib/canis/core/util/basestack.rb +412 -0
- data/lib/canis/core/util/defaultcolorparser.rb +84 -0
- data/lib/canis/core/util/extras/README +5 -0
- data/lib/canis/core/util/extras/bottomline.rb +1815 -0
- data/lib/canis/core/util/extras/padreader.rb +192 -0
- data/lib/canis/core/util/focusmanager.rb +31 -0
- data/lib/canis/core/util/helpmanager.rb +160 -0
- data/lib/canis/core/util/oldwidgetshortcuts.rb +304 -0
- data/lib/canis/core/util/promptmenu.rb +235 -0
- data/lib/canis/core/util/rcommandwindow.rb +933 -0
- data/lib/canis/core/util/rdialogs.rb +520 -0
- data/lib/canis/core/util/textutils.rb +74 -0
- data/lib/canis/core/util/viewer.rb +238 -0
- data/lib/canis/core/util/widgetshortcuts.rb +508 -0
- data/lib/canis/core/widgets/applicationheader.rb +103 -0
- data/lib/canis/core/widgets/box.rb +58 -0
- data/lib/canis/core/widgets/divider.rb +310 -0
- data/lib/canis/core/widgets/extras/README.md +12 -0
- data/lib/canis/core/widgets/extras/rtextarea.rb +960 -0
- data/lib/canis/core/widgets/extras/stackflow.rb +474 -0
- data/lib/canis/core/widgets/keylabelprinter.rb +194 -0
- data/lib/canis/core/widgets/listbox.rb +326 -0
- data/lib/canis/core/widgets/listfooter.rb +86 -0
- data/lib/canis/core/widgets/rcombo.rb +210 -0
- data/lib/canis/core/widgets/rcontainer.rb +415 -0
- data/lib/canis/core/widgets/rlink.rb +30 -0
- data/lib/canis/core/widgets/rmenu.rb +970 -0
- data/lib/canis/core/widgets/rmenulink.rb +30 -0
- data/lib/canis/core/widgets/rmessagebox.rb +400 -0
- data/lib/canis/core/widgets/rprogress.rb +118 -0
- data/lib/canis/core/widgets/rtabbedpane.rb +631 -0
- data/lib/canis/core/widgets/rtabbedwindow.rb +70 -0
- data/lib/canis/core/widgets/rwidget.rb +3634 -0
- data/lib/canis/core/widgets/scrollbar.rb +147 -0
- data/lib/canis/core/widgets/statusline.rb +113 -0
- data/lib/canis/core/widgets/table.rb +1072 -0
- data/lib/canis/core/widgets/tabular.rb +264 -0
- data/lib/canis/core/widgets/textpad.rb +1674 -0
- data/lib/canis/core/widgets/tree.rb +690 -0
- data/lib/canis/core/widgets/tree/treecellrenderer.rb +150 -0
- data/lib/canis/core/widgets/tree/treemodel.rb +432 -0
- data/lib/canis/version.rb +3 -0
- metadata +229 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Field to have history which pops up
|
|
2
|
+
App to have layout objects @1.6
|
|
3
|
+
F2 menu to have context sensitive items
|
|
4
|
+
SL and Dock events Hide. Move ...
|
|
5
|
+
Stack and Flow to be objects @1.5
|
|
6
|
+
ability to share directory options and functions across dir apps
|
|
7
|
+
add event to form, key_resize
|
|
8
|
+
app: add popup @1.5
|
|
9
|
+
app: widgets can register with dock @1.5
|
|
10
|
+
can use textpad in resultsetdb view to make things simpler
|
|
11
|
+
colored module that allows row-wise coloring for all multirow wids
|
|
12
|
+
find_file like microemacs @1.5
|
|
13
|
+
motion options in textview and lists gg G cYcEcDcB zz zt zb etc
|
|
14
|
+
registering command with Alt-X SL and Dock
|
|
15
|
+
schemes (color) @1.5
|
|
16
|
+
textview etc can have source. also module to recog file type,fmt
|
|
17
|
+
use textpad for lists etc
|
|
18
|
+
window.close can have a event so cleanup of any widget can be done
|
|
19
|
+
Backward char search using F
|
|
20
|
+
add progress bar to StatusWindow
|
|
21
|
+
bottomline options global @1.5
|
|
22
|
+
catch_alt_digits maybe at form level not global
|
|
23
|
+
widgets needs to expose mapped keys in some easy way
|
|
24
|
+
color_pair as :red_on_black
|
|
25
|
+
confirm quit option, and call a proc before quitting
|
|
26
|
+
elusive error if row not given in button
|
|
27
|
+
rpopupmenu and rmenu share same class names
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
1. simplify %Field. datatype and mask is overlapping
|
|
2
|
+
1. simplify %field, two ways of creating a label
|
|
3
|
+
2. how to override +- * a and others for listbox - need to call before super()
|
|
4
|
+
3. clear_row in %textpad can overlap next row if data long
|
|
5
|
+
4. app to contain window close and confirm close
|
|
6
|
+
4. %menu - remove complex rare functionality from main code
|
|
7
|
+
4. redo %menu bar -- current code is old and messy
|
|
8
|
+
5. test out vieditable and listeditable with core
|
|
9
|
+
6. when sorting cursor on old row but curr changed
|
|
10
|
+
.3. Make keylabels more rubyesque - later
|
|
11
|
+
x1. check native_text again to see how much used
|
|
12
|
+
x2. Show key mappings to user
|
|
13
|
+
x3. row_selector to be v
|
|
14
|
+
x5. convert testlistbox to core
|
|
15
|
+
x5. messagebox default button - done but current button should show default char
|
|
16
|
+
x5. messagebox to catch YN keys also
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
FIXME,MSGBOX,5,Confirm dialog: box vertical line overwritten in 2 spots,TODO
|
|
2
|
+
FIXME,MSGBOX,5,Confirm dialog: use normal key as hotkey also,TODO,Tue Jan 20 11:44:49 +0530 2009
|
|
3
|
+
FIXME,MSGBOX,5,Confirm dialog: arrow keys not navigating anylonger,TODO,Tue Jan 20 11:45:27 +0530 2009
|
|
4
|
+
FIXME,GEN,9,Message Box sizing,TODO,Thu Jan 22 20:39:21 +0530 2009
|
|
5
|
+
DONE,LIST,5,case insensitive char search in list and combo,TESTED,Sat Feb 21 20:43:05 +0530 2009
|
|
6
|
+
DONE,TABLE,5,increase the maxlen of this field please. Let us see how it goes.,TESTED
|
|
7
|
+
DONE,TABLE,5,Can we disable down arrow in Chkbox in table?,TESTED,Mon Jan 19 00:00:00 +0530 2009
|
|
8
|
+
DONE,TABLE,0,editing on enter,TESTED,Mon Jan 19 01:37:00 +0530 2009
|
|
9
|
+
DONE,TABLE,5,cell editors pcol is not being reset each time,TESTED,Mon Jan 19 17:47:00 +0530 2009
|
|
10
|
+
DONE,TABLE,5,Use TAB for intercell navig. use M-TAB for next f,TESTED,Tue Jan 20 00:38:19 +0530 2009
|
|
11
|
+
DONE,TABLE,5,Searching,TESTED,Sat Feb 21 20:42:10 +0530 2009
|
|
12
|
+
DONE,TABLE,3,Columns editable or not,TESTED,Sat Feb 21 20:43:10 +0530 2009
|
|
13
|
+
DONE,TABLE,1,Any way to start a table with no data and pop late,TODO,Sat Feb 21 20:43:33 +0530 2009
|
|
14
|
+
DONE,GEN,5,Make widget of Keylabelprinter,TESTED,Tue Jan 20 00:38:43 +0530 2009
|
|
15
|
+
DONE,GEN,5,Added Action class shared by Button Menuitem ,TESTED,Thu Jan 22 18:08:28 +0530 2009
|
|
16
|
+
DONE,GEN,5,Added PopupMenu 2009-01-22 18:09 ,TESTED,Thu Jan 22 18:09:34 +0530 2009
|
|
17
|
+
DONE,LIST,0,call on_enter and on_leave of component,TOTEST,Sun Feb 22 12:19:38 +0530 2009
|
|
18
|
+
DONE,FIELD,5,Field: OVERWRITE Mode,TESTED,2010-09-13 11:24:35 +0530
|
|
19
|
+
DONE,GEN,5,"Modified should check if value changed, not UP etc",TOTEST,2010-09-13 11:25:18 +0530
|
|
20
|
+
TODO,TABLE,1,table.set_data should check if models already created.,TODO
|
|
21
|
+
TODO,TABLE,5,"Set column_class in TableColumn, to avoid hassles",TODO
|
|
22
|
+
TODO,TABLE,2,Table sorting and filtering is required - using VIEW,TODO
|
|
23
|
+
TODO,TABLE,5,Table height and col widths auto sizing or FILLING extra space.,TODO
|
|
24
|
+
TODO,TEXTAREA,9,"Textarea: wrap options NONE, COLUMN",TODO,Tue Jan 20 01:04:15 +0530 2009
|
|
25
|
+
TODO,GEN,5,Give a decent FileChooser and FileSaver,TODO
|
|
26
|
+
TODO,GEN,5,Focus Traversable vs focusable,TODO
|
|
27
|
+
TODO,GEN,5,Action class: fire event for listeners,TODO,Thu Jan 22 20:09:50 +0530 2009
|
|
28
|
+
TODO,FIELD,5,Field: Auto-skip when reaching end of maxlen,TODO
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Eric S. Raymond, in his book The Art of Unix Programming,[2] summarizes the Unix philosophy as the widely-used KISS Principle of "Keep it Simple, Stupid."[3] He also provides a series of design rules:
|
|
2
|
+
|
|
3
|
+
* Rule of Modularity: Write simple parts connected by clean interfaces.
|
|
4
|
+
* Rule of Clarity: Clarity is better than cleverness.
|
|
5
|
+
* Rule of Composition: Design programs to be connected to other programs.
|
|
6
|
+
* Rule of Separation: Separate policy from mechanism; separate interfaces from engines.
|
|
7
|
+
* Rule of Simplicity: Design for simplicity; add complexity only where you must.
|
|
8
|
+
* Rule of Parsimony: Write a big program only when it is clear by demonstration that nothing else will do.
|
|
9
|
+
* Rule of Transparency: Design for visibility to make inspection and debugging easier.
|
|
10
|
+
* Rule of Robustness: Robustness is the child of transparency and simplicity.
|
|
11
|
+
* Rule of Representation: Fold knowledge into data so program logic can be stupid and robust.[4]
|
|
12
|
+
* Rule of Least Surprise: In interface design, always do the least surprising thing.
|
|
13
|
+
* Rule of Silence: When a program has nothing surprising to say, it should say nothing.
|
|
14
|
+
* Rule of Repair: When you must fail, fail noisily and as soon as possible.
|
|
15
|
+
* Rule of Economy: Programmer time is expensive; conserve it in preference to machine time.
|
|
16
|
+
* Rule of Generation: Avoid hand-hacking; write programs to write programs when you can.
|
|
17
|
+
* Rule of Optimization: Prototype before polishing. Get it working before you optimize it.
|
|
18
|
+
* Rule of Diversity: Distrust all claims for "one true way".
|
|
19
|
+
* Rule of Extensibility: Design for the future, because it will be here sooner than you think.
|
|
20
|
+
|
|
21
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
1. Small is beautiful.
|
|
2
|
+
2. Make each program do one thing well.
|
|
3
|
+
3. Build a prototype as soon as possible.
|
|
4
|
+
4. Choose portability over efficiency.
|
|
5
|
+
5. Store data in flat text files.
|
|
6
|
+
6. Use software leverage to your advantage.
|
|
7
|
+
7. Use shell scripts to increase leverage and portability.
|
|
8
|
+
8. Avoid captive user interfaces.
|
|
9
|
+
9. Make every program a filter.
|
|
10
|
+
|
|
11
|
+
|
data/examples/dbdemo.rb
ADDED
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
require 'canis/core/util/app'
|
|
2
|
+
require 'sqlite3'
|
|
3
|
+
#require 'canis/experimental/resultsettextview.rb'
|
|
4
|
+
#require 'canis/experimental/widgets/undomanager'
|
|
5
|
+
|
|
6
|
+
# @return array of table names from selected db file
|
|
7
|
+
def get_table_names
|
|
8
|
+
raise "No database file selected." unless $current_db
|
|
9
|
+
|
|
10
|
+
$tables = get_data "select name from sqlite_master"
|
|
11
|
+
$tables.collect!{|x| x[0] } ## 1.9 hack, but will it run on 1.8 ??
|
|
12
|
+
$tables
|
|
13
|
+
end
|
|
14
|
+
def get_column_names tbname
|
|
15
|
+
get_metadata tbname
|
|
16
|
+
end
|
|
17
|
+
def connect dbname
|
|
18
|
+
$log.debug "XXX: CONNECT got #{dbname} "
|
|
19
|
+
$current_db = dbname
|
|
20
|
+
$db = SQLite3::Database.new(dbname) if dbname
|
|
21
|
+
|
|
22
|
+
return $db
|
|
23
|
+
end
|
|
24
|
+
def get_data sql
|
|
25
|
+
$log.debug "SQL: #{sql} "
|
|
26
|
+
$columns, *rows = $db.execute2(sql)
|
|
27
|
+
$log.debug "XXX COLUMNS #{sql} "
|
|
28
|
+
content = rows
|
|
29
|
+
return nil if content.nil? or content[0].nil?
|
|
30
|
+
$datatypes = content[0].types #if @datatypes.nil?
|
|
31
|
+
return content
|
|
32
|
+
end
|
|
33
|
+
def get_metadata table
|
|
34
|
+
get_data "select * from #{table} limit 1"
|
|
35
|
+
#$columns.collect!{|x| x[0] } ## 1.9 hack, but will it run on 1.8 ??
|
|
36
|
+
return $columns
|
|
37
|
+
end
|
|
38
|
+
#
|
|
39
|
+
# creates a popup for selection given the data, and executes given block with
|
|
40
|
+
# following return value.
|
|
41
|
+
# @return [String] if mode is :single
|
|
42
|
+
# @return [Array] if mode is :multiple
|
|
43
|
+
#
|
|
44
|
+
def create_popup array, selection_mode=:single, &blk
|
|
45
|
+
#raise "no block given " unless block_given?
|
|
46
|
+
listconfig = {'bgcolor' => 'blue', 'color' => 'white'}
|
|
47
|
+
listconfig[:selection_mode] = selection_mode
|
|
48
|
+
ix = popuplist array, listconfig
|
|
49
|
+
if ix
|
|
50
|
+
if selection_mode == :single
|
|
51
|
+
value = array[ix]
|
|
52
|
+
blk.call value
|
|
53
|
+
else
|
|
54
|
+
#values = array.select {|v| ix.include? v}
|
|
55
|
+
values = []
|
|
56
|
+
array.each_with_index { |v, i| values << v if ix.include? i }
|
|
57
|
+
blk.call(values)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
#
|
|
63
|
+
# changed order of name and fields, thanks hramrach
|
|
64
|
+
def view_data name, fields="*"
|
|
65
|
+
fields = "*" if fields == ""
|
|
66
|
+
stmt = "select #{fields} from #{name}"
|
|
67
|
+
stmt << $where_string if $where_string
|
|
68
|
+
stmt << $order_string if $order_string
|
|
69
|
+
view_sql stmt
|
|
70
|
+
@form.by_name['tarea'] << stmt if @form # nil when called from menu
|
|
71
|
+
end
|
|
72
|
+
def view_sql stmt
|
|
73
|
+
begin
|
|
74
|
+
content = get_data stmt
|
|
75
|
+
if content.nil?
|
|
76
|
+
else
|
|
77
|
+
require 'canis/core/widgets/tabular'
|
|
78
|
+
t = Tabular.new do |t|
|
|
79
|
+
t.headings = $columns
|
|
80
|
+
t.data=content
|
|
81
|
+
end
|
|
82
|
+
view t.render
|
|
83
|
+
end
|
|
84
|
+
rescue => err
|
|
85
|
+
$log.error err.to_s
|
|
86
|
+
$log.error(err.backtrace.join("\n"))
|
|
87
|
+
textdialog [err.to_s, *err.backtrace], :title => "Exception"
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
App.new do
|
|
92
|
+
#header = app_header "canis #{Canis::VERSION}", :text_center => "Database Demo", :text_right =>"enabled"
|
|
93
|
+
form = @form
|
|
94
|
+
mylabel = "a field"
|
|
95
|
+
$catch_alt_digits = true # use M-1..9 in textarea
|
|
96
|
+
$current_table = nil
|
|
97
|
+
$current_db = nil # "testd.db"
|
|
98
|
+
connect $current_db if $current_db
|
|
99
|
+
def which_field
|
|
100
|
+
alert "curent field is #{form.get_current_field} "
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def get_commands
|
|
104
|
+
%w{ which_field }
|
|
105
|
+
end
|
|
106
|
+
def help_text
|
|
107
|
+
<<-eos
|
|
108
|
+
DBDEMO HELP
|
|
109
|
+
|
|
110
|
+
This is some help text for dbdemo.
|
|
111
|
+
We are testing out this feature.
|
|
112
|
+
|
|
113
|
+
Alt-d - Select a database
|
|
114
|
+
<Enter> on a table, view data (q to close window)
|
|
115
|
+
v on a table, display columns in lower list
|
|
116
|
+
|
|
117
|
+
COLUMN LIST KEYS
|
|
118
|
+
v on a column for multiple select
|
|
119
|
+
V on a column for range select/deselect from previous selection
|
|
120
|
+
<Enter> on column table to view data for selected columns
|
|
121
|
+
u unselect all
|
|
122
|
+
a select all
|
|
123
|
+
* invert selection
|
|
124
|
+
F4 View data for selected table (or columns if selected)
|
|
125
|
+
|
|
126
|
+
q or C-q Close the data window that comes on Enter or F4
|
|
127
|
+
|
|
128
|
+
Alt-x - Command mode (<tab> to see commands and select)
|
|
129
|
+
: - Command mode
|
|
130
|
+
Alt-z - Commands in TextArea
|
|
131
|
+
|
|
132
|
+
Sql Entry Area
|
|
133
|
+
C-x e Edit in $EDITOR or vi
|
|
134
|
+
M-? To see other key-bindings
|
|
135
|
+
F4 Execute SQL (there should be only one sql).
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
Result Set (this is not present in this demo any longer - moved
|
|
139
|
+
to canis-extras)
|
|
140
|
+
, Prev row (mnemonic <)
|
|
141
|
+
. Next row (mnemonic >)
|
|
142
|
+
< First row
|
|
143
|
+
> Last row
|
|
144
|
+
|
|
145
|
+
F10 - Quit application
|
|
146
|
+
[[index]]
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
-----------------------------------------------------------------------
|
|
151
|
+
Hope you enjoyed this help.
|
|
152
|
+
eos
|
|
153
|
+
end
|
|
154
|
+
def ask_databases
|
|
155
|
+
names = Dir.glob("*.{sqlite,db}")
|
|
156
|
+
if names
|
|
157
|
+
ix = popuplist( names )
|
|
158
|
+
if ix
|
|
159
|
+
value = names[ix]
|
|
160
|
+
connect(value);
|
|
161
|
+
@form.by_name["tlist"].list(get_table_names)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
else
|
|
165
|
+
alert "Can't find a .db or .sqlite file"
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
@form.help_manager.help_text = help_text()
|
|
169
|
+
# TODO accelerators and
|
|
170
|
+
# getting a handle for later use
|
|
171
|
+
mb = menubar do
|
|
172
|
+
keep_visible true
|
|
173
|
+
#@toggle_key=KEY_F2
|
|
174
|
+
menu "File" do
|
|
175
|
+
item "Open", "O" do
|
|
176
|
+
accelerator "Ctrl-O"
|
|
177
|
+
command do
|
|
178
|
+
alert "HA!! you wanted to open a file?"
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
menu "Database" do
|
|
182
|
+
item_list do
|
|
183
|
+
Dir.glob("**/*.{sqlite,db}")
|
|
184
|
+
end
|
|
185
|
+
command do |menuitem, text|
|
|
186
|
+
connect text
|
|
187
|
+
form.by_name["tlist"].list(get_table_names)
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
menu "Tables" do
|
|
191
|
+
item_list do
|
|
192
|
+
if $current_db
|
|
193
|
+
get_table_names
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
command do |menuitem, text|
|
|
197
|
+
$current_table = text
|
|
198
|
+
#alert(get_column_names(text).join(", "))
|
|
199
|
+
create_popup(get_column_names(text), :multiple) { |value| view_data( text, value.join(",") ) }
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
item "New", "N"
|
|
203
|
+
separator
|
|
204
|
+
item "Exit", "x" do
|
|
205
|
+
command do
|
|
206
|
+
throw(:close)
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
item "Cancel Menu" do
|
|
210
|
+
accelerator "Ctrl-g"
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
end # menu
|
|
214
|
+
menu "Window" do
|
|
215
|
+
item "Tile", "T"
|
|
216
|
+
menu "Find" do
|
|
217
|
+
item "More", "M"
|
|
218
|
+
$x = item "Less", "L" do
|
|
219
|
+
#accelerator "Ctrl-X"
|
|
220
|
+
command do
|
|
221
|
+
alert "You clickses on Less"
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
menu "Size" do
|
|
225
|
+
item "Zoom", "Z"
|
|
226
|
+
item "Maximize", "X"
|
|
227
|
+
item "Minimize", "N"
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
menu "Others" do
|
|
232
|
+
require 'canis/core/include/appmethods.rb'
|
|
233
|
+
item "Shell Output" do
|
|
234
|
+
command { shell_output }
|
|
235
|
+
end
|
|
236
|
+
item "Suspend" do
|
|
237
|
+
command { suspend }
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
end # menubar
|
|
241
|
+
mb.toggle_key = FFI::NCurses::KEY_F2
|
|
242
|
+
mb.color = :white
|
|
243
|
+
mb.bgcolor = :blue
|
|
244
|
+
@form.set_menu_bar mb
|
|
245
|
+
tv = nil
|
|
246
|
+
flow :margin_top => 1 do
|
|
247
|
+
col1w = 20
|
|
248
|
+
stack :width_pc => 20 do
|
|
249
|
+
text = ["No tables"]
|
|
250
|
+
if !$current_db
|
|
251
|
+
text = ["Select DB first.","Press Alt-D or ENTER"]
|
|
252
|
+
end
|
|
253
|
+
tlist = listbox :name => "tlist", :list => text, :title => "Tables", :height => 10,
|
|
254
|
+
:selected_color => 'cyan', :selected_bgcolor => 'black' , :selected_attr => Ncurses::A_REVERSE,
|
|
255
|
+
:help_text => "<ENTER> to View complete table, 'v' to select table and view columns",
|
|
256
|
+
:should_show_focus => true,
|
|
257
|
+
:selection_mode => :single
|
|
258
|
+
tlist.bind(:PRESS) do |eve|
|
|
259
|
+
if $current_db
|
|
260
|
+
# get data of table
|
|
261
|
+
view_data eve.text
|
|
262
|
+
#tv.sqlite $current_db, eve.text, "select * from #{eve.text} " # TODO in core
|
|
263
|
+
else
|
|
264
|
+
ask_databases
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
#tlist.bind(:ENTER_ROW) do |eve|
|
|
268
|
+
# too much confusion between selected and focussed row
|
|
269
|
+
#$current_table = eve.text if $db
|
|
270
|
+
#end
|
|
271
|
+
clist = listbox :name => "clist", :list => ["No columns"], :title => "Columns", :height => 14,
|
|
272
|
+
:selection_mode => :multiple,
|
|
273
|
+
:selected_color => 'cyan', :selected_bgcolor => 'black' , :selected_attr => Ncurses::A_REVERSE,
|
|
274
|
+
:help_text => "Enter to View selected fields, 'v' to select columns, w - where, o-order"
|
|
275
|
+
tlist.bind(:LIST_SELECTION_EVENT) do |eve|
|
|
276
|
+
$selected_table = eve.source[eve.firstrow]
|
|
277
|
+
$current_table = $selected_table
|
|
278
|
+
clist.list( get_column_names $selected_table)
|
|
279
|
+
end
|
|
280
|
+
clist.bind(:PRESS) do |eve|
|
|
281
|
+
# get data of table
|
|
282
|
+
if $selected_table
|
|
283
|
+
cols = "*"
|
|
284
|
+
c = clist.values_at(*clist.selected_indices)
|
|
285
|
+
c = clist.selected_values
|
|
286
|
+
unless c.empty?
|
|
287
|
+
cols = c.join(",")
|
|
288
|
+
end
|
|
289
|
+
view_data $selected_table, cols
|
|
290
|
+
else
|
|
291
|
+
alert "Select a table first."
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
clist.bind_key('w', 'add to where condition') {
|
|
295
|
+
c = clist.current_value
|
|
296
|
+
$where_columns ||= []
|
|
297
|
+
hist = ["#{c} = "]
|
|
298
|
+
w = rb_gets("where "){ |q| q.default = "#{c} = "; q.history = hist }
|
|
299
|
+
$where_columns << w if w
|
|
300
|
+
message "where: #{$where_columns.last}. Press F4 when done"
|
|
301
|
+
$log.debug "XXX: WHERE: #{$where_columns} "
|
|
302
|
+
}
|
|
303
|
+
clist.bind_key('o', 'add to order by') {
|
|
304
|
+
c = clist.current_value
|
|
305
|
+
$order_columns ||= []
|
|
306
|
+
$order_columns << c if c
|
|
307
|
+
message "order (asc): #{$order_columns.last}. Press F4 when done"
|
|
308
|
+
$log.debug "XXX: ORDER: #{$order_columns} "
|
|
309
|
+
}
|
|
310
|
+
clist.bind_key('O', 'add to ordery by desc') {
|
|
311
|
+
c = clist.current_value
|
|
312
|
+
$order_columns ||= []
|
|
313
|
+
$order_columns << " #{c} desc " if c
|
|
314
|
+
message "order: #{$order_columns.last}"
|
|
315
|
+
$log.debug "XXX: ORDER: #{$order_columns}. Press F4 when done"
|
|
316
|
+
}
|
|
317
|
+
@statusline = status_line
|
|
318
|
+
#wg = get_color($datacolor, 'white','green')
|
|
319
|
+
#wb = get_color($datacolor, 'white','blue')
|
|
320
|
+
@statusline.command {
|
|
321
|
+
# trying this out. If you want a persistent message that remains till the next on
|
|
322
|
+
# then send it in as $status_message
|
|
323
|
+
text = $status_message.value || ""
|
|
324
|
+
if !$current_db
|
|
325
|
+
#"[%-s] %s" % [ "Select a Database", text]
|
|
326
|
+
"[%-s] %s" % [ "#[bg=red,fg=yellow]Select a Database#[end]", text]
|
|
327
|
+
#[ [nil, "%-22s" % Time.now, nil], [$errorcolor, " [Select a Database ]", FFI::NCurses::A_BOLD], [nil, text, nil] ]
|
|
328
|
+
elsif !$current_table
|
|
329
|
+
"[DB: #[fg=white,bg=blue]%-s#[end] | %-s ] %s" % [ $current_db || "None", $current_table || "#[bg=red,fg=yellow]Select a table#[end]", text]
|
|
330
|
+
#[ [nil, "%-22s [DB: %-s | " % [Time.now, $current_db || "None" ],nil], [$errorcolor, " Select a Table ]", FFI::NCurses::A_BOLD], [nil, text, nil] ]
|
|
331
|
+
else
|
|
332
|
+
"DB: #[fg=white,bg=green,bold]%-s#[end] | #[bold]%-s#[end] ] %s" % [ $current_db || "None", $current_table || "----", text]
|
|
333
|
+
#[ [nil, "%-22s [DB: " % Time.now, nil], [wb, " #{$current_db} ", FFI::NCurses::A_BOLD],
|
|
334
|
+
#[wg, $current_table || "----", FFI::NCurses::A_BOLD], [nil, text, nil] ]
|
|
335
|
+
end
|
|
336
|
+
}
|
|
337
|
+
@adock = nil
|
|
338
|
+
keyarray = [
|
|
339
|
+
["F1" , "Help"], ["F10" , "Exit"],
|
|
340
|
+
["F2", "Menu"], ["F4", "View"],
|
|
341
|
+
["M-d", "Database"], ["M-t", "Table"],
|
|
342
|
+
["M-x", "Command"], nil
|
|
343
|
+
]
|
|
344
|
+
tlist_keyarray = keyarray + [ ["Sp", "Select"], nil, ["Enter","View"] ]
|
|
345
|
+
|
|
346
|
+
clist_keyarray = keyarray + [ ["Sp", "Select"], ["C-sp", "Range Sel"],
|
|
347
|
+
["Enter","View"], ['w', 'where'],
|
|
348
|
+
["o","order by"], ['O', 'order desc']
|
|
349
|
+
]
|
|
350
|
+
tarea_keyarray = keyarray + [ ["M-z", "Commands"], nil ]
|
|
351
|
+
#tarea_sub_keyarray = [ ["r", "Run"], ["c", "clear"], ["w","Save"], ["a", "Append next"],
|
|
352
|
+
#["y", "Yank"], ["Y", "yank pop"] ]
|
|
353
|
+
tarea_sub_keyarray = [ ["r", "Run"], ["c", "clear"], ["e", "Edit externally"], ["w","Kill Ring Save (M-w)"], ["a", "Append Next"],
|
|
354
|
+
["y", "Yank (C-y)"], ["Y", "yank pop (M-y)"],
|
|
355
|
+
["u", "Undo (C-_)"], ["R", "Redo (C-r)"],
|
|
356
|
+
]
|
|
357
|
+
|
|
358
|
+
gw = get_color($reversecolor, 'green', 'black')
|
|
359
|
+
@adock = dock keyarray, { :row => Ncurses.LINES-2, :footer_color_pair => $datacolor,
|
|
360
|
+
:footer_mnemonic_color_pair => gw }
|
|
361
|
+
@adock.set_key_labels tlist_keyarray, :tables
|
|
362
|
+
@adock.set_key_labels clist_keyarray, :columns
|
|
363
|
+
@adock.set_key_labels tarea_sub_keyarray, :tarea_sub
|
|
364
|
+
@adock.set_key_labels tarea_keyarray, :tarea
|
|
365
|
+
tlist.bind(:ENTER) { @adock.mode :tables }
|
|
366
|
+
clist.bind(:ENTER) { @adock.mode :columns }
|
|
367
|
+
|
|
368
|
+
reduce = lambda { |obj|
|
|
369
|
+
obj.height -= 1 if obj.height > 3
|
|
370
|
+
}
|
|
371
|
+
increase = lambda { |obj|
|
|
372
|
+
obj.height += 1 if obj.height + obj.row < Ncurses.LINES-2
|
|
373
|
+
}
|
|
374
|
+
_lower = lambda { |obj|
|
|
375
|
+
obj.row += 1 if obj.height + obj.row < Ncurses.LINES-2
|
|
376
|
+
}
|
|
377
|
+
_raise = lambda { |obj|
|
|
378
|
+
obj.row -= 1 if obj.row > 2
|
|
379
|
+
}
|
|
380
|
+
[clist, tlist].each do |o|
|
|
381
|
+
o.bind_key([?\C-x, ?-]){ |o| reduce.call(o) }
|
|
382
|
+
o.bind_key([?\C-x, ?+]){ |o| increase.call(o) }
|
|
383
|
+
o.bind_key([?\C-x, ?v]){ |o| _lower.call(o) }
|
|
384
|
+
o.bind_key([?\C-x, ?6]){ |o| _raise.call(o) }
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
@form.bind_key([?q,?q], 'quit') { throw :close }
|
|
389
|
+
@form.bind_key(?\M-t, 'select table') do
|
|
390
|
+
if $current_db.nil?
|
|
391
|
+
alert "Please select database first"
|
|
392
|
+
else
|
|
393
|
+
create_popup( get_table_names,:single) {|value| $selected_table = $current_table = value}
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
@form.bind_key(?\M-d, 'select database') do
|
|
397
|
+
ask_databases
|
|
398
|
+
end
|
|
399
|
+
@form.bind_key(FFI::NCurses::KEY_F4, 'view data') do
|
|
400
|
+
$where_string = nil
|
|
401
|
+
$order_string = nil
|
|
402
|
+
if $where_columns
|
|
403
|
+
$where_string = " where " + $where_columns.join(" and ")
|
|
404
|
+
end
|
|
405
|
+
if $order_columns
|
|
406
|
+
$order_string = " order by " + $order_columns.join(" , ")
|
|
407
|
+
end
|
|
408
|
+
# mismatch between current and selected table
|
|
409
|
+
if $current_table
|
|
410
|
+
cols = "*"
|
|
411
|
+
#c = clist.get_selected_values
|
|
412
|
+
c = clist.values_at(*clist.selected_indices)
|
|
413
|
+
unless c.empty?
|
|
414
|
+
cols = c.join(",")
|
|
415
|
+
end
|
|
416
|
+
view_data $current_table, cols
|
|
417
|
+
else
|
|
418
|
+
alert "Select a table first."
|
|
419
|
+
end
|
|
420
|
+
end
|
|
421
|
+
end # stack
|
|
422
|
+
stack :width_pc => 80 do
|
|
423
|
+
tarea = textarea :name => 'tarea', :height => 5, :title => 'Sql Statement'
|
|
424
|
+
#undom = SimpleUndo.new tarea
|
|
425
|
+
tarea.bind_key(Ncurses::KEY_F4, 'view data') do
|
|
426
|
+
text = tarea.get_text
|
|
427
|
+
if text == ""
|
|
428
|
+
alert "Please enter a query and then hit F4. Or press F4 over column list"
|
|
429
|
+
else
|
|
430
|
+
view_sql tarea.get_text
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
tarea.bind(:ENTER) { @adock.mode :tarea }
|
|
434
|
+
tarea.bind_key(?\M-z, 'textarea submenu'){
|
|
435
|
+
|
|
436
|
+
hash = { 'c' => lambda{ tarea.remove_all },
|
|
437
|
+
'e' => lambda{ tarea.edit_external },
|
|
438
|
+
'w' => lambda{ tarea.kill_ring_save },
|
|
439
|
+
'a' => lambda{ tarea.append_next_kill },
|
|
440
|
+
'y' => lambda{ tarea.yank },
|
|
441
|
+
'Y' => lambda{ tarea.yank_pop },
|
|
442
|
+
'r' => lambda{ view_sql tarea.get_text },
|
|
443
|
+
'u' => lambda{ tarea.undo },
|
|
444
|
+
'R' => lambda{ tarea.redo },
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
@adock.mode :tarea_sub
|
|
449
|
+
@adock.repaint
|
|
450
|
+
keys = @adock.get_current_keys
|
|
451
|
+
while((ch = @window.getchar()) != ?\C-c.getbyte(0) )
|
|
452
|
+
if ch < 33 || ch > 126
|
|
453
|
+
Ncurses.beep
|
|
454
|
+
elsif !keys.include?(ch.chr)
|
|
455
|
+
Ncurses.beep
|
|
456
|
+
else
|
|
457
|
+
hash.fetch(ch.chr).call
|
|
458
|
+
#opt_file ch.chr
|
|
459
|
+
break
|
|
460
|
+
end
|
|
461
|
+
end
|
|
462
|
+
@adock.mode :normal
|
|
463
|
+
} # M-z
|
|
464
|
+
flow do
|
|
465
|
+
#button_row = 17
|
|
466
|
+
button "Save" do
|
|
467
|
+
@cmd_history ||= []
|
|
468
|
+
filename = rb_gets("File to append contents to: ") { |q| q.default = @oldfilename; q.history = @cmd_history }
|
|
469
|
+
|
|
470
|
+
if filename
|
|
471
|
+
str = tarea.get_text
|
|
472
|
+
File.open(filename, 'a') {|f| f.write(str) }
|
|
473
|
+
@oldfilename = filename
|
|
474
|
+
@cmd_history << filename unless @cmd_history.include? filename
|
|
475
|
+
|
|
476
|
+
message "Appended data to #{filename}"
|
|
477
|
+
else
|
|
478
|
+
message "Aborted operation"
|
|
479
|
+
end
|
|
480
|
+
#hide_bottomline
|
|
481
|
+
end
|
|
482
|
+
button "Read" do
|
|
483
|
+
filter = "*"
|
|
484
|
+
#str = choose filter, :title => "Files", :prompt => "Choose a file: "
|
|
485
|
+
cproc = Proc.new { |str| Dir.glob(str + "*") }
|
|
486
|
+
str = rb_gets "Choose a file: ", :title => "Files", :tab_completion => cproc,
|
|
487
|
+
:help_text => "Press <tab> to complete filenames. C-a, C-e, C-k. Alt-?"
|
|
488
|
+
if str && File.exists?(str)
|
|
489
|
+
begin
|
|
490
|
+
tarea.set_content(str)
|
|
491
|
+
message "Read content from #{str} "
|
|
492
|
+
rescue => err
|
|
493
|
+
print_error_message "No file named: #{str}: #{err.to_s} "
|
|
494
|
+
end
|
|
495
|
+
end
|
|
496
|
+
end
|
|
497
|
+
#ok_button = button( [button_row,30], "OK", {:mnemonic => 'O'}) do
|
|
498
|
+
#end
|
|
499
|
+
end
|
|
500
|
+
blank
|
|
501
|
+
#tv = Canis::ResultsetTextView.new @form, :row => 1, :col => 1, :width => 50, :height => 16
|
|
502
|
+
#tv = resultsettextview :name => 'resultset', :height => 18 , :title => 'DB Browser', :print_footer => true
|
|
503
|
+
|
|
504
|
+
end
|
|
505
|
+
end
|
|
506
|
+
end # app
|