Synced with upstream

master
Yevgen Muntyan 2008-08-17 17:09:42 -05:00
parent 02d45051ec
commit d52003fc0f
4 changed files with 264 additions and 50 deletions

View File

@ -27,6 +27,7 @@
#include "gtksourcelanguage-private.h"
#include "gtksourcelanguage.h"
#include "gtksourceview-utils.h"
#include <gio/gio.h>
#define RNG_SCHEMA_FILE "language2.rng"
#define LANGUAGE_DIR "language-specs"
@ -408,3 +409,210 @@ gtk_source_language_manager_get_language (GtkSourceLanguageManager *lm,
return g_hash_table_lookup (lm->priv->language_ids, id);
}
static GtkSourceLanguage *
pick_lang_for_filename (GtkSourceLanguageManager *lm,
const gchar *filename)
{
char *filename_utf8;
const gchar* const * p;
/* Use g_filename_display_name() instead of g_filename_to_utf8() because
* g_filename_display_name() doesn't fail and replaces non-convertible
* characters to unicode substitution symbol. */
filename_utf8 = g_filename_display_name (filename);
for (p = gtk_source_language_manager_get_language_ids (lm);
p != NULL && *p != NULL;
p++)
{
GtkSourceLanguage *lang;
gchar **globs, **gptr;
lang = gtk_source_language_manager_get_language (lm, *p);
globs = gtk_source_language_get_globs (lang);
for (gptr = globs; gptr != NULL && *gptr != NULL; gptr++)
{
/* FIXME g_pattern_match is wrong: there are no '[...]'
* character ranges and '*' and '?' can not be escaped
* to include them literally in a pattern. */
if (g_pattern_match_simple (*gptr, filename_utf8))
{
g_strfreev (globs);
g_free (filename_utf8);
return lang;
}
}
g_strfreev (globs);
}
g_free (filename_utf8);
return NULL;
}
static GtkSourceLanguage *
pick_lang_for_mime_type_pass (GtkSourceLanguageManager *lm,
const char *mime_type,
gboolean exact_match)
{
const gchar* const * id_ptr;
for (id_ptr = gtk_source_language_manager_get_language_ids (lm);
id_ptr != NULL && *id_ptr != NULL;
id_ptr++)
{
GtkSourceLanguage *lang;
gchar **mime_types, **mptr;
lang = gtk_source_language_manager_get_language (lm, *id_ptr);
mime_types = gtk_source_language_get_mime_types (lang);
for (mptr = mime_types; mptr != NULL && *mptr != NULL; mptr++)
{
gboolean matches;
if (exact_match)
matches = strcmp (mime_type, *mptr) == 0;
else
matches = g_content_type_is_a (mime_type, *mptr);
if (matches)
{
g_strfreev (mime_types);
return lang;
}
}
g_strfreev (mime_types);
}
return NULL;
}
static GtkSourceLanguage *
pick_lang_for_mime_type (GtkSourceLanguageManager *lm,
const char *mime_type)
{
GtkSourceLanguage *lang;
lang = pick_lang_for_mime_type_pass (lm, mime_type, TRUE);
if (!lang)
lang = pick_lang_for_mime_type_pass (lm, mime_type, FALSE);
return lang;
}
#ifdef G_OS_WIN32
static void
grok_win32_content_type (const gchar *content_type,
gchar **alt_filename,
gchar **mime_type)
{
*alt_filename = NULL;
*mime_type = NULL;
/* If it contains slash, then it's probably a mime type.
* Otherwise treat is an extension. */
if (strchr (content_type, '/') != NULL)
*mime_type = g_strdup (content_type);
else
*alt_filename = g_strjoin ("filename", content_type, NULL);
}
#endif
/**
* gtk_source_language_manager_guess_language:
* @lm: a #GtkSourceLanguageManager.
* @filename: a filename in Glib filename encoding, or %NULL.
* @content_type: a content type (as in GIO API), or %NULL.
*
* Picks a #GtkSourceLanguage for given file name and content type,
* according to the information in lang files. Either @filename or
* @content_type may be %NULL. This function can be used as follows:
*
* <informalexample><programlisting>
* GtkSourceLanguage *lang;
* lang = gtk_source_language_manager_guess_language (filename, NULL);
* gtk_source_buffer_set_language (buffer, lang);
* </programlisting></informalexample>
*
* or
*
* <informalexample><programlisting>
* GtkSourceLanguage *lang = NULL;
* gboolean result_uncertain;
* gchar *content_type;
*
* content_type = g_content_type_guess (filename, NULL, 0, &result_uncertain);
* if (result_uncertain)
* {
* g_free (content_type);
* content_type = NULL;
* }
*
* lang = gtk_source_language_manager_guess_language (manager, filename, content_type);
* gtk_source_buffer_set_language (buffer, lang);
*
* g_free (content_type);
* </programlisting></informalexample>
*
* etc. Use gtk_source_language_get_mime_types() and gtk_source_language_get_globs()
* if you need full control over file -> language mapping.
*
* Returns: a #GtkSourceLanguage, or %NULL if there is no suitable language
* for given @filename and/or @content_type. Return value is owned by @lm
* and should not be freed.
*
* Since: 2.4
*/
GtkSourceLanguage *
gtk_source_language_manager_guess_language (GtkSourceLanguageManager *lm,
const gchar *filename,
const gchar *content_type)
{
GtkSourceLanguage *lang = NULL;
g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE_MANAGER (lm), NULL);
g_return_val_if_fail (filename != NULL || content_type != NULL, NULL);
g_return_val_if_fail ((filename == NULL || *filename != 0) &&
(content_type == NULL || *content_type != 0), NULL);
ensure_languages (lm);
/* TODO
> Maybe the logic should be:
> - match mime
> - match glob
> - if just one matches use it
> - if they both match and the corresponding mime inside the lang files are one
> the anchestor of the other pick the more strict lang
> - if they both match and the corresponding mime inside the lang files are
> unrelated, pick the glob one
*/
if (filename != NULL)
lang = pick_lang_for_filename (lm, filename);
if (lang == NULL && content_type != NULL)
{
#ifndef G_OS_WIN32
/* On Unix "content type" is mime type */
lang = pick_lang_for_mime_type (lm, content_type);
#else
/* On Windows "content type" is an extension, but user may pass a mime type too */
gchar *mime_type;
gchar *alt_filename;
grok_win32_content_type (content_type, &alt_filename, &mime_type);
if (alt_filename != NULL)
lang = pick_lang_for_filename (lm, alt_filename);
if (lang == NULL && mime_type != NULL)
lang = pick_lang_for_mime_type (lm, mime_type);
g_free (mime_type);
g_free (alt_filename);
#endif
}
return lang;
}

