ver 2009.10.14
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/CHANGELOG +1404 -0
- data/MANIFEST +187 -0
- data/Rakefile +30 -0
- data/TODO +169 -0
- data/bin/ver +19 -0
- data/config/detect.rb +109 -0
- data/config/keymap/vim.rb +239 -0
- data/config/rc.rb +0 -0
- data/config/scratch +3 -0
- data/config/syntax/ANTLR.json +275 -0
- data/config/syntax/ASP VB.net.json +228 -0
- data/config/syntax/ASP.json +135 -0
- data/config/syntax/ActionScript.json +168 -0
- data/config/syntax/Ada.json +108 -0
- data/config/syntax/Apache.json +342 -0
- data/config/syntax/AppleScript.json +721 -0
- data/config/syntax/Bibtex.json +253 -0
- data/config/syntax/Blog (HTML).json +47 -0
- data/config/syntax/Blog (Markdown).json +50 -0
- data/config/syntax/Blog (Text).json +45 -0
- data/config/syntax/Blog (Textile).json +45 -0
- data/config/syntax/Bulletin Board.json +428 -0
- data/config/syntax/C++.json +323 -0
- data/config/syntax/C.json +694 -0
- data/config/syntax/CSS.json +346 -0
- data/config/syntax/DOT.json +79 -0
- data/config/syntax/Diff.json +136 -0
- data/config/syntax/Dylan.json +104 -0
- data/config/syntax/Eiffel.json +128 -0
- data/config/syntax/Erlang.json +1636 -0
- data/config/syntax/F-Script.json +137 -0
- data/config/syntax/FXScript.json +260 -0
- data/config/syntax/Gri.json +141 -0
- data/config/syntax/HTML (Mason).json +207 -0
- data/config/syntax/HTML (Rails).json +52 -0
- data/config/syntax/HTML (Tcl).json +42 -0
- data/config/syntax/HTML for ASP.net.json +736 -0
- data/config/syntax/HTML-ASP.json +45 -0
- data/config/syntax/HTML.json +614 -0
- data/config/syntax/Haskell.json +407 -0
- data/config/syntax/Inform.json +80 -0
- data/config/syntax/Ini.json +91 -0
- data/config/syntax/Io.json +142 -0
- data/config/syntax/Java.json +745 -0
- data/config/syntax/JavaProperties.json +42 -0
- data/config/syntax/JavaScript.json +446 -0
- data/config/syntax/LaTeX Beamer.json +65 -0
- data/config/syntax/LaTeX Log.json +88 -0
- data/config/syntax/LaTeX.json +962 -0
- data/config/syntax/Lighttpd.json +93 -0
- data/config/syntax/Lisp.json +101 -0
- data/config/syntax/Literate Haskell.json +55 -0
- data/config/syntax/Logtalk.json +289 -0
- data/config/syntax/Lua.json +146 -0
- data/config/syntax/M.json +744 -0
- data/config/syntax/MEL.json +161 -0
- data/config/syntax/MIPS.json +114 -0
- data/config/syntax/Mail.json +224 -0
- data/config/syntax/Makefile.json +66 -0
- data/config/syntax/Markdown.json +644 -0
- data/config/syntax/Modula-3.json +80 -0
- data/config/syntax/Movable Type.json +348 -0
- data/config/syntax/OCaml.json +1391 -0
- data/config/syntax/Objective-C++.json +21 -0
- data/config/syntax/OpenGL.json +24 -0
- data/config/syntax/PHP.json +2184 -0
- data/config/syntax/Pascal.json +128 -0
- data/config/syntax/Perl.json +2091 -0
- data/config/syntax/Plain text.json +49 -0
- data/config/syntax/Processing.json +188 -0
- data/config/syntax/Quake3 Config.json +54 -0
- data/config/syntax/R.json +157 -0
- data/config/syntax/Rez.json +137 -0
- data/config/syntax/Ruby on Rails.json +170 -0
- data/config/syntax/Ruby.json +1753 -0
- data/config/syntax/SQL (Rails).json +31 -0
- data/config/syntax/SQL.json +435 -0
- data/config/syntax/SWIG.json +96 -0
- data/config/syntax/Scheme.json +359 -0
- data/config/syntax/Shell-Unix-Generic.json +1198 -0
- data/config/syntax/Slate.json +265 -0
- data/config/syntax/Smarty.json +110 -0
- data/config/syntax/Standard ML.json +322 -0
- data/config/syntax/Subversion commit message.json +62 -0
- data/config/syntax/Tcl.json +278 -0
- data/config/syntax/TeX Math.json +83 -0
- data/config/syntax/TeX.json +157 -0
- data/config/syntax/Textile.json +273 -0
- data/config/syntax/Twiki.json +436 -0
- data/config/syntax/Vectorscript.json +97 -0
- data/config/syntax/XML strict.json +148 -0
- data/config/syntax/XML.json +301 -0
- data/config/syntax/XSL.json +96 -0
- data/config/syntax/YAML.json +293 -0
- data/config/syntax/iCalendar.json +51 -0
- data/config/syntax/reStructuredText.json +403 -0
- data/config/theme/Active4D.json +260 -0
- data/config/theme/All Hallow's Eve.json +171 -0
- data/config/theme/Amy.json +359 -0
- data/config/theme/BBEdit.json +269 -0
- data/config/theme/Bespin.json +322 -0
- data/config/theme/Blackboard.json +215 -0
- data/config/theme/BoysAndGirls01.json +156 -0
- data/config/theme/Brilliance Black.json +1695 -0
- data/config/theme/Brilliance Dull.json +1451 -0
- data/config/theme/Classic Modified.json +288 -0
- data/config/theme/Cobalt.json +345 -0
- data/config/theme/Cool Glow.json +215 -0
- data/config/theme/Dawn.json +258 -0
- data/config/theme/Eiffel.json +270 -0
- data/config/theme/Espresso Libre.json +247 -0
- data/config/theme/Fluidvision.json +272 -0
- data/config/theme/IDLE.json +159 -0
- data/config/theme/LAZY.json +178 -0
- data/config/theme/Mac Classic.json +277 -0
- data/config/theme/MagicWB (Amiga).json +231 -0
- data/config/theme/Merbivore Soft.json +181 -0
- data/config/theme/Merbivore.json +181 -0
- data/config/theme/Monokai.json +177 -0
- data/config/theme/Notepad2.json +166 -0
- data/config/theme/Pastels on Dark.json +437 -0
- data/config/theme/RubyBlue.json +226 -0
- data/config/theme/Sin City 2.json +361 -0
- data/config/theme/Slate.json +270 -0
- data/config/theme/Slush & Poppies.json +232 -0
- data/config/theme/SpaceCadet.json +143 -0
- data/config/theme/Sunburst.json +415 -0
- data/config/theme/Twilight BG FG.json +633 -0
- data/config/theme/Twilight.json +321 -0
- data/config/theme/Whys Poignant.json +119 -0
- data/config/theme/Zenburnesque.json +237 -0
- data/config/theme/barf.json +155 -0
- data/config/theme/fake.json +418 -0
- data/config/theme/happydeluxe.json +114 -0
- data/config/theme/iLife 05.json +393 -0
- data/config/theme/iPlastic.json +177 -0
- data/config/theme/mintBlue Dark.json +414 -0
- data/config/theme/mintBlue.json +415 -0
- data/config/theme/monoindustrial.json +276 -0
- data/config/theme/starlight.json +67 -0
- data/config/tutorial +74 -0
- data/config/welcome +115 -0
- data/help/index.verh +14 -0
- data/lib/ver.rb +156 -0
- data/lib/ver/entry.rb +97 -0
- data/lib/ver/keymap.rb +96 -0
- data/lib/ver/layout.rb +107 -0
- data/lib/ver/methods.rb +19 -0
- data/lib/ver/methods/completion.rb +116 -0
- data/lib/ver/methods/control.rb +340 -0
- data/lib/ver/methods/insert.rb +6 -0
- data/lib/ver/methods/move.rb +65 -0
- data/lib/ver/methods/search.rb +33 -0
- data/lib/ver/methods/select.rb +145 -0
- data/lib/ver/methods/views.rb +21 -0
- data/lib/ver/mode.rb +160 -0
- data/lib/ver/options.rb +207 -0
- data/lib/ver/plist.rb +106 -0
- data/lib/ver/status.rb +67 -0
- data/lib/ver/syntax.rb +68 -0
- data/lib/ver/syntax/detector.rb +53 -0
- data/lib/ver/syntax/processor.rb +48 -0
- data/lib/ver/text.rb +374 -0
- data/lib/ver/textpow.rb +357 -0
- data/lib/ver/theme.rb +162 -0
- data/lib/ver/vendor/fuzzy_file_finder.rb +340 -0
- data/lib/ver/view.rb +163 -0
- data/lib/ver/view/entry.rb +28 -0
- data/lib/ver/view/list.rb +137 -0
- data/lib/ver/view/list/buffer.rb +27 -0
- data/lib/ver/view/list/fuzzy_file_finder.rb +44 -0
- data/lib/ver/view/list/syntax.rb +13 -0
- data/lib/ver/view/list/theme.rb +13 -0
- data/spec/keymap.rb +224 -0
- data/tasks/bacon.rake +49 -0
- data/tasks/changelog.rake +18 -0
- data/tasks/gem.rake +22 -0
- data/tasks/gem_installer.rake +76 -0
- data/tasks/grancher.rake +12 -0
- data/tasks/install_dependencies.rake +6 -0
- data/tasks/manifest.rake +4 -0
- data/tasks/plist2json.rake +35 -0
- data/tasks/rcov.rake +18 -0
- data/tasks/release.rake +12 -0
- data/tasks/reversion.rake +8 -0
- data/tasks/syntax_list.rake +31 -0
- data/ver.gemspec +29 -0
- metadata +241 -0
data/lib/ver/keymap.rb
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
module VER
|
|
2
|
+
class Keymap
|
|
3
|
+
def self.get(options)
|
|
4
|
+
name = options.fetch(:name)
|
|
5
|
+
|
|
6
|
+
find_and_load(name)
|
|
7
|
+
send(name, options)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.find(keymap_name)
|
|
11
|
+
VER.find_in_loadpath("keymap/#{keymap_name}.rb")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.find_and_load(keymap_name)
|
|
15
|
+
if path = find(keymap_name)
|
|
16
|
+
sane = path.dirname/path.basename(path.extname)
|
|
17
|
+
require sane.to_s
|
|
18
|
+
else
|
|
19
|
+
raise LoadError, "cannot find keymap: %p" % [keymap_name]
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
attr_accessor :modes, :callback, :widget, :tag
|
|
24
|
+
attr_reader :mode
|
|
25
|
+
|
|
26
|
+
def initialize(options)
|
|
27
|
+
@callback = options.fetch(:receiver)
|
|
28
|
+
@widget = options.fetch(:widget, @callback)
|
|
29
|
+
@modes = {}
|
|
30
|
+
|
|
31
|
+
prepare_tag
|
|
32
|
+
prepare_default_binds
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def send(*args)
|
|
36
|
+
@callback.__send__(*args)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def enter_key(key)
|
|
40
|
+
modes[mode].enter_key key
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def enter_missing(key)
|
|
44
|
+
modes[mode].enter_missing key
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def prepare_tag
|
|
48
|
+
self.tag = TkBindTag.new
|
|
49
|
+
tags = widget.bindtags
|
|
50
|
+
|
|
51
|
+
index = tags.index{|element| element.is_a?(Class) }
|
|
52
|
+
tags[index - 1, 0] = @tag
|
|
53
|
+
|
|
54
|
+
widget.bindtags = tags
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def prepare_default_binds
|
|
58
|
+
tag.bind 'Key' do |event|
|
|
59
|
+
case event.char
|
|
60
|
+
when ''
|
|
61
|
+
# enter_missing event.keysym
|
|
62
|
+
# p event
|
|
63
|
+
else
|
|
64
|
+
enter_missing event.char
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
Tk.callback_break
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
0.upto 9 do |n|
|
|
71
|
+
tag.bind("KeyPress-#{n}") do |key|
|
|
72
|
+
enter_key n.to_s
|
|
73
|
+
Tk.callback_break
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def register(key)
|
|
79
|
+
tag.bind(key){|event|
|
|
80
|
+
enter_key key
|
|
81
|
+
Tk.callback_break
|
|
82
|
+
}
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# TODO: callbacks
|
|
86
|
+
def mode=(cm)
|
|
87
|
+
@mode = cm.to_sym
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def add_mode(name)
|
|
91
|
+
@modes[name.to_sym] = mode = VER::Mode.new(name, self)
|
|
92
|
+
yield mode if block_given?
|
|
93
|
+
mode
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
data/lib/ver/layout.rb
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
module VER
|
|
2
|
+
class Layout < Ttk::Frame
|
|
3
|
+
attr_reader :strategy, :views
|
|
4
|
+
|
|
5
|
+
def initialize(parent, options = {})
|
|
6
|
+
super
|
|
7
|
+
|
|
8
|
+
pack(fill: :both, expand: true)
|
|
9
|
+
|
|
10
|
+
@views = []
|
|
11
|
+
self.strategy = Layout::VerticalTiling
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def strategy=(mod)
|
|
15
|
+
@strategy = mod
|
|
16
|
+
apply if @views.any?
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def create_view
|
|
20
|
+
view = View.new(self)
|
|
21
|
+
yield view
|
|
22
|
+
@views << view
|
|
23
|
+
|
|
24
|
+
apply
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def close_view(view)
|
|
28
|
+
@views.delete view
|
|
29
|
+
view.destroy
|
|
30
|
+
|
|
31
|
+
if previous = @views.last
|
|
32
|
+
apply
|
|
33
|
+
previous.focus
|
|
34
|
+
else
|
|
35
|
+
Tk.exit
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def focus_next(current)
|
|
40
|
+
return unless index = @views.index(current)
|
|
41
|
+
|
|
42
|
+
found = @views[index + 1] || @views[0]
|
|
43
|
+
found.focus
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def focus_prev(current)
|
|
47
|
+
return unless index = @views.index(current)
|
|
48
|
+
|
|
49
|
+
found = @views[index - 1]
|
|
50
|
+
found.focus
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def apply(options = {})
|
|
54
|
+
strategy.apply(self, options)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
module VerticalTiling
|
|
58
|
+
DEFAULT = { left: 1, right: -1 }
|
|
59
|
+
|
|
60
|
+
module_function
|
|
61
|
+
|
|
62
|
+
def apply(layout, options = {})
|
|
63
|
+
slaves = layout.winfo_children
|
|
64
|
+
left, right = DEFAULT.merge(options).values_at(:left, :right)
|
|
65
|
+
head, tail = slaves[0...left], slaves[left..right]
|
|
66
|
+
width = tail.size == 0 ? 1.0 : 0.5
|
|
67
|
+
head_step = 1.0 / head.size
|
|
68
|
+
tail_step = 1.0 / tail.size
|
|
69
|
+
|
|
70
|
+
head.each_with_index do |slave, idx|
|
|
71
|
+
slave.place(relx: 0.0, rely: (head_step * idx),
|
|
72
|
+
relheight: head_step, relwidth: width)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
tail.each_with_index do |slave, idx|
|
|
76
|
+
slave.place(relx: 0.5, rely: (tail_step * idx),
|
|
77
|
+
relheight: tail_step, relwidth: width)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
module HorizontalTiling
|
|
83
|
+
DEFAULT = { top: 1, bottom: -1 }
|
|
84
|
+
|
|
85
|
+
module_function
|
|
86
|
+
|
|
87
|
+
def apply(layout, options = {})
|
|
88
|
+
slaves = layout.winfo_children
|
|
89
|
+
top, bottom = DEFAULT.merge(options).values_at(:top, :bottom)
|
|
90
|
+
head, tail = slaves[0...top], slaves[top..bottom]
|
|
91
|
+
height = tail.size == 0 ? 1.0 : 0.5
|
|
92
|
+
head_step = 1.0 / head.size
|
|
93
|
+
tail_step = 1.0 / tail.size
|
|
94
|
+
|
|
95
|
+
head.each_with_index do |slave, idx|
|
|
96
|
+
slave.place(relx: (head_step * idx), rely: 0.0,
|
|
97
|
+
relheight: height, relwidth: head_step)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
tail.each_with_index do |slave, idx|
|
|
101
|
+
slave.place(relx: (tail_step * idx), rely: 0.5,
|
|
102
|
+
relheight: height, relwidth: tail_step)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
data/lib/ver/methods.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'ver/methods/move'
|
|
2
|
+
require 'ver/methods/views'
|
|
3
|
+
require 'ver/methods/insert'
|
|
4
|
+
require 'ver/methods/control'
|
|
5
|
+
require 'ver/methods/search'
|
|
6
|
+
require 'ver/methods/select'
|
|
7
|
+
require 'ver/methods/completion'
|
|
8
|
+
|
|
9
|
+
module VER
|
|
10
|
+
module Methods
|
|
11
|
+
include Move
|
|
12
|
+
include Views
|
|
13
|
+
include Insert
|
|
14
|
+
include Control
|
|
15
|
+
include Search
|
|
16
|
+
include Select
|
|
17
|
+
include Completion
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
module VER
|
|
2
|
+
module Methods
|
|
3
|
+
module Completion
|
|
4
|
+
def complete_file
|
|
5
|
+
files = file_completions
|
|
6
|
+
complete(files)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def complete_aspell
|
|
10
|
+
words = aspell_completions
|
|
11
|
+
complete(words)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def file_completions
|
|
15
|
+
word = get('insert wordstart', 'insert wordend')
|
|
16
|
+
|
|
17
|
+
glob = "#{word}*{**/*,/**/*}"
|
|
18
|
+
p glob
|
|
19
|
+
Dir[glob].uniq
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def aspell_completions
|
|
23
|
+
word = get('insert wordstart', 'insert wordend')
|
|
24
|
+
|
|
25
|
+
if result = aspell_execute(word)[word]
|
|
26
|
+
result[:suggestions]
|
|
27
|
+
else
|
|
28
|
+
[word]
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
ASPELL_PARSE = /^& (.*?) (\d+) (\d+): (.*)$/
|
|
33
|
+
|
|
34
|
+
def aspell_execute(word)
|
|
35
|
+
require 'open3'
|
|
36
|
+
results = {}
|
|
37
|
+
|
|
38
|
+
Open3.popen3("aspell pipe") do |stdin, stdout, stderr|
|
|
39
|
+
stdin.print("^#{word}")
|
|
40
|
+
stdin.close
|
|
41
|
+
result = stdout.read
|
|
42
|
+
|
|
43
|
+
result.scan(ASPELL_PARSE) do |original, count, offset, suggestions|
|
|
44
|
+
results[original] = {
|
|
45
|
+
count: count.to_i,
|
|
46
|
+
offset: offset.to_i,
|
|
47
|
+
suggestions: suggestions.split(/\s*,\s*/),
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
return results
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def complete(words)
|
|
56
|
+
return if words.empty?
|
|
57
|
+
|
|
58
|
+
x, y = caret.values_at('x', 'y')
|
|
59
|
+
longest_word = words.map{|word| word.size }.max
|
|
60
|
+
|
|
61
|
+
list = Tk::Listbox.new(self){
|
|
62
|
+
borderwidth 0
|
|
63
|
+
width longest_word + 2
|
|
64
|
+
height words.size
|
|
65
|
+
place x: x, y: y
|
|
66
|
+
focus
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
list.value = words
|
|
70
|
+
list.selection_set 0
|
|
71
|
+
|
|
72
|
+
# go down
|
|
73
|
+
list.bind('j'){|event|
|
|
74
|
+
index = list.curselection.first + 1
|
|
75
|
+
max = list.size
|
|
76
|
+
|
|
77
|
+
if index < max
|
|
78
|
+
list.selection_clear(0, 'end')
|
|
79
|
+
list.selection_set(index)
|
|
80
|
+
list.activate(index)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
Tk.callback_break
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
# go up
|
|
87
|
+
list.bind('k'){|event|
|
|
88
|
+
index = list.curselection.first - 1
|
|
89
|
+
|
|
90
|
+
if index >= 0
|
|
91
|
+
list.selection_clear(0, 'end')
|
|
92
|
+
list.selection_set(index)
|
|
93
|
+
list.activate(index)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
Tk.callback_break
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
list.bind('Return'){|event|
|
|
100
|
+
index = list.curselection.first
|
|
101
|
+
replacement = list.get(index)
|
|
102
|
+
replace('insert wordstart', 'insert wordend', replacement)
|
|
103
|
+
focus
|
|
104
|
+
list.destroy
|
|
105
|
+
Tk.callback_break
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
list.bind('Escape'){|event|
|
|
109
|
+
focus
|
|
110
|
+
list.destroy
|
|
111
|
+
Tk.callback_break
|
|
112
|
+
}
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
module VER
|
|
2
|
+
module Methods
|
|
3
|
+
module Control
|
|
4
|
+
def status_theme_select
|
|
5
|
+
return unless @syntax
|
|
6
|
+
|
|
7
|
+
status_ask 'Theme name: ' do |name|
|
|
8
|
+
load_theme(name) || "No theme called #{name} found"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def theme_switch
|
|
13
|
+
return unless @syntax
|
|
14
|
+
|
|
15
|
+
View::List::Theme.new(self){|name| load_theme(name) }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def syntax_switch
|
|
19
|
+
return unless @syntax
|
|
20
|
+
|
|
21
|
+
View::List::Syntax.new(self){|name| load_syntax(name) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def status_evaluate
|
|
25
|
+
status_ask 'Eval expression: ' do |term|
|
|
26
|
+
eval(term)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def status_ask(prompt, &callback)
|
|
31
|
+
@status.ask(prompt){|*args|
|
|
32
|
+
begin
|
|
33
|
+
callback.call(*args)
|
|
34
|
+
rescue => ex
|
|
35
|
+
p ex
|
|
36
|
+
status.message ex.message
|
|
37
|
+
ensure
|
|
38
|
+
focus
|
|
39
|
+
end
|
|
40
|
+
}
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def smart_evaluate
|
|
44
|
+
from, to = tag_ranges(:sel).first
|
|
45
|
+
|
|
46
|
+
if from && to
|
|
47
|
+
selection_evaluate
|
|
48
|
+
else
|
|
49
|
+
line_evaluate
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def line_evaluate
|
|
54
|
+
text = get('insert linestart', 'insert lineend')
|
|
55
|
+
result = eval(text)
|
|
56
|
+
insert("insert lineend", "\n#{result.inspect}\n")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def buffer_switch
|
|
60
|
+
View::List::Buffer.new self do |file|
|
|
61
|
+
|
|
62
|
+
# VER.resume_buffer file_path
|
|
63
|
+
open_path file if File.exists? file
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def window_switch(count = nil)
|
|
68
|
+
if count
|
|
69
|
+
p count: count
|
|
70
|
+
else
|
|
71
|
+
View::List::Window.new self do |view|
|
|
72
|
+
view.focus
|
|
73
|
+
# open_path(path)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def file_save
|
|
79
|
+
save_to(filename)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def file_save_popup
|
|
83
|
+
filetypes = [
|
|
84
|
+
['ALL Files', '*' ],
|
|
85
|
+
['Text Files', '*.txt'],
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
filename = ::File.basename @filename
|
|
89
|
+
extension = ::File.extname @filename
|
|
90
|
+
directory = ::File.dirname @filename
|
|
91
|
+
|
|
92
|
+
fpath = Tk.getSaveFile(
|
|
93
|
+
initialfile: filename,
|
|
94
|
+
initialdir: directory,
|
|
95
|
+
defaultextension: extension,
|
|
96
|
+
filetypes: filetypes
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
return if fpath.empty?
|
|
100
|
+
|
|
101
|
+
save_to(fpath)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Some strategies are discussed at:
|
|
105
|
+
#
|
|
106
|
+
# http://bitworking.org/news/390/text-editor-saving-routines
|
|
107
|
+
#
|
|
108
|
+
# I try another, "wasteful" approach, copying the original file to a
|
|
109
|
+
# temporary location, overwriting the contents in the copy, then moving the
|
|
110
|
+
# file to the location of the original file.
|
|
111
|
+
#
|
|
112
|
+
# This way all permissions should be kept identical without any effort, but
|
|
113
|
+
# it will take up additional disk space.
|
|
114
|
+
#
|
|
115
|
+
# If there is some failure during the normal saving procedure, we will
|
|
116
|
+
# simply overwrite the original file in place, make sure you have good insurance ;)
|
|
117
|
+
def save_to(to)
|
|
118
|
+
save_smart(filename, to)
|
|
119
|
+
rescue => ex
|
|
120
|
+
puts "#{ex.class}: #{ex}", *ex.backtrace
|
|
121
|
+
save_dumb(filename, to)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def save_smart(from, to)
|
|
125
|
+
sha1 = Digest::SHA1.hexdigest([from, to].join)
|
|
126
|
+
temp_path = File.join(Dir.tmpdir, 'ver', sha1)
|
|
127
|
+
temp_dir = File.dirname(temp_path)
|
|
128
|
+
|
|
129
|
+
FileUtils.mkdir_p(temp_dir)
|
|
130
|
+
FileUtils.copy_file(from, temp_path, preserve = true)
|
|
131
|
+
File.open(temp_path, 'w+') do |io|
|
|
132
|
+
io.write(self.value)
|
|
133
|
+
end
|
|
134
|
+
FileUtils.mv(temp_path, to)
|
|
135
|
+
|
|
136
|
+
status.message "Saved to #{to}"
|
|
137
|
+
rescue Errno::ENOENT
|
|
138
|
+
save_dumb(to)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def save_dumb(to)
|
|
142
|
+
File.open(to, 'w+') do |io|
|
|
143
|
+
io.write(self.value)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
status.message "Saved to #{to}"
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def file_open_popup
|
|
150
|
+
filetypes = [
|
|
151
|
+
['ALL Files', '*' ],
|
|
152
|
+
['Text Files', '*.txt'],
|
|
153
|
+
]
|
|
154
|
+
|
|
155
|
+
fpath = Tk.getOpenFile(filetypes: filetypes)
|
|
156
|
+
|
|
157
|
+
return if fpath.empty?
|
|
158
|
+
|
|
159
|
+
open_path(fpath)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def file_open_fuzzy
|
|
163
|
+
View::List::FuzzyFileFinder.new self do |path|
|
|
164
|
+
open_path(path)
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def delete_char_left
|
|
169
|
+
delete 'insert - 1 char'
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def delete_char_right
|
|
173
|
+
delete 'insert'
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def delete_word_right
|
|
177
|
+
delete 'insert', 'insert wordend'
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def delete_word_left
|
|
181
|
+
delete 'insert wordstart', 'insert'
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def delete_line
|
|
185
|
+
delete 'insert linestart', 'insert lineend + 1 char'
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def delete_to_eol
|
|
189
|
+
delete 'insert', 'insert lineend'
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def delete_to_eol_then_insert
|
|
193
|
+
delete_to_eol
|
|
194
|
+
start_insert_mode
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def join_lines
|
|
198
|
+
start_of_next_line = search(/\S/, 'insert lineend')
|
|
199
|
+
replace('insert lineend', start_of_next_line, ' ')
|
|
200
|
+
rescue RuntimeError => exception
|
|
201
|
+
return if exception.message =~ /Index "\d+\.\d+" before "insert lineend" in the text/
|
|
202
|
+
raise exception
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def insert_string(string)
|
|
206
|
+
# puts "Insert %p in mode %p" % [string, keymap.mode]
|
|
207
|
+
insert :insert, string unless string.empty?
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def ignore_string(string)
|
|
211
|
+
status.message "Ignore %p in mode %p" % [string, keymap.mode]
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def replace_char
|
|
215
|
+
status_ask 'Replace with: ' do |string|
|
|
216
|
+
replace('insert', 'insert + 1 chars', string)
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def indent_line
|
|
221
|
+
insert('insert linestart', ' ')
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def unindent_line
|
|
225
|
+
line = get('insert linestart', 'insert lineend')
|
|
226
|
+
|
|
227
|
+
return unless line =~ /^(\s\s?)/
|
|
228
|
+
|
|
229
|
+
replace(
|
|
230
|
+
'insert linestart',
|
|
231
|
+
"insert linestart + #{$1.size} chars",
|
|
232
|
+
''
|
|
233
|
+
)
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def insert_indented_newline_below
|
|
237
|
+
line = get('insert linestart', 'insert lineend')
|
|
238
|
+
|
|
239
|
+
indent = line.empty? ? "" : (line[/^\s+/] || '')
|
|
240
|
+
mark_set :insert, 'insert lineend'
|
|
241
|
+
insert :insert, "\n#{indent}"
|
|
242
|
+
|
|
243
|
+
start_insert_mode
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def insert_indented_newline_above
|
|
247
|
+
y, x = index(:insert).split('.').map(&:to_i)
|
|
248
|
+
|
|
249
|
+
if y > 1
|
|
250
|
+
go_line_up
|
|
251
|
+
insert_indented_newline_below
|
|
252
|
+
else
|
|
253
|
+
insert('insert linestart', "\n")
|
|
254
|
+
mark_set(:insert, 'insert - 1 line')
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def insert_newline
|
|
259
|
+
insert :insert, "\n"
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def insert_indented_newline
|
|
263
|
+
line1 = get('insert linestart', 'insert lineend')
|
|
264
|
+
indentation1 = line1[/^\s+/] || ''
|
|
265
|
+
insert :insert, "\n"
|
|
266
|
+
|
|
267
|
+
line2 = get('insert linestart', 'insert lineend')
|
|
268
|
+
indentation2 = line2[/^\s+/] || ''
|
|
269
|
+
|
|
270
|
+
replace(
|
|
271
|
+
'insert linestart',
|
|
272
|
+
"insert linestart + #{indentation2.size} chars",
|
|
273
|
+
indentation1
|
|
274
|
+
)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def insert_tab
|
|
278
|
+
insert :insert, "\t"
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def eol_then_insert_mode
|
|
282
|
+
go_end_of_line
|
|
283
|
+
start_insert_mode
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def sol_then_insert_mode
|
|
287
|
+
go_beginning_of_line
|
|
288
|
+
start_insert_mode
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def start_insert_mode
|
|
292
|
+
self.mode = :insert
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def start_control_mode
|
|
296
|
+
self.mode = :control
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def copy_line
|
|
300
|
+
copy get('insert linestart', 'insert lineend + 1 chars')
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def copy_right_word
|
|
304
|
+
copy get('insert', 'insert wordend')
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def copy_left_word
|
|
308
|
+
copy get('insert', 'insert wordstart')
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
# FIXME: nasty hack or neccesary?
|
|
312
|
+
def paste
|
|
313
|
+
text = TkClipboard.get
|
|
314
|
+
paste_continous text
|
|
315
|
+
|
|
316
|
+
rescue RuntimeError => ex
|
|
317
|
+
if ex.message =~ /form "STRING" not defined/
|
|
318
|
+
array = TkClipboard.get type: Array
|
|
319
|
+
paste_tk_array array
|
|
320
|
+
else
|
|
321
|
+
Kernel.raise ex
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def undo
|
|
326
|
+
edit_undo
|
|
327
|
+
touch!
|
|
328
|
+
rescue RuntimeError => ex
|
|
329
|
+
status.value = ex.message
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def redo
|
|
333
|
+
edit_redo
|
|
334
|
+
touch!
|
|
335
|
+
rescue RuntimeError => ex
|
|
336
|
+
status.value = ex.message
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
end
|