Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorflavio <fdanesse@gmail.com>2013-05-25 19:42:20 (GMT)
committer flavio <fdanesse@gmail.com>2013-05-25 19:43:53 (GMT)
commit561eccbedc21884da59b294cf45cfb2ea0f54375 (patch)
tree14687494de4c86401d3eebc8b71536aaa4d6bfa5
parent4ab968d0aa1cad79ebec9e4d0262f3ad2c28db22 (diff)
Nuevo sistema de autocompletado
-rw-r--r--WorkPanel.py251
-rw-r--r--gtkintrospection.py175
2 files changed, 301 insertions, 125 deletions
diff --git a/WorkPanel.py b/WorkPanel.py
index bfa2713..7238fcd 100644
--- a/WorkPanel.py
+++ b/WorkPanel.py
@@ -30,6 +30,8 @@ from gi.repository import GtkSource
from gi.repository import Vte
from gi.repository import GLib
+PATH = os.path.dirname(__file__)
+
class WorkPanel(Gtk.Paned):
"""
Panel, área de trabajo.
@@ -275,149 +277,148 @@ class AutoCompletado(GObject.Object, GtkSource.CompletionProvider):
def __init__(self, buffer):
GObject.Object.__init__(self)
-
- self.modulo = None
- self.nombre_modulo = ''
- self.ultimo_seleccionado = None
- self.mods_gi = self.__get_modulos_gi()
-
- self.priority = 1
+
self.buffer = buffer
- def do_activate_proposal(self, dato1, dato2):
+ def __set_imports(self, imports):
"""
- Cuando se selecciona y clickea
- una posible solución
+ Guarda los datos para importaciones previas,
+ para calculos de autocompletado.
"""
- nombre = dato1.get_text()
- self.nombre_modulo = self.nombre_modulo + "." + nombre
- if not self.modulo:
- return
- try:
- self.ultimo_seleccionado = self.modulo.__getattribute__(nombre)
- except:
- try:
- self.ultimo_seleccionado = self.modulo.__getattr__(nombre)
- except:
- print "Error al obtener el objeto clickeado."
+ import shelve
- def do_get_name(self):
+ pathin = os.path.join("/tmp", "shelvein")
+
+ archivo = shelve.open(pathin)
+ archivo["Lista"] = imports
+ archivo.close()
+
+ def __get_auto_completado(self):
"""
- Devuelve el nombre del último
- módulo al que se auto-completo
+ Devuelve la lista de opciones posibles
+ para auto completar.
"""
- return self.nombre_modulo
+ import commands
- def do_populate(self, context):
+ pathin = os.path.join("/tmp", "shelvein")
+
+ pathout = os.path.join(commands.getoutput(
+ 'python %s %s' % (
+ os.path.join(PATH, "gtkintrospection.py"),
+ pathin)))
+
+ lista = []
+
+ if os.path.exists(pathout):
+ ### Obtener lista para autocompletado.
+
+ import shelve
+
+ archivo = shelve.open(pathout)
+ lista = archivo["Lista"]
+ archivo.close()
+
+ return lista
+
+ def do_activate_proposal(self, dato1, dato2):
"""
- Obtiene el texto, se fija sí lo
- último introducido es un módulo, en caso
- de que así sea, hace 'dir(modulo)' y
- hace un menú para auto-completado
+ Cuando se selecciona y clickea
+ una posible solución.
"""
- self.modulo = None
-
- tema = Gtk.IconTheme.get_default()
- icono = tema.load_icon(Gtk.STOCK_DIALOG_INFO, 16, 0)
-
- inicio = self.buffer.get_start_iter()
- ingresado = self.buffer.get_iter_at_mark(self.buffer.get_insert())
- texto = self.buffer.get_text(inicio, ingresado, True)
- lineas = texto.splitlines()
-
- if lineas:
- linea = lineas[-1]
- else:
- linea = ''
-
- if texto:
- pass
- else:
- return
-
- if len(linea) >= 2:
- dato1 = linea[len(linea)-2:len(linea)]
- else:
- dato1 = "Ningun modulo"
-
- try:
- dat = linea.find(self.nombre_modulo)
- dat1 = len(self.nombre_modulo)
- dato_nombre = linea[dat:dat1]
- except:
- dato_nombre = ""
-
- if dato1[-1] == "." and dato1 != " ." and dato_nombre == self.nombre_modulo:
- tipo = str(type(self.ultimo_seleccionado))
- if "class" in tipo or "module" in tipo or "function" in tipo:
- self.resultados = []
- for Resultado in dir(self.ultimo_seleccionado):
- self.resultados.append(
- GtkSource.CompletionItem.new(
- Resultado,
- Resultado,
- icono,
- "Descripción - PygiHack"))
- context.add_proposals(self, self.resultados, True)
- else:
- self.ultimo_seleccionado = None
- self.nombre_modulo = None
- self.modulo = None
-
- if ' ' in linea:
- modulo = linea.split(' ')[-1]
- else:
- modulo = linea
-
- if modulo and modulo[-1] == '.':
- mod = ''
-
- for x in modulo[:-1]:
- mod += x
-
- modulo = mod
- self.nombre_modulo = modulo
-
- if modulo in self.mods_gi:
- mod = __import__("gi.repository.%s" % modulo)
- self.modulo = mod.importer.modules.get(modulo)
- try:
- if modulo != 'gtk' and modulo != 'gobject':
- self.modulo = __import__(modulo)
- except:
- pass
-
- self.resultados = []
-
- if self.modulo:
- for Resultado in dir(self.modulo):
- self.resultados.append(
- GtkSource.CompletionItem.new(
- Resultado,
- Resultado,
- icono,
- "Descripción - PygiHack"))
- context.add_proposals(self, self.resultados, True)
+ pass
- def __get_modulos_gi(self):
+ def do_get_name(self, coso=None, coso2=None):
"""
- Devuelve una lista de modulos
- de Gobject Introspection [Gi]
+ Devuelve el nombre del último
+ módulo al que se auto completó.
"""
- path_gi = "/usr/lib/girepository-1.0"
- modulos_nuevos = []
- if os.path.exists(path_gi):
- modulos = os.listdir(path_gi)
- for modulo in modulos:
- modulo = modulo.replace(".typelib", "")
- modulo = modulo.rpartition("-")
- modulos_nuevos.append(modulo[0])
- return modulos_nuevos
+ pass
+ def do_populate(self, context):
+ """
+ Cuando se producen cambios en el buffer.
+
+ Metodología para autocompletado:
+ * Importar todos los paquetes y módulos que se están
+ importando en el archivo sobre el cual estamos auto completando.
+ * Hacer el auto completado propiamente dicho, trabajando sobre
+ la línea de código que se está editando.
+ """
+
+ ### Iterador de texto sobre el código actual.
+ textiter = self.buffer.get_iter_at_mark(self.buffer.get_insert())# Gtk.TextIter
+
+ ### indice de linea activa.
+ indice_de_linea_activa = textiter.get_line()
+
+ ### Texto de la linea activa.
+ texto_de_linea_en_edicion = textiter.get_slice(
+ self.buffer.get_iter_at_line(indice_de_linea_activa))
+
+ ### Si hay un punto en la línea.
+ if "." in texto_de_linea_en_edicion:
+
+ ### Si el punto está en la última palabra.
+ if "." in texto_de_linea_en_edicion.split()[-1]:
+
+ ### Auto completado se hace sobre "."
+ if texto_de_linea_en_edicion.endswith("."):
+
+ palabras = texto_de_linea_en_edicion.split()
+
+ if palabras:
+ ### Importar paquetes y modulos previos
+ inicio = self.buffer.get_start_iter()
+ texto = self.buffer.get_text(inicio, textiter, True)
+ lineas = texto.splitlines()
+
+ imports = []
+
+ for linea in lineas:
+ # FIXME: Analizar mejor los casos como ''', """, etc.
+ if "import " in linea and not linea.startswith("#") and \
+ not linea.startswith("\"") and not linea.startswith("'"):
+ imports.append(linea)
+
+ ### ['import os', 'import sys', 'from os import path']
+ ### Esto es [] si auto completado se hace antes de los imports
+
+ ### Auto completado se hace sobre la última palabra
+ palabra = palabras[-1]
+ palabra = palabra.split("(")[-1] # Caso: class Ventana(gtk.
+
+ pals = palabra.split(".")[:-1]
+ imports.append(pals) # ['import os', 'import sys', 'from os import path', ['gtk', 'gdk', '']]
+
+ ### Guardar en un archivo.
+ self.__set_imports(imports)
+
+ ### Obtener lista para autocompletado.
+ lista = self.__get_auto_completado()
+
+ opciones = []
+
+ for item in lista:
+ opciones.append(GtkSource.CompletionItem.new(item,
+ item, None, None))
+
+ context.add_proposals(self, opciones, True)
+
+ else:
+ # FIXME: Se está autocompletando.
+ # Esto debe actualizar la lista de opciones disponibles,
+ # Filtrando en la lista según el texto escrito por el usuario.
+ text = texto_de_linea_en_edicion.split(".")[-1]
+
+ else:
+ context.add_proposals(self, [], True)
+
+ else:
+ context.add_proposals(self, [], True)
class Terminal(Vte.Terminal):
diff --git a/gtkintrospection.py b/gtkintrospection.py
new file mode 100644
index 0000000..4003762
--- /dev/null
+++ b/gtkintrospection.py
@@ -0,0 +1,175 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# gtkintrospection.py por:
+# Flavio Danesse <fdanesse@activitycentral.com>
+# ActivityCentran
+
+# 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 sys
+import shelve
+
+### Obtener los datos para hacer autocompletado.
+path = os.path.join(sys.argv[1])
+
+archivo = shelve.open(path)
+lista = archivo["Lista"]
+archivo.close()
+
+imports = lista[:-1]
+linea_activa = lista[-1]
+
+### Hacer importaciones previas.
+modulos = {}
+
+def append_modulo(name):
+ """
+ Importa un módulo según su nombre y lo
+ almacena importado.
+ """
+
+ # FIXME: Requiere analisis con mayor detenimiento.
+ try:
+ if not modulos.get(name, ""):
+ modulos[name] = __import__(name)
+
+ except:
+ arch = open("/tmp/log", "w")
+ arch.write(name)
+ arch.close()
+
+def append_modulo_to_prev(name, prev):
+ """
+ Importa un módulo que se encuentra dentro de
+ un paquete, según su nombre y el nombre
+ del paquete que lo contiene y lo almacena importado.
+ """
+
+ # FIXME: Requiere analisis con mayor detenimiento.
+ try:
+ if not modulos.get(prev, ""):
+ append_modulo(prev)
+
+ modulos[name] = modulos[prev].__getattribute__(name)
+
+ except:
+ pass
+
+def append_modulo_to_prev_for_path(path):
+ """
+ Importa los módulos necesarios segun path y lo almacena.
+ """
+
+ # FIXME: Requiere analisis con mayor detenimiento.
+ try:
+ # FIXME: Esta función Falla con tipos from modulo1.modulo2.modulo3 import modulo4
+ items = path.split(".")
+
+ contador = 0
+ prev = items[0]
+
+ for item in items:
+ contador += 1
+
+ if not contador == len(items):
+ dos = items[contador]
+ prev = "%s.%s" % (prev, items[contador])
+
+ mod = __import__(prev).__dict__[dos]
+
+ if not modulos.get(prev, ""):
+ modulos[prev] = mod
+
+ except:
+ pass
+
+for im in imports:
+
+ ### Caso 1: import os
+ ### Caso Especial: import os, sys, ...
+ if not "from " in im and not " *" in im and not " as" in im:
+ temp_list = im.split()[1:] # quitando "import" y separando los módulos.
+
+ for item in temp_list:
+ name = item.replace(",", "") # quitando ",".
+ append_modulo(name) # importar y almacenar.
+
+ ### Caso 1: import os
+ ### Caso Especial: from os import *
+ elif "from " in im and " *" in im and not " as" in im:
+ pass
+
+ ### Caso 2: from os import path
+ ### Caso Especial: from os import path, chmod, ...
+ elif "from " in im and not " *" in im and not "." in im and not " as" in im:
+ temp_list = im.split()
+ prev = temp_list[1]
+ temp_list = temp_list[3:]
+
+ for item in temp_list:
+ name = item.replace(",", "")
+ append_modulo_to_prev(name, prev)
+
+ ### Caso 2: from os import path
+ ### Caso Especial: from os import *
+ elif "from " in im and " *" in im and not "." in im and not " as" in im:
+ pass # http://stackoverflow.com/questions/2916374/how-to-import-with-import
+
+ ### caso 3: from Coso.Ventana import JAMediaPlayer
+ ### Caso Especial: from Coso.Ventana.Otro import JAMediaPlayer, OtraCosa, ...
+ elif "from " in im and not " *" in im and "." in im and not " as" in im:
+ temp_list = im.split()
+ prev = temp_list[1]
+ mod_temp_list = temp_list[3:]
+
+ if len(prev.split(".")) < 3: # FIXME la funcion falla para caso especial
+ ### Caso Especial: módulos de pygi.
+ if "gi.repository" in prev:
+ name = mod_temp_list[0]
+ mod = __import__("%s.%s" % (prev, name))
+ modulos[name] = mod.importer.modules.get(name)
+
+ else:
+ append_modulo_to_prev_for_path(prev)
+
+ for item in mod_temp_list:
+ name = item.replace(",", "")
+ append_modulo_to_prev(name, prev)
+
+### Importar el o los modulos sobre los que se está haciendo auto completado.
+lista = []
+
+# FIXME: Requiere análisis de casos especiales.
+if len(linea_activa) == 1:
+ name = linea_activa[0]
+ #append_modulo(name)
+
+ lista = dir(modulos[name])
+ #print dir(modulos[name])
+
+'''
+for key in modulos.keys():
+ print key, modulos[key]'''
+
+### Guardar la lista para autocompletar.
+path = os.path.join("/tmp", "shelveout")
+
+archivo = shelve.open(path)
+archivo["Lista"] = lista
+archivo.close()
+
+print path