[ Avaa Bypassed ]




Upload:

Command:

www-data@3.14.15.223: ~ $
#    Gedit snippets plugin
#    Copyright (C) 2005-2006  Jesse van den Kieboom <jesse@icecrew.nl>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import os
import re

from gi.repository import Gtk, Gdk, Gio, GLib, Gedit, GObject

from .library import Library
from .snippet import Snippet
from .placeholder import PlaceholderEnd
from . import completion
from .signals import Signals
from .shareddata import SharedData
from . import helper

try:
    import gettext
    gettext.bindtextdomain('gedit')
    gettext.textdomain('gedit')
    _ = gettext.gettext
except:
    _ = lambda s: s

class DynamicSnippet(dict):
    def __init__(self, text):
        self['text'] = text
        self.valid = True

class Document(GObject.Object, Gedit.ViewActivatable, Signals):
    TAB_KEY_VAL = (Gdk.KEY_Tab, Gdk.KEY_ISO_Left_Tab)
    SPACE_KEY_VAL = (Gdk.KEY_space,)

    view = GObject.Property(type=Gedit.View)

    def __init__(self):
        GObject.Object.__init__(self)
        Signals.__init__(self)

        self.placeholders = []
        self.active_snippets = []
        self.active_placeholder = None

        self.ordered_placeholders = []
        self.update_placeholders = []
        self.jump_placeholders = []
        self.language_id = 0
        self.timeout_update_id = 0

        self.provider = completion.Provider(_('Snippets'), self.language_id, self.on_proposal_activated)

    def do_activate(self):
        # Always have a reference to the global snippets
        Library().ref(None)

        buf = self.view.get_buffer()

        self.connect_signal(self.view, 'key-press-event', self.on_view_key_press)
        self.connect_signal(buf, 'notify::language', self.on_notify_language)
        self.connect_signal(self.view, 'drag-data-received', self.on_drag_data_received)

        self.connect_signal_after(self.view, 'draw', self.on_draw)

        self.update_language()

        completion = self.view.get_completion()
        completion.add_provider(self.provider)

        SharedData().register_controller(self.view, self)

    def do_deactivate(self):
        if self.timeout_update_id != 0:
            GLib.source_remove(self.timeout_update_id)
            self.timeout_update_id = 0

            del self.update_placeholders[:]
            del self.jump_placeholders[:]

        # Always release the reference to the global snippets
        Library().unref(None)
        self.active_placeholder = None

        self.disconnect_signals(self.view)
        self.disconnect_signals(self.view.get_buffer())

        # Remove all active snippets
        for snippet in list(self.active_snippets):
            self.deactivate_snippet(snippet, True)

        completion = self.view.get_completion()

        if completion:
            completion.remove_provider(self.provider)

        if self.language_id != 0:
            Library().unref(self.language_id)

        SharedData().unregister_controller(self.view, self)

    # Call this whenever the language in the view changes. This makes sure that
    # the correct language is used when finding snippets
    def update_language(self):
        lang = self.view.get_buffer().get_language()

        if lang == None and self.language_id == None:
            return
        elif lang and lang.get_id() == self.language_id:
            return

        langid = self.language_id

        if lang:
            self.language_id = lang.get_id()
        else:
            self.language_id = None

        if langid != 0:
            Library().unref(langid)

        Library().ref(self.language_id)
        self.provider.language_id = self.language_id

        SharedData().update_state(self.view.get_toplevel())

    def accelerator_activate(self, keyval, mod):
        if not self.view or not self.view.get_editable():
            return False

        accelerator = Gtk.accelerator_name(keyval, mod)
        snippets = Library().from_accelerator(accelerator, \
                self.language_id)

        if len(snippets) == 0:
            return False
        elif len(snippets) == 1:
            self.apply_snippet(snippets[0])
        else:
            # Do the fancy completion dialog
            provider = completion.Provider(_('Snippets'), self.language_id, self.on_proposal_activated)
            provider.set_proposals(snippets)

            cm = self.view.get_completion()
            cm.show([provider], cm.create_context(None))

        return True

    def first_snippet_inserted(self):
        buf = self.view.get_buffer()

        self.connect_signal(buf, 'changed', self.on_buffer_changed)
        self.connect_signal(buf, 'cursor-moved', self.on_buffer_cursor_moved)
        self.connect_signal_after(buf, 'insert-text', self.on_buffer_insert_text)

    def last_snippet_removed(self):
        buf = self.view.get_buffer()
        self.disconnect_signal(buf, 'changed')
        self.disconnect_signal(buf, 'cursor-moved')
        self.disconnect_signal(buf, 'insert-text')

    def current_placeholder(self):
        buf = self.view.get_buffer()

        piter = buf.get_iter_at_mark(buf.get_insert())
        found = []

        for placeholder in self.placeholders:
            begin = placeholder.begin_iter()
            end = placeholder.end_iter()

            if piter.compare(begin) >= 0 and piter.compare(end) <= 0:
                found.append(placeholder)

        if self.active_placeholder in found:
            return self.active_placeholder
        elif len(found) > 0:
            return found[0]
        else:
            return None

    def advance_placeholder(self, direction):
        # Returns (CurrentPlaceholder, NextPlaceholder), depending on direction
        buf = self.view.get_buffer()

        piter = buf.get_iter_at_mark(buf.get_insert())
        found = current = next = None
        length = len(self.placeholders)

        placeholders = list(self.placeholders)

        if self.active_placeholder:
            begin = self.active_placeholder.begin_iter()
            end = self.active_placeholder.end_iter()

            if piter.compare(begin) >= 0 and piter.compare(end) <= 0:
                current = self.active_placeholder
                currentIndex = placeholders.index(self.active_placeholder)

        if direction == 1:
            # w = piter, x = begin, y = end, z = found
            nearest = lambda w, x, y, z: (w.compare(x) <= 0 and (not z or \
                    x.compare(z.begin_iter()) < 0))
            indexer = lambda x: x < length - 1
        else:
            # w = piter, x = begin, y = end, z = prev
            nearest = lambda w, x, y, z: (w.compare(x) >= 0 and (not z or \
                    x.compare(z.begin_iter()) >= 0))
            indexer = lambda x: x > 0

        for index in range(0, length):
            placeholder = placeholders[index]
            begin = placeholder.begin_iter()
            end = placeholder.end_iter()

            # Find the nearest placeholder
            if nearest(piter, begin, end, found):
                found = placeholder

            # Find the current placeholder
            if piter.compare(begin) >= 0 and \
                    piter.compare(end) <= 0 and \
                    current == None:
                currentIndex = index
                current = placeholder

        if current and current != found and \
           (current.begin_iter().compare(found.begin_iter()) == 0 or \
            current.end_iter().compare(found.begin_iter()) == 0) and \
           self.active_placeholder and \
           current.begin_iter().compare(self.active_placeholder.begin_iter()) == 0:
            # if current and found are at the same place, then
            # resolve the 'hugging' problem
            current = self.active_placeholder
            currentIndex = placeholders.index(current)

        if current:
            if indexer(currentIndex):
                next = placeholders[currentIndex + direction]
        elif found:
            next = found
        elif length > 0:
            next = self.placeholders[0]

        return current, next

    def next_placeholder(self):
        return self.advance_placeholder(1)

    def previous_placeholder(self):
        return self.advance_placeholder(-1)

    def cursor_on_screen(self):
        buf = self.view.get_buffer()
        self.view.scroll_mark_onscreen(buf.get_insert())

    def set_active_placeholder(self, placeholder):
        self.active_placeholder = placeholder

    def goto_placeholder(self, current, next):
        last = None

        if current:
            # Signal this placeholder to end action
            self.view.get_completion().hide()
            current.leave()

            if current.__class__ == PlaceholderEnd:
                last = current

        self.set_active_placeholder(next)

        if next:
            next.enter()

            if next.__class__ == PlaceholderEnd:
                last = next
            elif len(next.defaults) > 1 and next.get_text() == next.default:
                provider = completion.Defaults(self.on_default_activated)
                provider.set_defaults(next.defaults)

                cm = self.view.get_completion()
                cm.show([provider], cm.create_context(None))

        if last:
            # This is the end of the placeholder, remove the snippet etc
            for snippet in list(self.active_snippets):
                if snippet.placeholders[0] == last:
                    self.deactivate_snippet(snippet)
                    break

        self.cursor_on_screen()

        return next != None

    def skip_to_next_placeholder(self):
        (current, next) = self.next_placeholder()
        return self.goto_placeholder(current, next)

    def skip_to_previous_placeholder(self):
        (current, prev) = self.previous_placeholder()
        return self.goto_placeholder(current, prev)

    def string_in_native_doc_encoding(self, buf, s):
        enc = buf.get_file().get_encoding()

        if not enc or enc.get_charset() == 'UTF-8':
            return s

        try:
            cv = GLib.convert(s, -1, enc.get_charset(), 'UTF-8')
            return cv[0]
        except GLib.GError:
            pass

        return s

    def env_get_selected_text(self, buf):
        bounds = buf.get_selection_bounds()

        if bounds:
            u8 = buf.get_text(bounds[0], bounds[1], False)

            return {'utf8': u8, 'noenc': self.string_in_native_doc_encoding(buf, u8)}
        else:
            return ''

    def env_get_current_word(self, buf):
        start, end = helper.buffer_word_boundary(buf)

        u8 = buf.get_text(start, end, False)

        return {'utf8': u8, 'noenc': self.string_in_native_doc_encoding(buf, u8)}

    def env_get_current_line(self, buf):
        start, end = helper.buffer_line_boundary(buf)

        u8 = buf.get_text(start, end, False)

        return {'utf8': u8, 'noenc': self.string_in_native_doc_encoding(buf, u8)}

    def env_get_current_line_number(self, buf):
        start, end = helper.buffer_line_boundary(buf)

        return str(start.get_line() + 1)

    def location_uri_for_env(self, location):
        if not location:
            return {'utf8': '', 'noenc': ''}

        u8 = location.get_parse_name()

        if location.has_uri_scheme('file'):
            u8 = "file://" + u8

        return {'utf8': u8, 'noenc': location.get_uri()}

    def location_name_for_env(self, location):
        if location:
            try:
                info = location.query_info("standard::display-name", 0, None)
                display_name = info.get_display_name()
            except:
                display_name = ''

            return {'utf8': display_name,
                'noenc': location.get_basename()}
        else:
            return ''

    def location_scheme_for_env(self, location):
        if location:
            return location.get_uri_scheme()
        else:
            return ''

    def location_path_for_env(self, location):
        if location and location.has_uri_scheme('file'):
            return {'utf8': location.get_parse_name(),
                'noenc': location.get_path()}
        else:
            return ''

    def location_dir_for_env(self, location):
        if location:
            parent = location.get_parent()

            if parent and parent.has_uri_scheme('file'):
                return {'utf8': parent.get_parse_name(),
                    'noenc': parent.get_path()}

        return ''

    def env_add_for_location(self, environ, location, prefix):
        parts = {'URI': self.location_uri_for_env,
             'NAME': self.location_name_for_env,
             'SCHEME': self.location_scheme_for_env,
             'PATH': self.location_path_for_env,
             'DIR': self.location_dir_for_env}

        for k in parts:
            v = parts[k](location)
            key = prefix + '_' + k

            if isinstance(v, dict):
                environ['utf8'][key] = v['utf8']
                environ['noenc'][key] = v['noenc']
            else:
                environ['utf8'][key] = v
                environ['noenc'][key] = str(v)

        return environ

    def env_get_document_type(self, buf):
        typ = buf.get_mime_type()

        if typ:
            return typ
        else:
            return ''

    def env_get_documents_uri(self, buf):
        toplevel = self.view.get_toplevel()

        documents_uri = {'utf8': [], 'noenc': []}

        if isinstance(toplevel, Gedit.Window):
            for doc in toplevel.get_documents():
                r = self.location_uri_for_env(doc.get_file().get_location())

                if isinstance(r, dict):
                    documents_uri['utf8'].append(r['utf8'])
                    documents_uri['noenc'].append(r['noenc'])
                else:
                    documents_uri['utf8'].append(r)
                    documents_uri['noenc'].append(str(r))

        return {'utf8': ' '.join(documents_uri['utf8']),
            'noenc': ' '.join(documents_uri['noenc'])}

    def env_get_documents_path(self, buf):
        toplevel = self.view.get_toplevel()

        documents_path = {'utf8': [], 'noenc': []}

        if isinstance(toplevel, Gedit.Window):
            for doc in toplevel.get_documents():
                r = self.location_path_for_env(doc.get_file().get_location())

                if isinstance(r, dict):
                    documents_path['utf8'].append(r['utf8'])
                    documents_path['noenc'].append(r['noenc'])
                else:
                    documents_path['utf8'].append(r)
                    documents_path['noenc'].append(str(r))

        return {'utf8': ' '.join(documents_path['utf8']),
            'noenc': ' '.join(documents_path['noenc'])}

    def get_environment(self):
        buf = self.view.get_buffer()
        environ = {'utf8': {}, 'noenc': {}}

        for k in os.environ:
            # Get the original environment, as utf-8
            v = os.environ[k]
            environ['noenc'][k] = v
            environ['utf8'][k] = os.environ[k].encode('utf-8')

        variables = {'GEDIT_SELECTED_TEXT': self.env_get_selected_text,
                 'GEDIT_CURRENT_WORD': self.env_get_current_word,
                 'GEDIT_CURRENT_LINE': self.env_get_current_line,
                 'GEDIT_CURRENT_LINE_NUMBER': self.env_get_current_line_number,
                 'GEDIT_CURRENT_DOCUMENT_TYPE': self.env_get_document_type,
                 'GEDIT_DOCUMENTS_URI': self.env_get_documents_uri,
                 'GEDIT_DOCUMENTS_PATH': self.env_get_documents_path}

        for var in variables:
            v = variables[var](buf)

            if isinstance(v, dict):
                environ['utf8'][var] = v['utf8']
                environ['noenc'][var] = v['noenc']
            else:
                environ['utf8'][var] = v
                environ['noenc'][var] = str(v)

        self.env_add_for_location(environ, buf.get_file().get_location(), 'GEDIT_CURRENT_DOCUMENT')

        return environ

    def uses_current_word(self, snippet):
        matches = re.findall('(\\\\*)\\$GEDIT_CURRENT_WORD', snippet['text'])

        for match in matches:
            if len(match) % 2 == 0:
                return True

        return False

    def uses_current_line(self, snippet):
        matches = re.findall('(\\\\*)\\$GEDIT_CURRENT_LINE', snippet['text'])

        for match in matches:
            if len(match) % 2 == 0:
                return True

        return False

    def apply_snippet(self, snippet, start = None, end = None, environ = {}):
        if not snippet.valid:
            return False

        # Set environmental variables
        env = self.get_environment()

        if environ:
            for k in environ['utf8']:
                env['utf8'][k] = environ['utf8'][k]

            for k in environ['noenc']:
                env['noenc'][k] = environ['noenc'][k]

        buf = self.view.get_buffer()
        s = Snippet(snippet, env)

        if not start:
            start = buf.get_iter_at_mark(buf.get_insert())

        if not end:
            end = buf.get_iter_at_mark(buf.get_selection_bound())

        if start.equal(end) and self.uses_current_word(s):
            # There is no tab trigger and no selection and the snippet uses
            # the current word. Set start and end to the word boundary so that
            # it will be removed
            start, end = helper.buffer_word_boundary(buf)
        elif start.equal(end) and self.uses_current_line(s):
            # There is no tab trigger and no selection and the snippet uses
            # the current line. Set start and end to the line boundary so that
            # it will be removed
            start, end = helper.buffer_line_boundary(buf)

        # You know, we could be in an end placeholder
        (current, next) = self.next_placeholder()
        if current and current.__class__ == PlaceholderEnd:
            self.goto_placeholder(current, None)

        if len(self.active_snippets) > 0:
            self.block_signal(buf, 'cursor-moved')

        buf.begin_user_action()

        # Remove the tag, selection or current word
        buf.delete(start, end)

        # Insert the snippet
        if len(self.active_snippets) == 0:
            self.first_snippet_inserted()
            self.block_signal(buf, 'cursor-moved')

        sn = s.insert_into(self, start)
        self.active_snippets.append(sn)

        # Put cursor at first tab placeholder
        keys = [x for x in sn.placeholders.keys() if x > 0]

        if len(keys) == 0:
            if 0 in sn.placeholders:
                self.goto_placeholder(self.active_placeholder, sn.placeholders[0])
            else:
                buf.place_cursor(sn.begin_iter())
        else:
            self.goto_placeholder(self.active_placeholder, sn.placeholders[keys[0]])

        self.unblock_signal(buf, 'cursor-moved')

        if sn in self.active_snippets:
            # Check if we can get end_iter in view without moving the
            # current cursor position out of view
            cur = buf.get_iter_at_mark(buf.get_insert())
            last = sn.end_iter()

            curloc = self.view.get_iter_location(cur)
            lastloc = self.view.get_iter_location(last)

            if (lastloc.y + lastloc.height) - curloc.y <= \
               self.view.get_visible_rect().height:
                self.view.scroll_mark_onscreen(sn.end_mark)

        buf.end_user_action()
        self.view.grab_focus()

        return True

    def get_tab_tag(self, buf, end = None):
        if not end:
            end = buf.get_iter_at_mark(buf.get_insert())

        start = end.copy()
        word = None
        first = True

        # Move start backward as long as there is a valid character
        while start.backward_char():
            c = start.get_char()

            if not helper.is_tab_trigger_character(c):
                # Check this for a single special char
                if first and helper.is_tab_trigger(c):
                    break

                # Make sure first char is valid
                while not start.equal(end) and \
                      not helper.is_first_tab_trigger_character(start.get_char()):
                    start.forward_char()

                break

            first = False

        if not start.equal(end):
            word = buf.get_text(start, end, False)

            if word and word != '':
                return (word, start, end)

        return (None, None, None)

    def parse_and_run_snippet(self, data, iter):
        if not self.view.get_editable():
            return

        self.apply_snippet(DynamicSnippet(data), iter, iter)

    def run_snippet_trigger(self, trigger, bounds):
        if not self.view:
            return False

        if not self.view.get_editable():
            return False

        buf = self.view.get_buffer()

        if buf.get_has_selection():
            return False

        snippets = Library().from_tag(trigger, self.language_id)

        if snippets:
            if len(snippets) == 1:
                return self.apply_snippet(snippets[0], bounds[0], bounds[1])
            else:
                # Do the fancy completion dialog
                provider = completion.Provider(_('Snippets'), self.language_id, self.on_proposal_activated)
                provider.set_proposals(snippets)

                cm = self.view.get_completion()
                cm.show([provider], cm.create_context(None))

                return True

        return False

    def run_snippet(self):
        if not self.view:
            return False

        if not self.view.get_editable():
            return False

        buf = self.view.get_buffer()

        # get the word preceding the current insertion position
        (word, start, end) = self.get_tab_tag(buf)

        if not word:
            return self.skip_to_next_placeholder()

        if not self.run_snippet_trigger(word, (start, end)):
            return self.skip_to_next_placeholder()
        else:
            return True

    def deactivate_snippet(self, snippet, force = False):
        remove = []
        ordered_remove = []

        for tabstop in snippet.placeholders:
            if tabstop == -1:
                placeholders = snippet.placeholders[-1]
            else:
                placeholders = [snippet.placeholders[tabstop]]

            for placeholder in placeholders:
                if placeholder in self.placeholders:
                    if placeholder in self.update_placeholders:
                        placeholder.update_contents()

                        self.update_placeholders.remove(placeholder)
                    elif placeholder in self.jump_placeholders:
                        placeholder[0].leave()

                    remove.append(placeholder)
                elif placeholder in self.ordered_placeholders:
                    ordered_remove.append(placeholder)

        for placeholder in remove:
            if placeholder == self.active_placeholder:
                self.active_placeholder = None

            self.placeholders.remove(placeholder)
            self.ordered_placeholders.remove(placeholder)

            placeholder.remove(force)

        for placeholder in ordered_remove:
            self.ordered_placeholders.remove(placeholder)
            placeholder.remove(force)

        snippet.deactivate()
        self.active_snippets.remove(snippet)

        if len(self.active_snippets) == 0:
            self.last_snippet_removed()

        self.view.queue_draw()

    def update_snippet_contents(self):
        self.timeout_update_id = 0

        for placeholder in self.update_placeholders:
            placeholder.update_contents()

        for placeholder in self.jump_placeholders:
            self.goto_placeholder(placeholder[0], placeholder[1])

        del self.update_placeholders[:]
        del self.jump_placeholders[:]

        return False

    def on_buffer_cursor_moved(self, buf):
        piter = buf.get_iter_at_mark(buf.get_insert())

        # Check for all snippets if the cursor is outside its scope
        for snippet in list(self.active_snippets):
            if snippet.begin_mark.get_deleted() or snippet.end_mark.get_deleted():
                self.deactivate(snippet)
            else:
                begin = snippet.begin_iter()
                end = snippet.end_iter()

                if piter.compare(begin) < 0 or piter.compare(end) > 0:
                    # Oh no! Remove the snippet this instant!!
                    self.deactivate_snippet(snippet)

        current = self.current_placeholder()

        if current != self.active_placeholder:
            self.jump_placeholders.append((self.active_placeholder, current))

            if self.timeout_update_id == 0:
                self.timeout_update_id = GLib.timeout_add(0,
                        self.update_snippet_contents)

    def on_buffer_changed(self, buf):
        for snippet in list(self.active_snippets):
            begin = snippet.begin_iter()
            end = snippet.end_iter()

            if begin.compare(end) >= 0:
                # Begin collapsed on end, just remove it
                self.deactivate_snippet(snippet)

        current = self.current_placeholder()

        if current:
            if not current in self.update_placeholders:
                self.update_placeholders.append(current)

            if self.timeout_update_id == 0:
                self.timeout_update_id = GLib.timeout_add(0, \
                        self.update_snippet_contents)

    def on_buffer_insert_text(self, buf, piter, text, length):
        ctx = helper.get_buffer_context(buf)

        # do nothing special if there is no context and no active
        # placeholder
        if (not ctx) and (not self.active_placeholder):
            return

        if not ctx:
            ctx = self.active_placeholder

        if not ctx in self.ordered_placeholders:
            return

        # move any marks that were incorrectly moved by this insertion
        # back to where they belong
        begin = ctx.begin_iter()
        end = ctx.end_iter()
        idx = self.ordered_placeholders.index(ctx)

        for placeholder in self.ordered_placeholders:
            if placeholder == ctx:
                continue

            ob = placeholder.begin_iter()
            oe = placeholder.end_iter()

            if ob.compare(begin) == 0 and ((not oe) or oe.compare(end) == 0):
                oidx = self.ordered_placeholders.index(placeholder)

                if oidx > idx and ob:
                    buf.move_mark(placeholder.begin, end)
                elif oidx < idx and oe:
                    buf.move_mark(placeholder.end, begin)
            elif ob.compare(begin) >= 0 and ob.compare(end) < 0 and (oe and oe.compare(end) >= 0):
                buf.move_mark(placeholder.begin, end)
            elif (oe and oe.compare(begin) > 0) and ob.compare(begin) <= 0:
                buf.move_mark(placeholder.end, begin)

    def on_notify_language(self, buf, spec):
        self.update_language()

    def on_view_key_press(self, view, event):
        library = Library()

        state = event.get_state()

        if not self.view.get_editable():
            return False

        if not (state & Gdk.ModifierType.CONTROL_MASK) and \
                not (state & Gdk.ModifierType.MOD1_MASK) and \
                event.keyval in self.TAB_KEY_VAL:
            if not state & Gdk.ModifierType.SHIFT_MASK:
                return self.run_snippet()
            else:
                return self.skip_to_previous_placeholder()
        elif not library.loaded and \
                library.valid_accelerator(event.keyval, state):
            library.ensure_files()
            library.ensure(self.language_id)
            self.accelerator_activate(event.keyval, \
                    state & Gtk.accelerator_get_default_mod_mask())

        return False

    def path_split(self, path, components=[]):
        head, tail = os.path.split(path)

        if not tail and head:
            return [head] + components
        elif tail:
            return self.path_split(head, [tail] + components)
        else:
            return components

    def apply_uri_snippet(self, snippet, mime, uri):
        # Remove file scheme
        gfile = Gio.file_new_for_uri(uri)

        environ = {'utf8': {'GEDIT_DROP_DOCUMENT_TYPE': mime.encode('utf-8')},
               'noenc': {'GEDIT_DROP_DOCUMENT_TYPE': mime}}

        self.env_add_for_location(environ, gfile, 'GEDIT_DROP_DOCUMENT')

        buf = self.view.get_buffer()
        location = buf.get_file().get_location()

        relpath = location.get_relative_path(gfile)

        # CHECK: what is the encoding of relpath?
        environ['utf8']['GEDIT_DROP_DOCUMENT_RELATIVE_PATH'] = relpath.encode('utf-8')
        environ['noenc']['GEDIT_DROP_DOCUMENT_RELATIVE_PATH'] = relpath

        mark = buf.get_mark('gtk_drag_target')

        if not mark:
            mark = buf.get_insert()

        piter = buf.get_iter_at_mark(mark)
        self.apply_snippet(snippet, piter, piter, environ)

    def in_bounds(self, x, y):
        rect = self.view.get_visible_rect()
        rect.x, rect.y = self.view.buffer_to_window_coords(Gtk.TextWindowType.WIDGET, rect.x, rect.y)

        return not (x < rect.x or x > rect.x + rect.width or y < rect.y or y > rect.y + rect.height)

    def on_drag_data_received(self, view, context, x, y, data, info, timestamp):
        if not self.view.get_editable():
            return

        uris = helper.drop_get_uris(data)
        if not uris:
            return

        if not self.in_bounds(x, y):
            return

        uris.reverse()
        stop = False

        for uri in uris:
            try:
                mime = Gio.content_type_guess(uri)
            except:
                mime = None

            if not mime:
                continue

            snippets = Library().from_drop_target(mime, self.language_id)

            if snippets:
                stop = True
                self.apply_uri_snippet(snippets[0], mime, uri)

        if stop:
            context.finish(True, False, timestamp)
            view.stop_emission('drag-data-received')
            view.get_toplevel().present()
            view.grab_focus()

    def find_uri_target(self, context):
        lst = Gtk.target_list_add_uri_targets((), 0)

        return self.view.drag_dest_find_target(context, lst)

    def on_proposal_activated(self, proposal, piter):
        if not self.view.get_editable():
            return False

        buf = self.view.get_buffer()
        bounds = buf.get_selection_bounds()

        if bounds:
            self.apply_snippet(proposal.snippet(), None, None)
        else:
            (word, start, end) = self.get_tab_tag(buf, piter)
            self.apply_snippet(proposal.snippet(), start, end)

        return True

    def on_default_activated(self, proposal, piter):
        buf = self.view.get_buffer()
        bounds = buf.get_selection_bounds()

        if bounds:
            buf.begin_user_action()
            buf.delete(bounds[0], bounds[1])
            buf.insert(bounds[0], proposal.props.label)
            buf.end_user_action()

            return True
        else:
            return False

    def iter_coords(self, piter):
        rect = self.view.get_iter_location(piter)
        rect.x, rect.y = self.view.buffer_to_window_coords(Gtk.TextWindowType.TEXT, rect.x, rect.y)

        return rect

    def placeholder_in_area(self, placeholder, area):
        start = placeholder.begin_iter()
        end = placeholder.end_iter()

        if not start or not end:
            return False

        # Test if start is before bottom, and end is after top
        start_rect = self.iter_coords(start)
        end_rect = self.iter_coords(end)

        return start_rect.y <= area.y + area.height and \
               end_rect.y + end_rect.height >= area.y

    def draw_placeholder_rect(self, ctx, placeholder):
        start = placeholder.begin_iter()
        start_rect = self.iter_coords(start)
        start_line = start.get_line()

        end = placeholder.end_iter()
        end_rect = self.iter_coords(end)
        end_line = end.get_line()

        line = start.copy()
        line.set_line_offset(0)
        geom = self.view.get_window(Gtk.TextWindowType.TEXT).get_geometry()

        ctx.translate(0.5, 0.5)

        while line.get_line() <= end_line:
            ypos, height = self.view.get_line_yrange(line)
            x_, ypos = self.view.window_to_buffer_coords(Gtk.TextWindowType.TEXT, 0, ypos)

            if line.get_line() == start_line and line.get_line() == end_line:
                # Simply draw a box, both are on the same line
                ctx.rectangle(start_rect.x, start_rect.y, end_rect.x - start_rect.x, start_rect.height - 1)
                ctx.stroke()
            elif line.get_line() == start_line or line.get_line() == end_line:
                if line.get_line() == start_line:
                    rect = start_rect
                else:
                    rect = end_rect

                ctx.move_to(0, rect.y + rect.height - 1)
                ctx.rel_line_to(rect.x, 0)
                ctx.rel_line_to(0, -rect.height + 1)
                ctx.rel_line_to(geom[2], 0)
                ctx.stroke()

            if not line.forward_line():
                break

    def draw_placeholder_bar(self, ctx, placeholder):
        start = placeholder.begin_iter()
        start_rect = self.iter_coords(start)

        ctx.translate(0.5, 0.5)
        extend_width = 2.5

        ctx.move_to(start_rect.x - extend_width, start_rect.y)
        ctx.rel_line_to(extend_width * 2, 0)

        ctx.move_to(start_rect.x, start_rect.y)
        ctx.rel_line_to(0, start_rect.height - 1)

        ctx.rel_move_to(-extend_width, 0)
        ctx.rel_line_to(extend_width * 2, 0)
        ctx.stroke()

    def draw_placeholder(self, ctx, placeholder):
        if isinstance(placeholder, PlaceholderEnd):
            return

        col = self.view.get_style_context().get_color(Gtk.StateFlags.INSENSITIVE)
        col.alpha = 0.5
        Gdk.cairo_set_source_rgba(ctx, col)

        if placeholder.tabstop > 0:
            ctx.set_dash([], 0)
        else:
            ctx.set_dash([2], 0)

        start = placeholder.begin_iter()
        end = placeholder.end_iter()

        if start.equal(end):
            self.draw_placeholder_bar(ctx, placeholder)
        else:
            self.draw_placeholder_rect(ctx, placeholder)

    def on_draw(self, view, ctx):
        window = view.get_window(Gtk.TextWindowType.TEXT)

        if not Gtk.cairo_should_draw_window(ctx, window):
            return False

        # Draw something
        ctx.set_line_width(1.0)

        Gtk.cairo_transform_to_window(ctx, view, window)

        clipped, clip = Gdk.cairo_get_clip_rectangle(ctx)

        if not clipped:
            return False

        for placeholder in self.ordered_placeholders:
            if not self.placeholder_in_area(placeholder, clip):
                continue

            ctx.save()
            self.draw_placeholder(ctx, placeholder)
            ctx.restore()

        return False

# ex:ts=4:et:

Filemanager

Name Type Size Permission Actions
__pycache__ Folder 0775
__init__.py File 1.03 KB 0644
appactivatable.py File 3.98 KB 0644
completion.py File 5.61 KB 0644
document.py File 35.07 KB 0644
exporter.py File 3.64 KB 0644
helper.py File 5.68 KB 0644
importer.py File 4.09 KB 0644
languagemanager.py File 1.24 KB 0644
library.py File 28.59 KB 0644
manager.py File 36.99 KB 0644
parser.py File 7.24 KB 0644
placeholder.py File 20.57 KB 0644
shareddata.py File 2.75 KB 0644
signals.py File 2.42 KB 0644
singleton.py File 1.13 KB 0644
snippet.py File 12.08 KB 0644
substitutionparser.py File 5.7 KB 0644
windowactivatable.py File 5.56 KB 0644