View File

@ -74,6 +74,10 @@ G_CONST_RETURN gchar* G_CONST_RETURN *
GtkSourceLanguage *gtk_source_language_manager_get_language (GtkSourceLanguageManager *lm,
const gchar *id);
GtkSourceLanguage *gtk_source_language_manager_guess_language (GtkSourceLanguageManager *lm,
const gchar *filename,
const gchar *content_type);
G_END_DECLS

View File

@ -41,7 +41,7 @@
<style id="keyword" _name="Keyword" map-to="def:keyword"/>
<style id="type" _name="Data Type" map-to="def:type"/>
<style id="storage-class" _name="Storage Class" map-to="def:type"/>
<style id="printf" _name="printf Conversion" map-to="def:character"/>
<style id="printf" _name="printf Conversion" map-to="def:special-char"/>
<style id="escaped-character" _name="Escaped Character" map-to="def:special-char"/>
<style id="floating-point" _name="Floating point number" map-to="def:floating-point"/>
<style id="decimal" _name="Decimal number" map-to="def:decimal"/>

View File

@ -296,81 +296,83 @@
<context id="common-command" style-ref="common-command">
<prefix>(?&lt;![\w\-\.])</prefix>
<suffix>(?![\w\-\.])</suffix>
<keyword>cp</keyword>
<keyword>rm</keyword>
<keyword>mv</keyword>
<keyword>which</keyword>
<keyword>cat</keyword>
<keyword>grep</keyword>
<keyword>sed</keyword>
<keyword>awk</keyword>
<keyword>mkdir</keyword>
<keyword>rmdir</keyword>
<keyword>ls</keyword>
<keyword>ps</keyword>
<keyword>killall</keyword>
<keyword>pidof</keyword>
<keyword>diff</keyword>
<keyword>head</keyword>
<keyword>tail</keyword>
<keyword>chown</keyword>
<keyword>chmod</keyword>
<keyword>dd</keyword>
<keyword>find</keyword>
<keyword>locate</keyword>
<keyword>tar</keyword>
<keyword>gunzip</keyword>
<keyword>gzip</keyword>
<keyword>beep</keyword>
<keyword>bunzip2</keyword>
<keyword>bzip2</keyword>
<keyword>zip</keyword>
<keyword>unzip</keyword>
<keyword>mount</keyword>
<keyword>umount</keyword>
<keyword>sh</keyword>
<keyword>cat</keyword>
<keyword>chmod</keyword>
<keyword>chown</keyword>
<keyword>clear</keyword>
<keyword>wget</keyword>
<keyword>cp</keyword>
<keyword>date</keyword>
<keyword>dd</keyword>
<keyword>df</keyword>
<keyword>dialog</keyword>
<keyword>diff</keyword>
<keyword>dir</keyword>
<keyword>du</keyword>
<keyword>eject</keyword>
<keyword>expr</keyword>
<keyword>su</keyword>
<keyword>passwd</keyword>
<keyword>man</keyword>
<keyword>info</keyword>
<keyword>file</keyword>
<keyword>find</keyword>
<keyword>gcc</keyword>
<keyword>grep</keyword>
<keyword>gunzip</keyword>
<keyword>gzip</keyword>
<keyword>head</keyword>
<keyword>id</keyword>
<keyword>ifconfig</keyword>
<keyword>gcc</keyword>
<keyword>make</keyword>
<keyword>ld</keyword>
<keyword>ln</keyword>
<keyword>lsmod</keyword>
<keyword>info</keyword>
<keyword>insmod</keyword>
<keyword>modprobe</keyword>
<keyword>killall</keyword>
<keyword>ld</keyword>
<keyword>less</keyword>
<keyword>ln</keyword>
<keyword>locate</keyword>
<keyword>ls</keyword>
<keyword>lsmod</keyword>
<keyword>make</keyword>
<keyword>man</keyword>
<keyword>mkdir</keyword>
<keyword>modprobe</keyword>
<keyword>more</keyword>
<keyword>mount</keyword>
<keyword>mv</keyword>
<keyword>nice</keyword>
<keyword>passwd</keyword>
<keyword>patch</keyword>
<keyword>pidof</keyword>
<keyword>ping</keyword>
<keyword>pkg-config</keyword>
<keyword>nice</keyword>
<keyword>ps</keyword>
<keyword>renice</keyword>
<keyword>file</keyword>
<keyword>rmdir</keyword>
<keyword>rm</keyword>
<keyword>sed</keyword>
<keyword>sh</keyword>
<keyword>sleep</keyword>
<keyword>sort</keyword>
<keyword>sudo</keyword>
<keyword>beep</keyword>
<keyword>su</keyword>
<keyword>tail</keyword>
<keyword>tar</keyword>
<keyword>tempfile</keyword>
<keyword>touch</keyword>
<keyword>eject</keyword>
<keyword>tr</keyword>
<keyword>umount</keyword>
<keyword>uname</keyword>
<keyword>uniq</keyword>
<keyword>unzip</keyword>
<keyword>uptime</keyword>
<keyword>wget</keyword>
<keyword>whereis</keyword>
<keyword>which</keyword>
<keyword>whoami</keyword>
<keyword>who</keyword>
<keyword>whereis</keyword>
<keyword>sleep</keyword>
<keyword>dialog</keyword>
<keyword>xdialog</keyword>
<keyword>zenity</keyword>
<keyword>sort</keyword>
<keyword>uniq</keyword>
<keyword>zip</keyword>
</context>
<context id="case">