plugins/snippets/lib/snippets/tab_handler.rb in redcar-0.7 vs plugins/snippets/lib/snippets/tab_handler.rb in redcar-0.8

- old
+ new

@@ -3,11 +3,11 @@ class Snippets class TabHandler def self.priority 10 end - + def self.handle(edit_view, modifiers) controller = edit_view.document.controllers(Snippets::DocumentController).first if controller.in_snippet? if modifiers == ["Shift"] controller.move_backward_tab_stop @@ -21,62 +21,95 @@ else return false if modifiers.any? find_snippet(edit_view) end end - + def self.activate_snippet(edit_view, snippet) controller = edit_view.document.controllers(Snippets::DocumentController).first doc = edit_view.document - doc.delete(doc.cursor_offset - snippet.tab_trigger.length, snippet.tab_trigger.length) - controller.start_snippet!(snippet) + edit_view.compound do + doc.delete(doc.cursor_offset - snippet.tab_trigger.length, snippet.tab_trigger.length) + controller.start_snippet!(snippet) + end end - + # Decides whether a snippet can be inserted at this location. If so # returns the snippet, if not returns false. def self.find_snippet(edit_view) document = edit_view.document @word, @offset, @start_word_offset = nil, nil, nil @word = word_before_cursor(edit_view) - if @word @offset = document.cursor_offset @start_word_offset = document.cursor_offset - @word.length - options = Snippets.registry.find_by_scope_and_tab_trigger(document.cursor_scope, @word) + options = find_snippet_options(document.cursor_scope, @word) if options.any? choose_snippet(edit_view, options) end end end - + + #search for snippet matches inside a word block in an intelligent way + def self.find_snippet_options(scope,word) + search_word = word + options = search_registry(scope,word) + if not options.any? and word.match(/\W/) and word.match(/\w/) + + #most likely, there is just one symbol preceding the snippet + if not options.any? and char = word.index(/\w/,word.index(/\W/)) + search_word = word[char,word.split(//).length] + options = search_registry(scope, search_word) + end + + #otherwise, search from the end + if not options.any? + offset = -1 + while not options.any? and + (offset * -1) < word.split(//).length and + symbol_idx = word.rindex(/\W/,offset) and + char = word.index(/\w/,symbol_idx) + search_word = word[char,word.split(//).length] + options = search_registry(scope, search_word) + offset = offset - 1 + end + end + end + options + end + + def self.search_registry(scope,word) + Snippets.registry.find_by_scope_and_tab_trigger(scope,word) + end + def self.word_before_cursor(edit_view) document = edit_view.document line = document.get_slice(document.cursor_line_start_offset, document.cursor_offset).reverse if line =~ /([\S]+)(\s|$|\.)/ word = $1.reverse end word end - + def self.choose_snippet(edit_view, snippets) if not snippets or snippets.length == 0 false elsif snippets.length == 1 activate_snippet(edit_view, snippets.first) true else - builder = Menu::Builder.new do - snippets.group_by {|s| s.bundle_name }.each do |_, bsnippets| - bsnippets.each_with_index do |snippet, i| + builder = Menu::Builder.new do + snippets.group_by {|s| s.bundle_name }.each do |_, bsnippets| + bsnippets.each_with_index do |snippet, i| item(snippet.name||"<untitled>") do - Snippets::TabHandler.activate_snippet(edit_view, snippet) + Snippets::TabHandler.activate_snippet(edit_view, snippet) end - end - separator + end + separator end - end - Redcar.app.focussed_window.popup_menu_with_numbers(builder.menu) - true + end + Redcar.app.focussed_window.popup_menu_with_numbers(builder.menu) + true end end end end