git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@4257 ea778897-0a13-0410-b9d1-a72fbfd435f5
		
			
				
	
	
		
			431 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			431 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| =============
 | |
| Hacking Geany
 | |
| =============
 | |
| .. contents::
 | |
| 
 | |
| General
 | |
| =======
 | |
| 
 | |
| About this file
 | |
| ---------------
 | |
| This file contains information for anyone wanting to work on the Geany
 | |
| codebase. You should be aware of the open source licenses used - see
 | |
| the README file or the documentation. It is reStructuredText; the
 | |
| source file is HACKING. You can generate hacking.html by running ``make
 | |
| hacking-doc`` from the doc/ subdirectory.
 | |
| 
 | |
| Writing plugins
 | |
| ---------------
 | |
| * src/plugindata.h contains the plugin API data types.
 | |
| * See plugins/demoplugin.c for a very basic example plugin.
 | |
| * src/plugins.c loads and unloads plugins (you shouldn't need to read
 | |
|   this really).
 | |
| * The API documentation contains a few basic guidelines and hints to
 | |
|   write plugins.
 | |
| 
 | |
| You should generate and read the plugin API documentation, see below.
 | |
| 
 | |
| Plugin API documentation
 | |
| ^^^^^^^^^^^^^^^^^^^^^^^^
 | |
| You can generate documentation for the plugin API using the doxygen
 | |
| tool. Run ``make api-doc`` in the doc subdirectory. The documentation
 | |
| will be output to doc/reference/index.html.
 | |
| Alternatively you can view the API documentation online at
 | |
| http://www.geany.org/manual/reference/.
 | |
| 
 | |
| Patches
 | |
| -------
 | |
| We are happy to receive patches, but it's best to check with us by email
 | |
| or mailing list whether a new feature is appropriate, and whether someone
 | |
| is already working on similar code.
 | |
| 
 | |
| In general it's best to work from the current SVN, but we accept patches
 | |
| against other releases::
 | |
| 
 | |
|     $ svn diff > fix-some-bug.patch
 | |
| 
 | |
| If you're not using SVN, you can use the diff command::
 | |
| 
 | |
|     $ diff -u originalpath modifiedpath > new-feature.patch
 | |
| 
 | |
| .. note::
 | |
|     Please make sure patches follow the style of existing code - In
 | |
|     particular, use tabs for indentation. See `Coding`_.
 | |
| 
 | |
| Windows tools
 | |
| -------------
 | |
| * Subversion (SVN): http://subversion.tigris.org/
 | |
| * diff, grep, etc: http://mingw.org/ or http://unxutils.sourceforge.net/
 | |
| 
 | |
| See also the 'Building on Windows' document on the website.
 | |
| 
 | |
| File organization
 | |
| -----------------
 | |
| callbacks.c is just for Glade callbacks.
 | |
| Avoid adding code to geany.h if it will fit better elsewhere.
 | |
