Class: VER::Buffer
- Inherits:
-
Text
- Object
- Tk::Text
- Text
- VER::Buffer
show all
- Extended by:
- Forwardable
- Includes:
- Keymapped
- Defined in:
- lib/ver/methods/save.rb,
lib/ver/buffer.rb,
lib/ver/buffer/frame.rb,
lib/ver/methods/move.rb,
lib/ver/methods/basic.rb,
lib/ver/buffer/console.rb,
lib/ver/methods/delete.rb,
lib/ver/buffer/matching_brace.rb,
lib/ver/buffer/markup_underline_link.rb,
lib/ver/buffer/invalid_trailing_whitespace.rb
Overview
Some strategies are discussed at:
bitworking.org/news/390/text-editor-saving-routines
I try another, “wasteful” approach, copying the original file to a temporary location, overwriting the contents in the copy, then moving the file to the location of the original file.
This way all permissions should be kept identical without any effort, but it will take up additional disk space.
If there is some failure during the normal saving procedure, we will simply overwrite the original file in place, make sure you have good insurance ;)
TODO: we must write backup files, VER can corrupt files on a system
crash for some reason.
Defined Under Namespace
Classes: Console, Frame, HighlightPending, InvalidTrailingWhitespace, MarkupUnderlineLink, MatchingBrace, Terminal
Constant Summary
collapse
- OPTIONS =
{
autoseparators: false,
background: '#000',
blockcursor: false,
borderwidth: 0,
exportselection: true, foreground: '#fff', highlightbackground: '#000', highlightcolor: '#fff', highlightthickness: 1, insertbackground: '#fff',
relief: :solid,
setgrid: false,
tabstyle: :wordprocessor,
takefocus: true,
undo: false,
wrap: :word
}
- MODE_STYLES =
{
:control => {blockcursor: false},
:insert => {blockcursor: false, insertbackground: 'red'},
/select/ => {blockcursor: true, insertbackground: 'yellow'},
/replace/ => {blockcursor: true, insertbackground: 'orange'},
}
- TAG_ALL_MATCHING_OPTIONS =
{ from: '1.0', to: 'end - 1 chars' }
- PROJECT_DIRECTORY_GLOB =
'{.git/,.hg/,_darcs/,_FOSSIL_}'
- MODELINES =
{
/\s+(?:ver|vim?|ex):\s*.*$/ => /\s+(?:ver|vim?|ex):\s*(.*)$/,
/\s+(?:ver|vim?|ex):[^:]+:/ => /\s+(?:ver|vim?|ex):([^:]+):/,
/^(?:ver|vim?):[^:]+:/ => /^(?:ver|vim?):([^:]+):/,
}
- REPEAT_BREAK_CMD =
[
:repeat_action,
:undo,
:redo,
]
- REPEAT_BREAK_MODE =
[
:move,
:search,
]
- None =
Object.new
Instance Attribute Summary collapse
Attributes included from Keymapped
#major_mode
Attributes inherited from Text
#lock
Class Method Summary
collapse
Instance Method Summary
collapse
-
#actions ⇒ Object
-
#after_open(syntax = nil, line = nil, char = nil) ⇒ Object
-
#apply_modeline ⇒ Object
-
#apply_modeline_option(option) ⇒ Object
-
#apply_preferences ⇒ Object
-
#ask(prompt, options = {}, &action) ⇒ Object
-
#ask_go_line ⇒ Object
-
#backward_scroll(count = buffer.prefix_count) ⇒ Object
-
#change_register ⇒ Object
-
#close ⇒ Object
-
#default_theme_config=(config) ⇒ Object
-
#delete(*indices) ⇒ Object
-
#delete_trailing_whitespace ⇒ Object
Tag and delete all trailing whitespace in the Buffer.
-
#detect_project_paths ⇒ Object
-
#eval_buffer ⇒ Object
Eval the value of Buffer in toplevel binding.
-
#events ⇒ Object
-
#finalize_open(syntax) ⇒ Object
-
#forward_scroll(count = buffer.prefix_count) ⇒ Object
-
#handle_pending_syntax_highlights ⇒ Object
-
#hide ⇒ Object
-
#initialize(parent = VER.layout, given_options = {}) ⇒ Buffer
constructor
A new instance of Buffer.
-
#insert(*args) ⇒ Object
-
#insert=(position) ⇒ Object
-
#load_info ⇒ Object
-
#load_preferences ⇒ Object
-
#load_snippets ⇒ Object
-
#load_syntax(name) ⇒ Object
-
#load_theme(name) ⇒ Object
-
#lock_uri(uri, &block) ⇒ Object
-
#may_close ⇒ Object
-
#may_save(as = nil) ⇒ Object
-
#message(*args) ⇒ Object
-
#name=(name) ⇒ Object
-
#on_destroy(event) ⇒ Object
-
#on_enter_minor_mode(event) ⇒ Object
-
#on_focus_in(event) ⇒ Object
-
#on_focus_out(event) ⇒ Object
-
#on_modified(event) ⇒ Object
-
#on_movement(event) ⇒ Object
-
#open(uri, line = 1, char = 0) ⇒ Object
-
#open_empty(line, char) ⇒ Object
-
#open_pathname(pathname, line, char) ⇒ Object
-
#open_symbolic(symbol, line, char) ⇒ Object
-
#open_uri(uri, line, char) ⇒ Object
-
#parse_go_line(input) ⇒ Object
-
#persist_info ⇒ Object
This has to be called before <Destroy> is received, otherwise the Buffer is half-dead.
-
#persisted? ⇒ Boolean
-
#prefix_arg_sol ⇒ Object
-
#prefix_count(default = 1) ⇒ Object
Same as [prefix_arg], but returns 1 if there is no argument.
-
#quit ⇒ Object
Close one buffer after another, wait when one needs user input.
-
#redo ⇒ Object
-
#repeat_action ⇒ Object
-
#replace(*args) ⇒ Object
-
#rsearch_all(regexp, start = 'end', stop = '1.0') ⇒ Object
-
#save(filename = self.filename, &block) ⇒ Object
-
#save_all ⇒ Object
Save all buffers in ordered fashion, take into account that some buffers might require user interaction.
-
#save_as ⇒ Object
-
#save_atomic(from, to, &block) ⇒ Object
Try to copy the file we want to save to a temp dir, trying to preserve permissions.
-
#save_dumb(to, &block) ⇒ Object
-
#save_popup(options = {}, &block) ⇒ Object
-
#save_to(to, &block) ⇒ Object
-
#search_all(regexp, start = '1.0', stop = 'end - 1 chars') ⇒ Object
-
#set(option, value) ⇒ Object
-
#set_filetype(type) ⇒ Object
-
#setup ⇒ Object
-
#setup_binds ⇒ Object
-
#setup_highlight ⇒ Object
-
#setup_highlight_for(syntax) ⇒ Object
-
#setup_layout ⇒ Object
-
#setup_misc ⇒ Object
-
#setup_tags ⇒ Object
-
#setup_widgets ⇒ Object
-
#short_filename ⇒ Object
-
#show ⇒ Object
-
#store(namespace, key, value = None) ⇒ Object
-
#success(message) ⇒ Object
-
#sync_encoding_status ⇒ Object
-
#sync_mode_status ⇒ Object
-
#sync_mode_style(given_mode = nil) ⇒ Object
-
#sync_percent_status ⇒ Object
-
#sync_position_status ⇒ Object
-
#tag_all_matching(name, regexp, options = {}) ⇒ Object
-
#tag_exists?(given_path) ⇒ Boolean
-
#tags_tooltip(count = prefix_arg) ⇒ Object
Display a tooltip for the tags the insert cursor is on.
-
#tooltip(string, timeout = 5) ⇒ Object
-
#touch!(*indices) ⇒ Object
-
#type(string) ⇒ Object
-
#undo ⇒ Object
-
#undo_record(&block) ⇒ Object
Use this method in commands that do multiple insert, delete, replace.
-
#unlock_uri(uri = self.uri) ⇒ Object
-
#up_down_displayline(count) ⇒ Object
OK, finally found the issue.
-
#up_down_line(count) ⇒ Object
This method goes up and down lines, not taking line wrapping into account.
-
#update_mtime ⇒ Object
-
#update_prefix_arg ⇒ Object
-
#uri_lockfile(uri = self.uri) ⇒ Object
-
#warn(*args) ⇒ Object
-
#with_register ⇒ Object
Methods included from Keymapped
#minor_mode, #minor_mode?
Methods inherited from Text
#execute, #execute_only, #focus, #index, #inspect, #mark, #mark_next, #mark_previous, #marks, #place_forget, #range, #tag, #tag_ranges, #tags
Constructor Details
#initialize(parent = VER.layout, given_options = {}) ⇒ Buffer
Returns a new instance of Buffer.
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
# File 'lib/ver/buffer.rb', line 106
def initialize(parent = VER.layout, given_options = {})
@layout = parent
@frame = Frame.new(parent, self)
font, tabstop = VER.options.font, VER.options.tabstop
tabs = font.measure('0') * tabstop
default_options = OPTIONS.merge(
font: font,
insertofftime: VER.options.insertofftime,
insertontime: VER.options.insertontime,
tabs: tabs
)
super(frame, default_options.merge(given_options))
setup
end
|
Instance Attribute Details
#at_current ⇒ Object
Returns the value of attribute at_current.
92
93
94
|
# File 'lib/ver/buffer.rb', line 92
def at_current
@at_current
end
|
#at_end ⇒ Object
Returns the value of attribute at_end.
92
93
94
|
# File 'lib/ver/buffer.rb', line 92
def at_end
@at_end
end
|
#at_insert ⇒ Object
Returns the value of attribute at_insert.
92
93
94
|
# File 'lib/ver/buffer.rb', line 92
def at_insert
@at_insert
end
|
#at_sel ⇒ Object
Returns the value of attribute at_sel.
95
96
97
|
# File 'lib/ver/buffer.rb', line 95
def at_sel
@at_sel
end
|
#encoding ⇒ Object
Returns the value of attribute encoding.
95
96
97
|
# File 'lib/ver/buffer.rb', line 95
def encoding
@encoding
end
|
#filename ⇒ Object
Returns the value of attribute filename.
95
96
97
|
# File 'lib/ver/buffer.rb', line 95
def filename
@filename
end
|
#frame ⇒ Object
Returns the value of attribute frame.
92
93
94
|
# File 'lib/ver/buffer.rb', line 92
def frame
@frame
end
|
#layout ⇒ Object
Returns the value of attribute layout.
92
93
94
|
# File 'lib/ver/buffer.rb', line 92
def layout
@layout
end
|
#locked ⇒ Object
Also known as:
locked?
Returns the value of attribute locked.
95
96
97
|
# File 'lib/ver/buffer.rb', line 95
def locked
@locked
end
|
#matching_brace ⇒ Object
Returns the value of attribute matching_brace.
92
93
94
|
# File 'lib/ver/buffer.rb', line 92
def matching_brace
@matching_brace
end
|
#minibuf ⇒ Object
Returns the value of attribute minibuf.
92
93
94
|
# File 'lib/ver/buffer.rb', line 92
def minibuf
@minibuf
end
|
#options ⇒ Object
Returns the value of attribute options.
92
93
94
|
# File 'lib/ver/buffer.rb', line 92
def options
@options
end
|
#prefix_arg ⇒ Object
Returns the value of attribute prefix_arg.
95
96
97
|
# File 'lib/ver/buffer.rb', line 95
def prefix_arg
@prefix_arg
end
|
#pristine ⇒ Object
Also known as:
pristine?
Returns the value of attribute pristine.
95
96
97
|
# File 'lib/ver/buffer.rb', line 95
def pristine
@pristine
end
|
#project_repo ⇒ Object
Returns the value of attribute project_repo.
95
96
97
|
# File 'lib/ver/buffer.rb', line 95
def project_repo
@project_repo
end
|
#project_root ⇒ Object
Returns the value of attribute project_root.
95
96
97
|
# File 'lib/ver/buffer.rb', line 95
def project_root
@project_root
end
|
#readonly ⇒ Object
Returns the value of attribute readonly.
95
96
97
|
# File 'lib/ver/buffer.rb', line 95
def readonly
@readonly
end
|
#register ⇒ Object
Returns the value of attribute register.
95
96
97
|
# File 'lib/ver/buffer.rb', line 95
def register
@register
end
|
#skip_prefix_count_once ⇒ Object
Returns the value of attribute skip_prefix_count_once.
95
96
97
|
# File 'lib/ver/buffer.rb', line 95
def skip_prefix_count_once
@skip_prefix_count_once
end
|
#snippets ⇒ Object
Returns the value of attribute snippets.
92
93
94
|
# File 'lib/ver/buffer.rb', line 92
def snippets
@snippets
end
|
#status ⇒ Object
Returns the value of attribute status.
92
93
94
|
# File 'lib/ver/buffer.rb', line 92
def status
@status
end
|
#symbolic ⇒ Object
Also known as:
symbolic?
Returns the value of attribute symbolic.
95
96
97
|
# File 'lib/ver/buffer.rb', line 95
def symbolic
@symbolic
end
|
#syntax ⇒ Object
Returns the value of attribute syntax.
92
93
94
|
# File 'lib/ver/buffer.rb', line 92
def syntax
@syntax
end
|
#theme_config ⇒ Object
Returns the value of attribute theme_config.
92
93
94
|
# File 'lib/ver/buffer.rb', line 92
def theme_config
@theme_config
end
|
#undoer ⇒ Object
Returns the value of attribute undoer.
95
96
97
|
# File 'lib/ver/buffer.rb', line 95
def undoer
@undoer
end
|
#uri ⇒ Object
Returns the value of attribute uri.
95
96
97
|
# File 'lib/ver/buffer.rb', line 95
def uri
@uri
end
|
Class Method Details
.[](uri, line = nil, char = nil) ⇒ Object
60
61
62
|
# File 'lib/ver/buffer.rb', line 60
def self.[](uri, line = nil, char = nil)
find_or_create(uri, line, char)
end
|
.create(path = nil, line = nil, char = nil) ⇒ Object
64
65
66
67
68
69
70
|
# File 'lib/ver/buffer.rb', line 64
def self.create(path = nil, line = nil, char = nil)
VER.layout.create_buffer do |buffer|
buffer.open(path, line, char)
yield(buffer) if block_given?
buffer
end
end
|
.find_or_create(uri, line = nil, char = nil, &block) ⇒ Object
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
# File 'lib/ver/buffer.rb', line 72
def self.find_or_create(uri, line = nil, char = nil, &block)
case uri
when Pathname, Symbol
if buffer = VER.buffers.find{|buf| buf.uri == uri }
buffer.show
buffer.focus
buffer.at_insert.go_line_char(line, char)
yield buffer if block_given?
buffer
else
create(uri, line, char, &block)
end
when String
path = Pathname(uri.to_str).expand_path
find_or_create(path, line, char, &block)
else
raise ArgumentError, "Invalid path: %p" % [path]
end
end
|
Instance Method Details
#actions ⇒ Object
304
305
306
|
# File 'lib/ver/buffer.rb', line 304
def actions
major_mode.action_history
end
|
#after_open(syntax = nil, line = nil, char = nil) ⇒ Object
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
|
# File 'lib/ver/buffer.rb', line 477
def after_open(syntax = nil, line = nil, char = nil)
@undoer = VER::Undo::Tree.new(self)
VER.opened_file(self)
layout.wm_title = uri.to_s
info = load_info
if line || char
self.insert = "#{line || 1}.#{char || 0}"
else
self.insert = info['insert'] || '1.0'
end
VER.buffers << self
message "Opened #{uri}"
finalize_open(syntax || info['syntax'])
rescue => ex
VER.error(ex)
end
|
#apply_modeline ⇒ Object
607
608
609
610
611
612
613
614
615
616
617
618
619
620
|
# File 'lib/ver/buffer.rb', line 607
def apply_modeline
MODELINES.each do |search_pattern, |
found = search(search_pattern, 1.0, :end, :count)
next if found.empty?
pos, count = found
line = get(pos, "#{pos} + #{count} chars")
line =~
$1.scan(/[^:\s]+/) do |option|
apply_modeline_option(option)
end
end
end
|
#apply_modeline_option(option) ⇒ Object
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
|
# File 'lib/ver/buffer.rb', line 622
def apply_modeline_option(option)
negative = option.gsub!(/^no/, '')
boolean = !negative
case option
when 'ai', 'autoindent'
set :autoindent, boolean
when 'et', 'expandtab'
set :expandtab, boolean
when /(?:tw|textwidth)=(\d+)/
set :textwidth, $1.to_i
when /(?:ts|tabstop)=(\d+)/
set :tabstop, $1.to_i
when /(?:sw|shiftwidth)=(\d+)/
set :shiftwidth, $1.to_i
when /(?:ft|filetype)=(\w+)/
set :filetype, $1
else
VER.warn "Unknown modeline: %p" % [option]
end
end
|
#apply_preferences ⇒ Object
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
|
# File 'lib/ver/buffer.rb', line 984
def apply_preferences
return unless @preferences
@preferences.each do |preference|
next unless preference[:name] == "Comments"
if settings = preference[:settings]
if shell_variables = settings[:shellVariables]
shell_variables.each do |variable|
name, value = variable.values_at(:name, :value)
ENV[name] = value
case name
when 'TM_COMMENT_START'
options. = value
end
end
end
end
end
end
|
#ask(prompt, options = {}, &action) ⇒ Object
1034
1035
1036
1037
|
# File 'lib/ver/buffer.rb', line 1034
def ask(prompt, options = {}, &action)
options[:caller] ||= self
@minibuf.ask(prompt, options, &action)
end
|
#ask_go_line ⇒ Object
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
# File 'lib/ver/methods/move.rb', line 20
def ask_go_line
initial = $1 if events.last[:unicode] =~ /^(\d+)$/
question = 'Go to [line number|+lines][,column number]: '
ask(question, value: initial) do |answer, action|
case action
when :attempt
parse_go_line(answer) do |index|
self.insert = index
:abort
end
when :modified
parse_go_line(answer) do |index|
tag_configure(Methods::Search::TAG, Methods::Search::HIGHLIGHT)
tag_add(Methods::Search::TAG, index, index.lineend)
see(index)
Tk::After.ms(3000){
tag_remove(Methods::Search::TAG, index, index.lineend)
at_insert.see
}
end
end
end
end
|
14
15
16
17
18
|
# File 'lib/ver/methods/move.rb', line 14
def backward_scroll(count = buffer.prefix_count)
count_abs = count.abs
yview_scroll(-count_abs, :units)
prev_line(count_abs)
end
|
#change_register ⇒ Object
711
712
713
714
715
716
717
718
719
720
721
722
723
|
# File 'lib/ver/buffer.rb', line 711
def change_register
major_mode.read(1) do |name|
if unicode = name.unicode
if unicode.empty?
warn "invalid name for register: %p" % [name]
else
self.register = Register[unicode]
end
else
warn "invalid name for register: %p" % [name]
end
end
end
|
#close ⇒ Object
675
676
677
678
679
680
|
# File 'lib/ver/buffer.rb', line 675
def close
may_close do
persist_info
layout.destroy
end
end
|
#default_theme_config=(config) ⇒ Object
1029
1030
1031
1032
|
# File 'lib/ver/buffer.rb', line 1029
def default_theme_config=(config)
@theme_config = config
sync_mode_style
end
|
#delete(*indices) ⇒ Object
366
367
368
369
370
371
372
|
# File 'lib/ver/buffer.rb', line 366
def delete(*indices)
return super unless undoer
undo_record do |record|
record.delete(*indices)
end
end
|
#delete_trailing_whitespace ⇒ Object
Tag and delete all trailing whitespace in the VER::Buffer.
4
5
6
7
8
|
# File 'lib/ver/methods/delete.rb', line 4
def delete_trailing_whitespace
@invalid_trailing_whitespace.each_range do |range|
range.delete
end
end
|
#detect_project_paths ⇒ Object
592
593
594
595
596
597
598
599
600
601
602
603
604
605
|
# File 'lib/ver/buffer.rb', line 592
def detect_project_paths
return unless filename
parent = filename.expand_path.dirname
begin
(parent/PROJECT_DIRECTORY_GLOB).glob do |repo|
self.project_repo = repo
self.project_root = repo.dirname
return
end
parent = parent.dirname
end until parent.root?
end
|
#eval_buffer ⇒ Object
Eval the value of VER::Buffer in toplevel binding. So while hacking VER you can dynamically reload parts of it.
5
6
7
8
|
# File 'lib/ver/methods/basic.rb', line 5
def eval_buffer
message "Source #{uri}"
TOPLEVEL_BINDING.eval(value.to_s)
end
|
#events ⇒ Object
300
301
302
|
# File 'lib/ver/buffer.rb', line 300
def events
major_mode.event_history
end
|
#finalize_open(syntax) ⇒ Object
499
500
501
502
503
504
505
506
|
# File 'lib/ver/buffer.rb', line 499
def finalize_open(syntax)
VER.defer do
syntax ? setup_highlight_for(syntax) : setup_highlight
load_preferences
apply_modeline
end
bind('<Map>'){ at_insert.see }
end
|
8
9
10
11
12
|
# File 'lib/ver/methods/move.rb', line 8
def forward_scroll(count = buffer.prefix_count)
count_abs = count.abs
yview_scroll(count_abs, :units)
next_line(count_abs)
end
|
#handle_pending_syntax_highlights ⇒ Object
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
|
# File 'lib/ver/buffer.rb', line 1005
def handle_pending_syntax_highlights
ignore_tags = %w[ver.highlight.pending sel]
tag_ranges('ver.highlight.pending').each do |range|
from, to = range.first, range.last
(tag_names(from) - ignore_tags).each do |tag_name|
tag_from, _ = tag_prevrange(tag_name, from)
from = tag_from if tag_from && from > tag_from
end
(tag_names(to) - ignore_tags).each do |tag_name|
_, tag_to = (tag_name, to)
to = tag_to if tag_to && to < tag_to
end
from, to = index("#{from} linestart"), index("#{to} lineend")
syntax.highlight(self, from.line - 1, from, to) if syntax
@invalid_trailing_whitespace.refresh(from: from, to: to)
@markup_underline_link.refresh(from: from, to: to)
tag_remove('ver.highlight.pending', from, to)
end
end
|
#hide ⇒ Object
667
668
669
|
# File 'lib/ver/buffer.rb', line 667
def hide
layout.hide
end
|
#insert(*args) ⇒ Object
382
383
384
385
386
387
388
|
# File 'lib/ver/buffer.rb', line 382
def insert(*args)
return super unless undoer
undo_record do |record|
record.insert(*args)
end
end
|
#insert=(position) ⇒ Object
362
363
364
|
# File 'lib/ver/buffer.rb', line 362
def insert=(position)
at_insert.index = position
end
|
#load_info ⇒ Object
250
251
252
253
254
255
256
257
258
259
260
|
# File 'lib/ver/buffer.rb', line 250
def load_info
file = VER.loadpath.first/'buffer_info.json'
l "Loading Buffer info from: #{file}"
JSON::Store.new(file.to_s, true).transaction do |buffer_info|
if info = buffer_info[uri.to_s]
return info
end
end
return {}
end
|
#load_preferences ⇒ Object
973
974
975
976
977
978
979
980
981
982
|
# File 'lib/ver/buffer.rb', line 973
def load_preferences
return unless syntax
name = syntax.name
return unless file = VER.find_in_loadpath("preferences/#{name}.rb")
@preferences = eval(file.read)
apply_preferences
rescue Errno::ENOENT, TypeError => ex
VER.error(ex)
end
|
#load_snippets ⇒ Object
963
964
965
966
967
968
969
970
971
|
# File 'lib/ver/buffer.rb', line 963
def load_snippets
return unless syntax
name = syntax.name
return unless file = VER.find_in_loadpath("snippets/#{name}.rb")
@snippets = eval(file.read)
rescue Errno::ENOENT, TypeError => ex
VER.error(ex)
end
|
#load_syntax(name) ⇒ Object
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
|
# File 'lib/ver/buffer.rb', line 947
def load_syntax(name)
return false unless syntax
theme = syntax.theme
if name.is_a?(Syntax)
self.syntax = Syntax.new(name.name, theme)
elsif found = Syntax.find(name)
self.syntax = Syntax.new(name, theme)
else
return false
end
message "Syntax #{syntax.name} loaded"
end
|
#load_theme(name) ⇒ Object
937
938
939
940
941
942
943
944
945
|
# File 'lib/ver/buffer.rb', line 937
def load_theme(name)
return unless syntax
return unless found = Theme.find(name)
syntax.theme = Theme.load(found)
touch!('1.0', 'end')
message "Theme #{found} loaded"
end
|
#lock_uri(uri, &block) ⇒ Object
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
|
# File 'lib/ver/buffer.rb', line 508
def lock_uri(uri, &block)
lock = uri_lockfile(uri)
if lock.file? info = Hash[lock.read.scan(/^(\w+):\s*(.*)$/)]
ctime = lock.ctime
pid = info['pid']
user = info['user']
uri = info['uri']
alive = info
prompt = <<-TEXT.chomp
Found a lock file at: #{lock}
owned by: #{user}
used by: #{pid}
dated: #{ctime}
for: #{uri}
Another program may be editing the same file.
If this is the case, be careful not to end up with two different instances of the same file when making changes.
Close this buffer or continue with caution.
[O]pen Read-Only, [E]dit anyway, [D]elete lock, [Q]uit, [A]bort:
TEXT
ask(prompt) do |answer, action|
case action
when :modified
case answer
when /o/i
yield :read_only
:abort
when /e/i
yield :shared
:abort
when /q/i
yield :quit
:abort
when /a/i
yield :abort
:abort
when /d/i
VER.defer do
lock.rm
lock_uri(uri, &block)
end
:abort
else
warn('invalid answer')
minibuf.answer = ''
end
end
end
else
File.open(lock, 'w+') do |file|
file.puts(
"pid: #{Process.pid}",
"uid: #{Process.uid}",
"uri: #{uri}"
)
end
yield :single
end
end
|
#may_close ⇒ Object
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
|
# File 'lib/ver/methods/save.rb', line 169
def may_close
return yield if pristine? || persisted?
question = "Save buffer #{uri} before closing? " \
"[y]es [n]o [c]ancel: "
ask question, value: 'y' do |answer, action|
case action
when :attempt
case answer[0]
when /y/i
may_save{ yield if save }
VER.message 'Saved'
:abort
when /n/i
yield
VER.message 'Closing without saving'
:abort
else
VER.warn "Cancel closing"
:abort
end
end
end
end
|
#may_save(as = nil) ⇒ Object
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
|
# File 'lib/ver/methods/save.rb', line 195
def may_save(as = nil)
last = store(:stat, :mtime)
current = filename.mtime rescue nil
if last && current
return yield if last == current
else
return yield
end
question = "The buffer #{uri} has changed since last save, " \
"overwrite? [y]es [n]o: "
ask question, value: 'n' do |answer, action|
case action
when :attempt
case answer[0]
when /y/i
yield
:abort
else
warn "Save aborted"
:abort
end
end
end
end
|
#message(*args) ⇒ Object
308
309
310
|
# File 'lib/ver/buffer.rb', line 308
def message(*args)
@minibuf.message(*args)
end
|
#name=(name) ⇒ Object
352
353
354
355
|
# File 'lib/ver/buffer.rb', line 352
def name=(name)
@name = name
status.event :filename if status
end
|
#on_destroy(event) ⇒ Object
#on_enter_minor_mode(event) ⇒ Object
193
194
195
196
|
# File 'lib/ver/buffer.rb', line 193
def on_enter_minor_mode(event)
sync_mode_status
sync_mode_style(event.detail)
end
|
#on_focus_in(event) ⇒ Object
209
210
211
212
213
214
215
216
217
218
|
# File 'lib/ver/buffer.rb', line 209
def on_focus_in(event)
if @minibuf.asking
@minibuf.focus
else
Dir.chdir(filename.dirname.to_s) if filename && options.auto_chdir
on_movement(event)
end
Tk.callback_break
end
|
#on_focus_out(event) ⇒ Object
220
221
222
|
# File 'lib/ver/buffer.rb', line 220
def on_focus_out(event)
Tk.callback_break
end
|
#on_modified(event) ⇒ Object
198
199
200
|
# File 'lib/ver/buffer.rb', line 198
def on_modified(event)
on_movement(event)
end
|
#on_movement(event) ⇒ Object
202
203
204
205
206
207
|
# File 'lib/ver/buffer.rb', line 202
def on_movement(event)
at_insert.see
at_sel.refresh
@matching_brace.refresh
sync_position_status
end
|
#open(uri, line = 1, char = 0) ⇒ Object
390
391
392
393
394
395
396
397
398
399
400
401
402
403
|
# File 'lib/ver/buffer.rb', line 390
def open(uri, line = 1, char = 0)
case uri
when Symbol
open_symbolic(uri, line, char)
when Pathname
open_pathname(uri, line, char)
when String, URI
open_uri(uri, line, char)
else
raise ArgumentError, "Invalid uri: %p" % [uri]
end
true
end
|
#open_empty(line, char) ⇒ Object
463
464
465
466
467
468
469
|
# File 'lib/ver/buffer.rb', line 463
def open_empty(line, char)
self.uri = '<empty>'
self.value = ''
self.encoding = value.encoding
self.readonly = false
after_open(nil, line, char)
end
|
#open_pathname(pathname, line, char) ⇒ Object
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
|
# File 'lib/ver/buffer.rb', line 435
def open_pathname(pathname, line, char)
lock_uri(pathname) do |answer|
begin
case answer
when :single, :shared, :read_only
self.uri = self.filename = pathname
content, encoding = pathname.read_encoded_file
self.encoding = encoding
self.value = content.chomp
self.readonly = answer == :read_only || pathname.readonly?
self.locked = answer == :single
detect_project_paths
update_mtime
after_open(nil, line, char)
when :abort
close
:abort
when :quit
VER.exit
end
rescue Errno::ENOENT => ex
VER.error(ex)
open_empty(line, char)
end
end
end
|
#open_symbolic(symbol, line, char) ⇒ Object
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
|
# File 'lib/ver/buffer.rb', line 405
def open_symbolic(symbol, line, char)
self.uri = symbol
self.symbolic = true
case symbol
when :Scratch
self.value = <<-TEXT
# This buffer is for notes you don't want to save, and for Ruby evaluation.
# If you want to create a file, visit that file with :o.
# then enter the text in that file's own buffer.
TEXT
syntax = 'Ruby'
when :Messages
clear
tag(:info).configure(foreground: '#aaf')
tag(:warn).configure(foreground: '#faa')
syntax = 'Plain Text'
when :Completions
clear
self.major_mode = :Completions
tag('ver.minibuf.completion').configure(foreground: '#fff')
syntax = 'Plain Text'
else
clear
syntax = 'Plain Text'
end
after_open(Syntax.new(syntax), line, char)
end
|
#open_uri(uri, line, char) ⇒ Object
471
472
473
474
475
|
# File 'lib/ver/buffer.rb', line 471
def open_uri(uri, line, char)
self.uri = uri
self.value = Kernel.open(uri){|io| io.read.chomp }
after_open(nil, line, char)
end
|
#parse_go_line(input) ⇒ Object
45
46
47
48
49
50
51
52
53
54
55
56
|
# File 'lib/ver/methods/move.rb', line 45
def parse_go_line(input)
case input.to_s.strip
when /^\+(\d+)(?:,(\d+))?$/
line, char = $1.to_i, $2.to_i
yield index("#{at_insert.line + line}.#{char}")
when /^(\d+)(?:,(\d+))?$/
line, char = $1.to_i, $2.to_i
yield index("#{line}.#{char}")
else
VER.warn("Invalid [+]line[,char]: %p" % [input])
end
end
|
#persist_info ⇒ Object
This has to be called before <Destroy> is received, otherwise the Buffer is half-dead.
236
237
238
239
240
241
242
243
244
245
246
247
248
|
# File 'lib/ver/buffer.rb', line 236
def persist_info
file = VER.loadpath.first/'buffer_info.json'
l "Persisting Buffer info into: #{file}"
JSON::Store.new(file.to_s, true).transaction do |buffer_info|
syntax_name = @syntax.name if @syntax
buffer_info[uri.to_s] = {
'insert' => index('insert').to_s,
'syntax' => syntax_name
}
end
end
|
#persisted? ⇒ Boolean
316
317
318
319
320
321
322
323
324
|
# File 'lib/ver/buffer.rb', line 316
def persisted?
return false unless filename
return false unless filename.file?
require 'digest/md5'
on_disk = Digest::MD5.hexdigest(filename.read)
in_memory = Digest::MD5.hexdigest(value)
on_disk == in_memory
end
|
#prefix_arg_sol ⇒ Object
3
4
5
6
|
# File 'lib/ver/methods/move.rb', line 3
def prefix_arg_sol
return if update_prefix_arg
at_insert.start_of_line
end
|
#prefix_count(default = 1) ⇒ Object
Same as [prefix_arg], but returns 1 if there is no argument.
The return value in case there is no argument can be changed by passing a default
argument.
Useful for [Move] methods and the like. Please note that calling this method is destructive. It will reset the state of the prefix_arg in order to avoid persistent arguments. So use it only once while your action is running, and store the result in a variable if you need it more than once.
760
761
762
763
764
765
766
767
768
769
770
|
# File 'lib/ver/buffer.rb', line 760
def prefix_count(default = 1)
if skip_prefix_count_once
self.skip_prefix_count_once = false
update_prefix_arg
return default
end
count = prefix_arg || default
update_prefix_arg
count
end
|
#quit ⇒ Object
Close one buffer after another, wait when one needs user input.
20
21
22
23
24
25
26
27
28
29
|
# File 'lib/ver/methods/save.rb', line 20
def quit
buffers = VER.buffers.each
closer = lambda{
begin
buffers.next.close(&closer)
rescue StopIteration
end
}
closer.call
end
|
#redo ⇒ Object
691
692
693
|
# File 'lib/ver/buffer.rb', line 691
def redo
undoer.redo if undoer
end
|
#repeat_action ⇒ Object
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
|
# File 'lib/ver/buffer.rb', line 772
def repeat_action
stack = []
actions.reverse_each do |event, mode, action|
if stack.empty?
next if REPEAT_BREAK_CMD.include?(action.to_method(self).name)
next if REPEAT_BREAK_MODE.include?(mode.name)
else
break if REPEAT_BREAK_CMD.include?(action.to_method(self).name)
break if REPEAT_BREAK_MODE.include?(mode.name)
end
stack << [event, action]
end
return if stack.empty?
prefix_arg = self.prefix_arg
stack.reverse_each do |event, action|
self.prefix_arg = prefix_arg
action.call(event)
end
end
|
#replace(*args) ⇒ Object
374
375
376
377
378
379
380
|
# File 'lib/ver/buffer.rb', line 374
def replace(*args)
return super unless undoer
undo_record do |record|
record.replace(*args)
end
end
|
#rsearch_all(regexp, start = 'end', stop = '1.0') ⇒ Object
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
|
# File 'lib/ver/buffer.rb', line 841
def rsearch_all(regexp, start = 'end', stop = '1.0')
unless block_given?
return Enumerator.new(self, :rsearch_all, regexp, start, stop)
end
while result = rsearch(regexp, start, stop, :count)
pos, len = result
break if !pos || len == 0
from = index(pos)
to = index("#{pos} + #{len} chars")
match = get(from, to)
yield(match, from, to)
start = from
end
end
|
#save(filename = self.filename, &block) ⇒ Object
127
128
129
130
131
132
133
|
# File 'lib/ver/methods/save.rb', line 127
def save(filename = self.filename, &block)
if filename
save_to(filename, &block)
else
save_as(&block)
end
end
|
#save_all ⇒ Object
Save all buffers in ordered fashion, take into account that some buffers might require user interaction.
33
34
35
36
37
38
39
40
41
42
|
# File 'lib/ver/methods/save.rb', line 33
def save_all
buffers = VER.buffers.each
closer = lambda{
begin
buffers.next.save(&closer)
rescue StopIteration
end
}
closer.call
end
|
#save_as ⇒ Object
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
# File 'lib/ver/methods/save.rb', line 142
def save_as
if filename = self.filename
dir = filename.dirname.to_s + '/'
else
dir = Dir.pwd + '/'
end
message = "Save #{uri} as: "
ask message, value: dir do |answer, action|
case action
when :complete
Pathname(answer + '*').expand_path.glob.map{|f|
File.directory?(f) ? "#{f}/" : f
}
when :attempt
begin
save_to(Pathname(answer).expand_path)
yield if block_given?
:abort
rescue => exception
warn exception
end
end
end
end
|
#save_atomic(from, to, &block) ⇒ Object
Try to copy the file we want to save to a temp dir, trying to preserve permissions. Once it’s there, we overwrite the contents with the buffer contents. If that worked, we move it to the original location.
On sshfs mounts we might face chown issues, so we ignore them. If this all fails for some reason, we resort to #save_dumb
When save was successful overall, we call the given block
.
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
# File 'lib/ver/methods/save.rb', line 53
def save_atomic(from, to, &block)
require 'tmpdir'
sha1 = Digest::SHA1.hexdigest([from, to].join)
temp_path = File.join(Dir.tmpdir, 'ver/save', sha1)
temp_dir = File.dirname(temp_path)
FileUtils.mkdir_p(temp_dir)
FileUtils.copy_file(from, temp_path, preserve = true)
if save_dumb(temp_path)
FileUtils.mv(temp_path, to)
success("Saved to #{to}", &block)
else
false
end
rescue Errno::EACCES => ex
if ex.backtrace[0].match(/chown\'$/)
success("Saved to #{to} (chown issue)", &block)
else
warn(ex)
false
end
rescue Errno::ENOENT
save_dumb(to, &block)
end
|
#save_dumb(to, &block) ⇒ Object
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
# File 'lib/ver/methods/save.rb', line 79
def save_dumb(to, &block)
File.open(to, 'w+') do |io|
io.set_encoding(self.encoding)
begin
io.write(self.value)
rescue Encoding::UndefinedConversionError => ex
warn("Saving as UTF-8 because of: #{ex.class}: #{ex}")
io.rewind
io.set_encoding(Encoding::UTF_8)
io.write(self.value)
self.encoding = Encoding::UTF_8
end
end
success("Saved to #{to}", &block)
rescue Exception => ex
warn(ex)
VER.error(ex)
return false
end
|
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
# File 'lib/ver/methods/save.rb', line 111
def (options = {}, &block)
options = options.dup
options[:filetypes] ||= [
['ALL Files', '*' ],
['Text Files', '*.txt'],
]
options[:initialfile] ||= filename.basename
options[:defaultextension] ||= filename.extname
options[:initialdir] ||= filename.dirname
fpath = Tk.get_save_file(options)
return unless fpath
save_to(fpath, &block)
end
|
#save_to(to, &block) ⇒ Object
135
136
137
138
139
140
|
# File 'lib/ver/methods/save.rb', line 135
def save_to(to, &block)
may_save{ save_atomic(filename, to, &block) }
rescue => exception
VER.error(exception)
may_save{ save_dumb(to, &block) }
end
|
#search_all(regexp, start = '1.0', stop = 'end - 1 chars') ⇒ Object
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
|
# File 'lib/ver/buffer.rb', line 822
def search_all(regexp, start = '1.0', stop = 'end - 1 chars')
unless block_given?
return Enumerator.new(self, :search_all, regexp, start, stop)
end
while result = search(regexp, start, stop, :count)
pos, len = result
return if !pos || len == 0
from = index(pos)
to = index("#{pos} + #{len} chars")
match = get(from, to)
yield(match, from, to)
start = to
end
end
|
#set(option, value) ⇒ Object
644
645
646
647
648
649
650
651
652
653
654
655
656
657
|
# File 'lib/ver/buffer.rb', line 644
def set(option, value)
method = "set_#{option}"
if respond_to?(method)
if block_given?
__send__(method, value, &Proc.new)
else
__send__(method, value)
end
else
options[option] = value
yield(value) if block_given?
end
end
|
#set_filetype(type) ⇒ Object
659
660
661
662
663
664
665
|
# File 'lib/ver/buffer.rb', line 659
def set_filetype(type)
syntax = VER::Syntax.from_filename(Pathname("foo.#{type}"))
if load_syntax(syntax)
options.filetype = type
end
end
|
#setup ⇒ Object
125
126
127
128
129
130
131
132
|
# File 'lib/ver/buffer.rb', line 125
def setup
setup_tags
setup_misc
setup_widgets
setup_layout
setup_binds
layout.bind('<Map>'){ Tk.update }
end
|
#setup_binds ⇒ Object
178
179
180
181
182
183
184
185
|
# File 'lib/ver/buffer.rb', line 178
def setup_binds
bind('<<EnterMinorMode>>', &method(:on_enter_minor_mode))
bind('<<Modified>>', &method(:on_modified))
bind('<<Movement>>', &method(:on_movement))
bind('<FocusIn>', &method(:on_focus_in))
bind('<FocusOut>', &method(:on_focus_out))
bind('<Destroy>', &method(:on_destroy))
end
|
#setup_highlight ⇒ Object
914
915
916
|
# File 'lib/ver/buffer.rb', line 914
def setup_highlight
setup_highlight_for(Syntax.from_filename(filename)) if filename
end
|
#setup_highlight_for(syntax) ⇒ Object
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
|
# File 'lib/ver/buffer.rb', line 918
def setup_highlight_for(syntax)
return if encoding == Encoding::BINARY
return unless syntax
syntax = Syntax.new(syntax) unless syntax.is_a?(Syntax)
self.syntax = syntax
VER.cancel_block(@highlighter)
interval = options.syntax_highlight_interval.to_int
@highlighter = VER.when_inactive_for(interval){
handle_pending_syntax_highlights
}
touch!('1.0', 'end')
handle_pending_syntax_highlights
sync_mode_status
end
|
#setup_layout ⇒ Object
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
# File 'lib/ver/buffer.rb', line 149
def setup_layout
self. grid_configure row: 0, column: 0, sticky: :nsew
@ybar. grid_configure row: 0, column: 1, sticky: :ns if @ybar
@xbar. grid_configure row: 1, column: 0, sticky: :ew if @xbar
status. grid_configure row: 2, column: 0, sticky: :ew
@minibuf.grid_configure row: 3, column: 0, sticky: :ew
frame.grid_columnconfigure 0, weight: 1
frame.grid_columnconfigure 1, weight: 0
frame.grid_rowconfigure 0, weight: 1
frame.grid_rowconfigure 1, weight: 0
frame.grid_rowconfigure 2, weight: 0
frame.grid_rowconfigure 3, weight: 0
end
|
#setup_misc ⇒ Object
164
165
166
167
168
169
170
171
172
173
174
175
176
|
# File 'lib/ver/buffer.rb', line 164
def setup_misc
@store_hash = Hash.new{|h,k| h[k] = {} }
@options = Options.new(:text, VER.options)
@at_current = Mark.new(self, :current)
@at_insert = Insert.new(self)
@at_end = End.new(self)
@at_sel = Selection::Char.new(self, false)
@theme_config = nil
@highlighter = nil
@pristine = true
self.register = Register['*']
self.major_mode = :Fundamental
end
|
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
# File 'lib/ver/buffer.rb', line 134
def setup_widgets
@status = Status.new(frame, self)
@minibuf = VER.minibuf.peer_create(frame, self)
if options.horizontal_scrollbar
@xbar = Tk::Tile::XScrollbar.new(frame)
xscrollbar(@xbar)
end
if options.vertical_scrollbar
@ybar = Tk::Tile::YScrollbar.new(frame)
yscrollbar(@ybar)
end
end
|
#short_filename ⇒ Object
330
331
332
333
334
335
336
337
338
339
340
|
# File 'lib/ver/buffer.rb', line 330
def short_filename
if filename
if root = @project_root
filename.relative_path_from(root).to_s
else
filename.sub(Dir.pwd + '/', '').to_s
end
elsif uri
uri.to_s
end
end
|
#show ⇒ Object
671
672
673
|
# File 'lib/ver/buffer.rb', line 671
def show
layout.show
end
|
#store(namespace, key, value = None) ⇒ Object
703
704
705
706
707
708
709
|
# File 'lib/ver/buffer.rb', line 703
def store(namespace, key, value = None)
if None == value
@store_hash[namespace][key]
else
@store_hash[namespace][key] = value
end
end
|
#success(message) ⇒ Object
103
104
105
106
107
108
109
|
# File 'lib/ver/methods/save.rb', line 103
def success(message)
self.message(message)
self.pristine = true
update_mtime
yield if block_given?
true
end
|
#sync_encoding_status ⇒ Object
270
271
272
|
# File 'lib/ver/buffer.rb', line 270
def sync_encoding_status
status.event :encoding
end
|
#sync_mode_status ⇒ Object
262
263
264
|
# File 'lib/ver/buffer.rb', line 262
def sync_mode_status
status.event :mode
end
|
#sync_mode_style(given_mode = nil) ⇒ Object
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
|
# File 'lib/ver/buffer.rb', line 278
def sync_mode_style(given_mode = nil)
config = (theme_config || {}).merge(blockcursor: false)
modes = given_mode ? [given_mode] : major_mode.minors
modes.each do |mode|
mode = MinorMode[mode]
MODE_STYLES.each do |pattern, style|
config.merge!(style) if pattern === mode.name
end
end
configure(config)
return unless status && color = config[:insertbackground]
status.style = {
background: cget(:background),
foreground: color,
}
end
|
#sync_percent_status ⇒ Object
274
275
276
|
# File 'lib/ver/buffer.rb', line 274
def sync_percent_status
status.event :percent
end
|
#sync_position_status ⇒ Object
266
267
268
|
# File 'lib/ver/buffer.rb', line 266
def sync_position_status
status.event :position, :percent
end
|
#tag_all_matching(name, regexp, options = {}) ⇒ Object
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
|
# File 'lib/ver/buffer.rb', line 804
def tag_all_matching(name, regexp, options = {})
name = name.to_s
options = TAG_ALL_MATCHING_OPTIONS.merge(options)
from, to = options.values_at(:from, :to)
if tag_exists?(name)
tag_remove(name, from, to)
else
fg, bg = options.values_at(:foreground, :background)
tag_configure(name, foreground: fg, background: bg)
end
search_all(regexp, from, to) do |match, match_from, match_to|
name = yield(match, match_from, match_to) if block_given?
tag_add name, match_from, match_to
end
end
|
#tag_exists?(given_path) ⇒ Boolean
798
799
800
801
802
|
# File 'lib/ver/buffer.rb', line 798
def tag_exists?(given_path)
tag_names.include?(given_path)
rescue RuntimeError => ex
false
end
|
Display a tooltip for the tags the insert cursor is on. Also generates a status message. Hides the tooltip after 5 seconds unless a seconds count
is given.
13
14
15
16
17
18
19
|
# File 'lib/ver/methods/basic.rb', line 13
def tags_tooltip(count = prefix_arg)
index = at_insert
value = index.tag_names.join(', ')
message(value)
tooltip(value, count || 5)
end
|
21
22
23
24
25
26
27
|
# File 'lib/ver/methods/basic.rb', line 21
def tooltip(string, timeout = 5)
require 'ver/tooltip'
tooltip = Tk::Tooltip.new(string)
tooltip.show_on(self)
Tk::After.ms(timeout * 1000){ tooltip.destroy }
end
|
#touch!(*indices) ⇒ Object
682
683
684
685
|
# File 'lib/ver/buffer.rb', line 682
def touch!(*indices)
tag_add('ver.highlight.pending', *indices.flatten)
Tk::Event.generate(self, '<<Modified>>')
end
|
#type(string) ⇒ Object
326
327
328
|
# File 'lib/ver/buffer.rb', line 326
def type(string)
major_mode.fake(string)
end
|
#undo ⇒ Object
687
688
689
|
# File 'lib/ver/buffer.rb', line 687
def undo
undoer.undo if undoer
end
|
#undo_record(&block) ⇒ Object
Use this method in commands that do multiple insert, delete, replace
696
697
698
699
700
701
|
# File 'lib/ver/buffer.rb', line 696
def undo_record(&block)
VER.warn "Buffer is Read-only" if readonly
undoer ? undoer.record_multi(&block) : yield(self)
ensure
self.pristine = false
end
|
#unlock_uri(uri = self.uri) ⇒ Object
574
575
576
577
|
# File 'lib/ver/buffer.rb', line 574
def unlock_uri(uri = self.uri)
return unless locked?
uri_lockfile(uri).rm_f
end
|
#up_down_displayline(count) ⇒ Object
OK, finally found the issue.
the implementation of tk::TextUpDownLine is smart, but not smart enough. It doesn’t assume large deltas between the start of up/down movement and the last other modification of the insert mark.
This means that, after scrolling with up/down for a few hundred lines, it has to calculate the amount of display lines in between, which is a very expensive calculation and time increases O(delta_lines).
We’ll try to solve this another way, by assuming that there are at least a few other lines of same or greater length in between, we simply compare against a closer position and make delta_lines as small as possible.
Now, if you go to, like column 100 of a line, and there is never a line as long for the rest of the file, the scrolling will still slow down a lot. This is an issue we can fix if we “forget” the @udl_pos_orig after a user-defined maximum delta (something around 200 should do), will implement that on demand.
880
881
882
883
884
885
886
887
888
889
890
891
|
# File 'lib/ver/buffer.rb', line 880
def up_down_displayline(count)
insert = at_insert
@udl_pos_orig = insert if @udl_pos_prev != insert
lines = count(@udl_pos_orig, insert, :displaylines)
target = index("#@udl_pos_orig + #{lines + count} displaylines")
@udl_pos_prev = target
@udl_pos_orig = target if target.char == @udl_pos_orig.char
target
end
|
#up_down_line(count) ⇒ Object
This method goes up and down lines, not taking line wrapping into account. To go a line down, pass 1, to go one up -1, you get the idea. Tries to maintain the same char position across lines.
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
|
# File 'lib/ver/buffer.rb', line 896
def up_down_line(count)
insert = at_insert
@udl_pos_orig = insert if @udl_pos_prev != insert
lines = count(@udl_pos_orig, insert, :lines)
target = index("#@udl_pos_orig + #{lines + count} lines")
@udl_pos_prev = target
@udl_pos_orig = target if target.char == @udl_pos_orig.char
target
end
|
#update_mtime ⇒ Object
587
588
589
590
|
# File 'lib/ver/buffer.rb', line 587
def update_mtime
store(:stat, :mtime, filename.mtime) if filename
rescue Errno::ENOENT
end
|
#update_prefix_arg ⇒ Object
734
735
736
737
738
739
740
741
742
743
744
745
746
747
|
# File 'lib/ver/buffer.rb', line 734
def update_prefix_arg
numbers = []
events.reverse_each do |event|
break unless event.keysym =~ /^(\d+)$/
numbers << $1
end
if numbers.any? && numbers != ['0']
self.prefix_arg = numbers.reverse.join.to_i
else
self.prefix_arg = nil
end
end
|
#uri_lockfile(uri = self.uri) ⇒ Object
579
580
581
582
583
584
585
|
# File 'lib/ver/buffer.rb', line 579
def uri_lockfile(uri = self.uri)
require 'tmpdir'
hash = Digest::SHA1.hexdigest(uri.to_s)
lock = Pathname.tmpdir/'ver/lock'/hash
lock.dirname.mkpath
lock
end
|
#warn(*args) ⇒ Object
312
313
314
|
# File 'lib/ver/buffer.rb', line 312
def warn(*args)
@minibuf.warn(*args)
end
|
#with_register ⇒ Object
725
726
727
728
729
730
731
732
|
# File 'lib/ver/buffer.rb', line 725
def with_register
@with_register_level ||= 0
@with_register_level += 1
value = yield(register)
@with_register_level -= 1
ensure
self.register = Register['*'] if @with_register_level == 0
end
|