Monodevelop AddIns
De Mono Hispano
Autores:
Jose Ramon Palanco jose.palanco@hazent.com correo
Contents |
Introducción
MonoDevelop (y SharpDevelop) se han escrito pensados para ser extendidos fácilemnete. Esto se puede hacer simplemente con dos cosas. Un assembly (.dll) que contenga el código del add-in y un fichero XML (.addin) que mapee el código de nuestro add-in en MonoDevelop.
Terminología
- add-in: Lo que mucha gente entiende por plugin.
- pad: Contenedor de partes de programa como el navegador de solución o la salida de compilación
- vista: Area principal como el SourceEditor -editor- .
- binding: Compilación, ejecución y gestión de proyecto para un lenguaje de programación.
- servicio: Parte encargada de ofrecer una actividad, como MessageService, encargado de mostrar mensajes al usuario.
Add-in assembly
Mediante el código de este assembly podemos añadir funcionalidades a MonoDevelop como puedan ser: nuevos menus, pads, vistas, servicios. commandos, ... Es recomendable descargarse el códio fuente de MonoDevelop (de la versión con la que estemos trabajando) y mirar src/AddIns/ para ver como se implementa cada cosa. En la mayoría de los casos bastará con heredar de una clase abstracta o implementar una interfaz.
Ejemplo de un servicio:
using System;
using MonoDevelop.Core.Services;
namespace MonoDevelop.Services;
{
public class ExampleService : AbstractService
{
// Incluir funcionalidad aquí
}
}
Aquí teneis una lista de la que normalmente querréis heredar:
- ./src/Main/Base/Gui/Dialogs/AbstractOptionPanel.cs
- ./src/Main/Base/Gui/Dialogs/Wizard/AbstractWizardPanel.cs
- ./src/Main/Base/Gui/Pads/ClassScout/BrowserNode/AbstractClassScoutNode.cs
- ./src/Main/Base/Gui/Pads/ProjectBrowser/BrowserNode/AbstractBrowserNode.cs
- ./src/Main/Base/Gui/AbstractBaseViewContent.cs
- ./src/Main/Base/Gui/AbstractPadContent.cs
- ./src/Main/Base/Gui/AbstractViewContent.cs
- ./src/Main/Base/Gui/AbstractSecondaryViewContent.cs
El fichero .addin.xml
Debemos de crear un fichero .addin.xml que mapee nuestro código en las partes de MonoDevelop donde queremos incrustarlo. Ahí debemos especificar servicios a cargar, donde colocar nuestra entrada del menu de usuario, etc...
Debido a que MonoDevelop está desarrollado por un subconjunto de add-ins (es un diseño impresionantemente modular), no tenemos límite para hacer lo que queramos desde un add-in. Disponemos de directivas condicionales y otras construcciones avanzadas. En el siguiente ejemplo MonoDevelopNunit.addin.xml, veremos como se especifica el nombre del assembly a cargar, el servicio a lanzar dentro del nodo /Workspace/Services, dos vistas y algún menú. Es importante darse cuenta de que el atributo de la clase se usa para especificar el tipo a instanciar para esa parte del add-in.
<AddIn name = "MonoDevelop Nunit"
author = "John Luke"
copyright = "GPL"
url = "http://monodevelop.com"
description = "NUnit testing tool"
version = "0.2">
<Runtime>
<Import assembly="MonoDevelop.Nunit.dll" />
</Runtime>
<Extension path="/Workspace/Services">
<Class id = "NunitService"
class = "MonoDevelop.Services.NunitService" />
</Extension>
<Extension path="/SharpDevelop/Workbench/Views">
<Class id = "NunitTestTree"
class = "MonoDevelop.Nunit.Gui.TestTree" />
<Class id = "NunitResultTree"
class = "MonoDevelop.Nunit.Gui.ResultTree" />
</Extension>
<Extension path="/SharpDevelop/Workbench/MainMenu/Tools">
<MenuItem id = "NunitMenu"
_label = "NUnit"
insertafter = "ExternalTools"
insertbefore = "Options">
<MenuItem id = "LoadTestAssembly"
_label = "Load Assembly"
shortcut = ""
class = "MonoDevelop.Commands.NunitLoadAssembly" />
<MenuItem id = "NunitRunTests"
_label = "Run Tests"
shortcut = ""
class = "MonoDevelop.Commands.NunitRunTests" />
</MenuItem>
</Extension>
</AddIn>
Add-in tree
Los AddIns se cargan y fusionan en un AddInTree, de tal manera que MonoDevelop conoce todos los elementos y donde cargarlos. Mira build/AddIns/SharpDevelopCore.addin.xml para ver varios lugares donde colgar tu add-in.
Formato del Add-in XML
Existe un fichero AddIn.xsd que especifica el formato XML requerido/óptimo. Quizá a alguien le interese data/resources/AddIn.xsd
Compilación e instalación
AddIns Existentes
- SourceEditor
- CSharpBinding
- JavaBinding
- NemerleBinding
- DebuggerAddin
- Monodoc
- StartPage (no se ha portado entero, en MD 0.8 debería estar)
- NUnit (incompleto)
ideas:
- Corrector ortográfico
- Ruby(.NET)Binding
- (Iron)PythonBinding
- Regex builder and checker
- Nant, Xdevelop, integration
- Stetic and GladeCodeGenerator integration (like VisualStudio... just design the GUI and click)
- AspNetEditor and XSP integration
- Beagle backend for search code like koders.com
- koders.com integration
- MonoUML integration
- Database designer integration (maybe into monouml?)
- GForge integration
- Cecil integration for debugging thru assemblies out of our project
- Compilación continua y subrayado de errores con listado de soluciones aplicacles con click
- Asistente de tabulado e indentación dependiendo del tipo de lenguaje
- XAML integration
- reorganize usings (reorganize imports in eclipse)
- GccCILBackendBinding
- refactorización
- buscar instanciación de una clase a partir del texto seleccionado
Advertencias
A pesar de que MonoDevelop usa el mismo formato que SharpDevelop, los add-ins que hagan uso de interfaz gráfica no funcionarán debido a que las librerías usadas por estos proyectos son muy diferentes. Incluso muchas veces tendremos problemas con gtk# debido a que las librerías de monodevelop se hayan compilado contra una versión distinta a la que estemos compilando nosotros.
El tipo de error es dificil de localizar, pero sabiendo esto podremos percatartnos cuando obtengamos un error similar a:
... type must be 'Gtk.Widget' to match overridden member ...
Y nos cercioremos de que estamos colocando los parámetros del tipo correcto.
Internacionalización
MonoDevelop usa gettext en vez de usar recursos para realizar la tradución a otras lenguas. Esto es una ventaja debido a que gran parte de la comunidad de desarrolladores de este entorno conoce gettext.
Con gettext, en vez de usar cadenas directamente en nuestro código, hacemos algo similar a esto:
GettextCatalog.GetString ("cadena que veran los usuarios")
String.Format (GettextCatalog.GetString ("cadena que veran los usuarios {0}"), variable)
Luego debemos de añadir esas cadenas a MonoDevelop/po/FICHEROS_POT.in
Código
Hola Mundo
Crearemos un fichero holamundo.addin.xml
<AddIn name = "Hola Mundo"
author = "Jose Ramon Palanco"
copyright = "MIT X11"
url = "http://www.monohispano.org"
description = ""
version = "0.01">
<Runtime>
<Import assembly="holamundo.dll"/>
</Runtime>
<Extension path = "/SharpDevelop/Commands">
<Command id = "MonoDevelop.HolaMundo.Commands.Command1"
_label = "_Hola Mundo"
defaultHandler = "MonoDevelop.HolaMundo.Test"
description = "Hola Mundo" />
</Extension>
<Extension path="/SharpDevelop/Workbench/MainMenu/Help">
<CommandItem id = "MonoDevelop.HolaMundo.Commands.Command1" insertafter="Separator2" insertbefore="Web"
/>
</Extension>
</AddIn>
En la etiqueta <Runtime> estamos importando holamundo.dll. En el path "/SharpDevelop/Workbench/MainMenu/Help" insertamos una entrada en el menú con identificador HolaMundo después de Web y antes del segundo separador con la etiqueta "Hola Mundo" que llama al comando HolaMundoCommand.
Ahora tenemos que hacer ese comando. Para ellos nos ponemos a escribir holamundo.cs.
using System;
using MonoDevelop.Core.AddIns.Codons;
using MonoDevelop.Commands;
namespace MonoDevelop.HolaMundo
{
public enum Commands
{
Command1
}
public class Test : CommandHandler
{
protected override void Run()
{
Console.WriteLine("Hola Mundo");
}
}
}
Aquí estamos heredando de AbstractMenuCommand (Core/src/MonoDevelop.Core/AddIns/Codons/AbstractCommand.cs). Vamos a ojearlo, ya que es muy pequeño:
using System;
using System.Collections;
using System.CodeDom.Compiler;
using MonoDevelop.Core.AddIns;
using MonoDevelop.Core.AddIns.Codons;
using MonoDevelop.Core.Properties;
namespace MonoDevelop.Core.AddIns.Codons
{
public abstract class AbstractCommand : ICommand
{
object owner = null;
public virtual object Owner {
get {
return owner;
}
set {
owner = value;
}
}
public abstract void Run();
}
}
AbstractCommand implementa ICommand y nos obliga (abstract) a implementar un método void Run() que es lo que hace el propio comando. En nuestro caso solo hemos escrito un "Hola Mundo". También podemos ver que nos permite sobre-escribir el acceso a owner, que ya veremos más adelante lo que es.
Para compilar (en Debian y Ubuntu) simplemente debemos de ejecutar:
$ mcs -r:/usr/lib/monodevelop/bin/MonoDevelop.Base.dll -target:library holamundo.cs
Para probar nuestro AddIn debemos colorcar el .xml y la .dll en /var/lib/monodevelop/AddIns/. Para que quede más ordenado es recomendable crear un directorio, ya que MonoDevelop es capaz de mirar dentro y queda todo más ordenadito:
$ sudo mkdir /var/lib/monodevelop/AddIns/HolaMundo $ sudo cp holamundo.dll holamundo.addin.xml /var/lib/monodevelop/AddIns/HolaMundo
Ahora podemos arrancar MonoDevelop y ejecutar nuestro nuevo menú. Veréis como en la consola aparece nuestro "Hola Mundo".
Buscador de koders.com
En desarrollo
Referencias
Mapa del código
| Nombre | Ubicación | Descricción | Dependencias |
| MonoDevelop.Core | src/Libraries/MonoDevelop.Core/ | Contains the bare necessities for the IDE | ninguna |
| MonoDevelop.Base | src/Main/Base/ | Es la base del IDE |
|
| gdl-sharp | gdldock/ | Binding of the gdl dock C library |
|
| ICSharpCode.SharpAssembly | src/Libraries/SharpAssembly/ | Librería de lectura de Assemblies | ninguna |
| ICSharpCode.SharpRefactory | src/Libraries/SharpRefactory/ | C# parser library | ninguna |
| MonoDevelop.SourceEditor | src/AddIns/DisplayBindings/SourceEditor/ | Editor por defecto de MonoDevelop |
|
| MonoDevelop.Gui.Utils | src/Libraries/MonoDevelop.Gui.Utils/ | Funciones adicionales extra |
|
| MonoDevelop.Gui.Widgets | src/Libraries/MonoDevelop.Gui.Widgets/ | Widgets específicos de gtk# |
|
| MonoDevelop.Debugger | src/AddIns/DebuggerAddIn/ | Librería de soporte de debugging |
|
| MonoDevelop.StartPage | src/AddIns/Misc/StartPage/ | Página de inicio del IDE |
|
| CSharpBinding | src/AddIns/BackendBindings/CSharpBinding/ | Backend for C# langauge support |
|
| JavaBinding | src/AddIns/BackendBindings/JavaBinding/ | Backend de Java langauge |
|
| StartUp | src/Main/StartUp/ | Parsea la línea de comandos e invoca al resto de componentes |
|
Créditos, Licencia y Errata
Los registros de iconos aún no están funcionando, pero se pueden ver ejemplos de como registrarlos via addin.xml en svn:
- (svn) Extras/MonoQuery/MonoQuery/MonoQuery.addin.xml
- (svn) Extras/MonoQuery/MonoQuery/Gui/NodeBuilders/TablesNodeBuilder.cs
En el segundo archivo podremos ver:
label = GettextCatalog.GetString ("Tables");
string iconName = "md-mono-query-tables";
icon = Context.GetIcon (iconName);
TablesNode node = (TablesNode) dataObject;
node.RefreshEvent += RefreshHandler;
"md-mono-query-tables" a los iconos definidos en MonoQuery.addin.xml. Los iconos se almacenan como recurso en la .dll del add-in
Enviad comentarios a Jose Ramon Palanco (mailto:jose.palanco@hazent.com)
Send comments to jluke (mailto:jluke@cfl.rr.com) or the MonoDevelop mailing list (mailto:monodevelop-list@lists.ximian.com)
Licensed under the MIT License

Powered by MediaWiki