| See the top of each ``src/*.c`` file for a brief description of what
 | |
| it's for.
 | |
| 
 | |
| Keeping the plugin ABI stable
 | |
| -----------------------------
 | |
| Please be aware that anything with a doc-comment (a comment with an
 | |
| extra asterix: ``/**``) is something in the plugin API. Things like
 | |
| enums and structs can usually still be appended to, ensuring that all
 | |
| the existing elements stay in place - this will keep the ABI stable.
 | |
| 
 | |
| .. warning::
 | |
| 
 | |
|     Some structs like GeanyKeyGroupInfo and GeanyCallback cannot be
 | |
|     appended to without breaking the ABI because they are used to declare
 | |
|     structs by plugins, not just for accessing struct members through
 | |
|     a pointer.
 | |
| 
 | |
| Before the 1.0 release series, the ABI can change when necessary, and
 | |
| even the API can change. An ABI change just means that all plugins will
 | |
| not load and they must be rebuilt. An API change means that some plugins
 | |
| might not build correctly.
 | |
| 
 | |
| If you're reordering or changing existing elements of structs that are
 | |
| used as part of the plugin API, you should increment GEANY_ABI_VERSION
 | |
| in plugindata.h. This is usually not needed if you're just appending
 | |
| fields to structs. The GEANY_API_VERSION value should be incremented
 | |
| for any changes to the plugin API, including appending elements.
 | |
| 
 | |
| If you're in any doubt when making changes to plugin API code, just ask us.
 | |
| 
 | |
| Plugin API/ABI design
 | |
| ^^^^^^^^^^^^^^^^^^^^^
 | |
| You should not make plugins rely on the size of a struct. This means:
 | |
| 
 | |
| * Don't let plugins allocate any structs (stack or heap).
 | |
| * Don't let plugins index any arrays of structs.
 | |
| * Don't add any array fields to structs in case we want to change the
 | |
|   array size later.
 | |
| 
 | |
| Glade
 | |
| -----
 | |
| Use the code generation features of Glade instead of editing interface.c
 | |
| or support.c. Glade 2.12 is recommended as long as we support GTK+ 2.8,
 | |
| because later versions of Glade are not 100% compatible with GTK+ 2.8
 | |
| (e.g. they may use functions added in GTK+ 2.10).
 | |
| 
 | |
| You can build Glade 2.12 and run the binary in place, without installing
 | |
| it - this should work fine even if you have another version of Glade
 | |
| installed on the system.
 | |
| 
 | |
| GTK API documentation
 | |
| ---------------------
 | |
| The official GTK 2.8 API documentation is not available online anymore,
 | |
| so we put them on http://www.geany.org/manual/gtk/.
 | |
| There is also a tarball with all available files for download and use
 | |
| with devhelp.
 | |
| 
 | |
| Using the 2.8 API documentation of the GTK libs (including GLib, GDK and
 | |
| Pango) has the advantages that you don't get confused by any newer API
 | |
| additions and you don't have to take care about whether you can use
 | |
| them or not.
 | |
| This is because Geany depends on GTK 2.8. API symbols from newer
 | |
| GTK/GLib versions should be avoided to keep the source code building
 | |
| against GTK 2.8.
 | |
| 
 | |
| Coding
 | |
| ------
 | |
| * Don't write long functions with a lot of variables and/or scopes - break
 | |
|   them down into smaller static functions where possible. This makes code
 | |
|   much easier to read and maintain.
 | |
| * Use GLib types and functions - gint not int, g_free() not free().
 | |
| * Your code should build against GLib 2.8 and GTK 2.8. At least for the
 | |
|   moment, we want to keep the minimum requirement for GTK at 2.8 (of
 | |
|   course, you can use the GTK_CHECK_VERSION macro to protect code using
 | |
|   later versions).
 | |
| * Variables should be declared before statements. You can use
 | |
|   gcc's -Wdeclaration-after-statement to warn about this.
 | |
| * Don't let variable names shadow outer variables - use gcc's -Wshadow
 | |
|   option.
 | |
| 
 | |
| Compiler options & warnings
 | |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | |
| Use ``CFLAGS='-Wfoo' ./configure`` or ``CFLAGS='-Wfoo' ./autogen.sh``
 | |
| to set warning options (as well as anything else e.g. -g -O2).
 | |
| 
 | |
| * Enable warnings - for gcc use '-Wall -W' (and optionally
 | |
|   -Wno-unused-parameter to avoid unused parameter warnings in Glade
 | |
|   callbacks).
 | |
| * You should try to write ISO C90 code for portability, so always
 | |
|   use C ``/* */`` comments and function_name(void) instead of
 | |
|   function_name(). This is for compatibility with various Unix-like
 | |
|   compilers. You should use -ansi to help check this.
 | |
| 
 | |
| Style
 | |
| ^^^^^
 | |
| * We use a tab width of 4 and indent completely with tabs not spaces.
 | |
|   Note the documentation files use (4) spaces instead, so you may want
 | |
|   to use the 'Detect from file' indent pref.
 | |
| * Use the multiline comment ``/* */`` to comment small blocks of code,
 | |
|   functions descriptions or longer explanations of code, etc. C++ single
 | |
|   line comments will cause portability issues. The more comments are in
 | |
|   your code the better. (See also ``scripts/fix-cxx-comments.pl`` in SVN).
 | |
| * Lines should not be longer than about 100 characters and after 100
 | |
|   characters the lines should be wrapped and indented once more to
 | |
|   show that the line is continued.
 | |
| * We don't put spaces between function names and the opening brace for
 | |
|   argument lists.
 | |
| * Variable declarations come first after an opening brace, then one
 | |
|   newline to separate declarations and code.
 | |
| * 2-operand operators should have a space each side.
 | |
| * Function bodies should have 2 blank newlines after them.
 | |
| * Align braces together on separate lines.
 | |
| * Don't put assignments in 'if/while/etc' expressions.
 | |
| * if statements without brace bodies should have the code on a separate
 | |
|   line, then a blank line afterwards.
 | |
| * Use braces after if/while statements if the body uses another
 | |
|   if/while statement.
 | |
| * Try to fit in with the existing code style.
 | |
| 
 | |
| .. note::
 | |
|     A few of the above can be done with the SVN
 | |
|     ``scripts/fix-alignment.pl``, but it is quite dumb and it's much better
 | |
|     to write it correctly in the first place.
 | |
| 
 | |
| .. below tabs should be used, but spaces are required for reST.
 | |
| 
 | |
| Example::
 | |
| 
 | |
|     gint some_func(void);
 | |
| 
 | |
| 
 | |
|     gint function_long_name(gchar arg1, <too many args to fit on this line>,
 | |
|             gchar argN)
 | |
|     {
 | |
|         gint foo, bar;  /* variables can go on the same line */
 | |
|         gchar *ptr;     /* pointer symbol must go next to variable name, not type */
 | |
|         gchar *another; /* pointers should normally go on separate lines */
 | |
| 
 | |
|         if (foo)
 | |
|         {
 | |
|             gint dir = -1;    /* -1 to search backwards */
 | |
| 
 | |
|             bar = foo;
 | |
|             if ((bar & (guint)dir) != 7)
 | |
|                 some_code(arg1, <too many args to fit on this line>,
 | |
|                     argN - 1, argN);
 | |
| 
 | |
|             some_func();
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     gint another_function(void)
 | |
|     {
 | |
|         ...
 | |
| 
 | |
| 
 | |
| Libraries
 | |
| ---------
 | |
| We prefer to use an unmodified version of Scintilla - any changes should
 | |
| be passed on to the maintainers at http://scintilla.org.
 | |
| 
 | |
| Tagmanager was originally taken from Anjuta 1.2.2, and parts of it
 | |
| (notably c.c) have been merged from later versions of Anjuta and
 | |
| CTags. The independent Tagmanager library itself ceased development
 | |
| before Geany was started. It's source code parsing is mostly taken from
 | |
| Exuberant CTags (see http://ctags.sf.net).
 | |
| 
 | |
| 
 | |
| Notes
 | |
| =====
 | |
| Some of these notes below are brief (or maybe incomplete) - please
 | |
| contact the geany-devel mailing list for more information.
 | |
| 
 | |
| Using pre-defined autotools values
 | |
| ----------------------------------
 | |
| When you are use macros supplied by the autotools like GEANY_PREFIX,
 | |
| GEANY_LIBDIR, GEANY_DATADIR and GEANY_LOCALEDIR be aware that these
 | |
| might not be static strings when Geany is configured with
 | |
| --enable-binreloc. Then these macros will be replaced by function calls
 | |
| (in src/prefix.h). So, don't use anything like
 | |
| printf("Prefix: " GEANY_PREFIX); but instead use
 | |
| printf("Prefix: %s", GEANY_PREFIX);
 | |
| 
 | |
| Adding a source file foo.[hc] in src/ or plugins/
 | |
| -------------------------------------------------
 | |
| * Add foo.c, foo.h to SRCS in path/Makefile.am.
 | |
| * Add foo.o to OBJS in path/makefile.win32.
 | |
| * Add path/foo.c to geany_sources in wscript.
 | |
| * Add path/foo.c to po/POTFILES.in (for string translation).
 | |
| 
 | |
| Adding a filetype
 | |
| -----------------
 | |
| You can add a filetype without syntax highlighting or tag parsing, but
 | |
| check to see if those features have been written in other projects first.
 | |
| 
 | |
| * Add GEANY_FILETYPES_FOO to filetypes.h.
 | |
| * Initialize GEANY_FILETYPES_FOO in init_builtin_filetypes() of
 | |
|   filetypes.c. You should use filetype_make_title() to avoid a
 | |
|   translation whenever possible.
 | |
| * Update data/filetype_extensions.conf.
 | |
| 
 | |
| filetypes.* configuration file
 | |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | |
| All languages need a data/filetypes.foo configuration file. See
 | |
| the "Filetype definition files" section in the manual and/or
 | |
| data/filetypes.c for an example.
 | |
| 
 | |
| Programming languages should have:
 | |
| 
 | |
| * [keywords] if the lexer supports it.
 | |
| * [settings] mostly for comment settings.
 | |
| * [build_settings] for commands to run.
 | |
| 
 | |
| For languages with a Scintilla lexer, there should be a [styling] section,
 | |
| to correspond to the styles used in styleset_foo() in highlighting.c -
 | |
| see below.
 | |
| 
 | |
| Syntax highlighting
 | |
| ^^^^^^^^^^^^^^^^^^^
 | |
| It may be possible to use an existing Scintilla lexer in the scintilla/
 | |
| subdirectory - if not, you will need to find (or write) one,
 | |
| LexFoo.cxx. Try the official Scintilla project first.
 | |
| 
 | |
| .. warning::
 | |
|     We won't accept adding a lexer that conflicts with one in
 | |
|     Scintilla. All new lexers should be submitted back to the Scintilla
 | |
|     project to save duplication of work.
 | |
| 
 | |
| When adding a lexer, update:
 | |
| 
 | |
| * scintilla/Makefile.am
 | |
| * scintilla/makefile.win32
 | |
| * wscript
 | |
| * scintilla/KeyWords.cxx - add a LINK_LEXER command *manually*
 | |
| 
 | |
| For syntax highlighting, you will need to edit highlighting.c and add
 | |
| the following things:
 | |
| 
 | |
| 1. Write styleset_foo_init() to setup lexer styles and load style
 | |
|    settings from the filetypes.foo configuration file. You should probably
 | |
|    start by copying and adapting another filetype's initialization, such
 | |
|    as styleset_tcl_init(). You may want to use load_style_entries().
 | |
| 2. Write styleset_foo() to apply styles when a new scintilla widget
 | |
|    is created. Again you could copy and adapt a function like
 | |
|    styleset_tcl(). You may want to use apply_style_entries().
 | |
| 3. In highlighting_init_styles(), add
 | |
|    ``init_styleset_case(GEANY_FILETYPES_FOO, styleset_foo_init);``.
 | |
| 4. In highlighting_set_styles(), add
 | |
|    ``styleset_case(GEANY_FILETYPES_FOO, styleset_foo);``.
 | |
| 5. Write data/filetypes.foo configuration file [styling] section. See
 | |
|    the manual and see data/filetypes.d for a named style example.
 | |
| 
 | |
| .. note::
 | |
|     Please try to make your styles fit in with the other filetypes'
 | |
|     default colors, and to use named styles where possible (e.g.
 | |
|     "commentline=comment"). Filetypes that share a lexer should have
 | |
|     the same colors. If not using named styles, leave the background color
 | |
|     empty to match the default color.
 | |
| 
 | |
| Error message parsing
 | |
| ^^^^^^^^^^^^^^^^^^^^^
 | |
| New-style error message parsing is done with an extended GNU-style regex
 | |
| stored in the filetypes.foo file - see the [build_settings] information
 | |
| in the manual for details.
 | |
| 
 | |
| Old-style error message parsing is done in
 | |
| msgwin_parse_compiler_error_line() of msgwindow.c - see the ParseData
 | |
| typedef for more information.
 | |
| 
 | |
| Other features
 | |
| ^^^^^^^^^^^^^^
 | |
| For brace indentation, update lexer_has_braces() in editor.c;
 | |
| indentation after ':' is done from on_new_line_added().
 | |
| 
 | |
| If the lexer has comment styles, you should add them in is_comment_style()
 | |
| in editor.c. You should also update is_string_style() for string/character
 | |
| styles. For now, this prevents calltips and autocompletion when typing
 | |
| in a comment (but it can still be forced by the user).
 | |
| 
 | |
| If the Scintilla lexer supports user type keyword highlighting (e.g.
 | |
| SCLEX_CPP), update editor_lexer_get_type_keyword_idx() in editor.c.
 | |
| 
 | |
| Adding a TagManager parser
 | |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
 | |
| This assumes the filetype for Geany already exists.
 | |
| 
 | |
| First write or find a CTags compatible parser, foo.c. Note that there
 | |
| are some language patches for CTags at:
 | |
| http://sf.net/projects/ctags - see the tracker.
 | |
| 
 | |
| (You can also try the Anjuta project's tagmanager codebase.)
 | |
| 
 | |
| * Add foo.c to SRCS in Makefile.am.
 | |
| * Add foo.o to OBJS in makefile.win32.
 | |
| * Add path/foo.c to geany_sources in wscript.
 | |
| * Add Foo to parsers.h & fill in comment with parser number for foo.
 | |
| 
 | |
| In foo.c:
 | |
| Edit FooKinds 3rd column to match a s_tag_type_names string in tm_tag.c.
 | |
| 
 | |
| In filetypes.c, init_builtin_filetypes():
 | |
| Set filetypes[GEANY_FILETYPES_FOO].lang = foo's parser number.
 | |
| 
 | |
| In symbols.c:
 | |
| If your parser doesn't use C-like tag type names, update
 | |
| add_top_level_items() for foo, calling tag_list_add_groups().
 | |
| 
 | |
| 
 | |
| GDB
 | |
| ---
 | |
| 
 | |
| Stop on warnings
 | |
| ^^^^^^^^^^^^^^^^
 | |
| When a GLib or GTK warning is printed, often you want to get a
 | |
| backtrace to find out what code caused them. You can do that with the
 | |
| ``--g-fatal-warnings`` argument, which will abort Geany on the first
 | |
| warning it receives.
 | |
| 
 | |
| But for ordinary testing, you don't always want your editor to abort
 | |
| just because of a warning - use::
 | |
| 
 | |
|     (gdb) b handler_log if level <= G_LOG_LEVEL_WARNING
 | |
| 
 | |
| 
 | |
| Running with batch commands
 | |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | |
| Use::
 | |
| 
 | |
|     $ gdb src/geany -x gdb-commands
 | |
| 
 | |
| Where ``gdb-commands`` is a file with the following lines::
 | |
| 
 | |
|     set pagination off
 | |
|     b handler_log if level <= G_LOG_LEVEL_WARNING
 | |
|     r -v
 | |
| 
 | |
| 
 | |
| Loading a plugin
 | |
| ^^^^^^^^^^^^^^^^
 | |
| This is useful so you can load plugins without installing them first.
 | |
| Alternatively you can use a symlink in ~/.config/geany/plugins or
 | |
| $prefix/lib/geany (where $prefix is /usr/local by default).
 | |
| 
 | |
| The gdb session below was run from the toplevel Geany source directory.
 | |
| Start normally with e.g. "gdb src/geany".
 | |
| Type 'r' to run.
 | |
| Press Ctrl-C from the gdb window to interrupt program execution.
 | |
| 
 | |
| Example::
 | |
| 
 | |
|     Program received signal SIGINT, Interrupt.
 | |
|     0x00d16402 in __kernel_vsyscall ()
 | |
|     (gdb) call plugin_new("./plugins/.libs/demoplugin.so")
 | |
|     ** INFO: Loaded:   ./plugins/.libs/demoplugin.so (Demo)
 | |
|     $1 = (Plugin *) 0x905a890
 | |
|     (gdb) c
 | |
|     Continuing.
 | |
| 
 | |
|     Program received signal SIGINT, Interrupt.
 | |
|     0x00d16402 in __kernel_vsyscall ()
 | |
|     (gdb) call plugin_free(0x905a890)
 | |
|     ** INFO: Unloaded: ./plugins/.libs/demoplugin.so
 | |
|     (gdb) c
 | |
|     Continuing.
 |