[gtksourceview] language: add support for gresources



commit cee9447f788755f1f9ed17a68dec0b11d9ec4399
Author: Christian Hergert <chergert redhat com>
Date:   Thu Jan 27 17:05:47 2022 -0800

    language: add support for gresources
    
    This allows you to specify a resource:///path/ to load language specs
    from without having to install them to the system.
    
    Fixes #253

 gtksourceview/gtksourcelanguage.c | 57 +++++++++++++++++++++++++++------------
 testsuite/meson.build             |  7 ++++-
 testsuite/test-languagemanager.c  | 22 +++++++++++++++
 testsuite/testsuite.gresource.xml |  6 +++++
 testsuite/testsuite.lang          | 43 +++++++++++++++++++++++++++++
 5 files changed, 117 insertions(+), 18 deletions(-)
---
diff --git a/gtksourceview/gtksourcelanguage.c b/gtksourceview/gtksourcelanguage.c
index c17df9d7..a7a0c6e5 100644
--- a/gtksourceview/gtksourcelanguage.c
+++ b/gtksourceview/gtksourcelanguage.c
@@ -97,18 +97,35 @@ _gtk_source_language_new_from_file (const gchar              *filename,
 {
        GtkSourceLanguage *lang = NULL;
        xmlTextReaderPtr reader = NULL;
+       GBytes *bytes = NULL;
        gint ret;
-       gint fd;
+       gint fd = -1;
 
        g_return_val_if_fail (filename != NULL, NULL);
        g_return_val_if_fail (lm != NULL, NULL);
 
-       /*
-        * Use fd instead of filename so that it's utf8 safe on w32.
-        */
-       fd = g_open (filename, O_RDONLY, 0);
-       if (fd != -1)
-               reader = xmlReaderForFd (fd, filename, NULL, 0);
+       if (g_str_has_prefix (filename, "resource://"))
+       {
+               const char *path = filename + strlen ("resource://");
+
+               bytes = g_resources_lookup_data (path, 0, NULL);
+
+               if (bytes != NULL)
+               {
+                       reader = xmlReaderForMemory (g_bytes_get_data (bytes, NULL),
+                                                    g_bytes_get_size (bytes),
+                                                    NULL, NULL, 0);
+               }
+       }
+       else
+       {
+               /*
+                * Use fd instead of filename so that it's utf8 safe on w32.
+                */
+               fd = g_open (filename, O_RDONLY, 0);
+               if (fd != -1)
+                       reader = xmlReaderForFd (fd, filename, NULL, 0);
+       }
 
        if (reader != NULL)
        {
@@ -135,23 +152,14 @@ _gtk_source_language_new_from_file (const gchar              *filename,
                                ret = xmlTextReaderRead (reader);
                }
 
-               xmlFreeTextReader (reader);
-               close (fd);
-
                if (ret != 0)
                {
-                   g_warning("Failed to parse '%s'", filename);
-                   return NULL;
+                   g_warning ("Failed to parse '%s'", filename);
                }
         }
        else
        {
                g_warning ("Unable to open '%s'", filename);
-
-               if (fd != -1)
-               {
-                       close (fd);
-               }
        }
 
        if (lang != NULL)
@@ -161,6 +169,21 @@ _gtk_source_language_new_from_file (const gchar              *filename,
                                           (gpointer) &lang->language_manager);
        }
 
+       if (reader != NULL)
+       {
+               xmlFreeTextReader (reader);
+       }
+
+       if (fd != -1)
+       {
+               close (fd);
+       }
+
+       if (bytes != NULL)
+       {
+               g_bytes_unref (bytes);
+       }
+
        return lang;
 }
 
diff --git a/testsuite/meson.build b/testsuite/meson.build
index 2940639f..1dbd2816 100644
--- a/testsuite/meson.build
+++ b/testsuite/meson.build
@@ -14,6 +14,11 @@ testsuite_c_args = [
   '-UG_DISABLE_CAST_CHECKS',
 ]
 
+testsuite_res = gnome.compile_resources(
+  'testsuite-gresources',
+  'testsuite.gresource.xml'
+)
+
 testsuite_sources = [
   ['test-buffer'],
   ['test-buffer-input-stream'],
@@ -44,7 +49,7 @@ testsuite_sources = [
 
 foreach test: testsuite_sources
   test_name = test.get(0)
-  test_sources = gtksource_res + [
+  test_sources = gtksource_res + testsuite_res + [
     '@0@.c'.format(test_name),
   ]
 
diff --git a/testsuite/test-languagemanager.c b/testsuite/test-languagemanager.c
index ced5ce0f..7ca0aa62 100644
--- a/testsuite/test-languagemanager.c
+++ b/testsuite/test-languagemanager.c
@@ -23,6 +23,8 @@
 #include <gtk/gtk.h>
 #include <gtksourceview/gtksource.h>
 
+#include "testsuite-gresources.h"
+
 /* If we are running from the source dir (e.g. during make check)
  * we override the path to read from the data dir
  */
@@ -185,6 +187,25 @@ test_guess_language (void)
 #endif
 }
 
+static void
+test_resources (void)
+{
+       GtkSourceLanguageManager *lm = gtk_source_language_manager_new ();
+       const char * const search_path[] = { "resource:///language-specs/", NULL };
+       const char * const *ids;
+
+       g_resources_register (testsuite_get_resource ());
+
+       gtk_source_language_manager_set_search_path (lm, search_path);
+       ids = gtk_source_language_manager_get_language_ids (lm);
+
+       g_assert_nonnull (ids);
+       g_assert_cmpstr (ids[0], ==, "testsuite");
+       g_assert_null (ids[1]);
+
+       g_object_unref (lm);
+}
+
 int
 main (int argc, char** argv)
 {
@@ -199,6 +220,7 @@ main (int argc, char** argv)
        g_test_add_func ("/LanguageManager/guess-language/subprocess/empty_null", 
test_guess_language_empty_null);
        g_test_add_func ("/LanguageManager/guess-language/subprocess/null_empty", 
test_guess_language_null_empty);
        g_test_add_func ("/LanguageManager/guess-language/subprocess/empty_empty", 
test_guess_language_empty_empty);
+       g_test_add_func ("/LanguageManager/resources", test_resources);
 
        return g_test_run();
 }
diff --git a/testsuite/testsuite.gresource.xml b/testsuite/testsuite.gresource.xml
new file mode 100644
index 00000000..831cfda9
--- /dev/null
+++ b/testsuite/testsuite.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/language-specs">
+    <file>testsuite.lang</file>
+  </gresource>
+</gresources>
diff --git a/testsuite/testsuite.lang b/testsuite/testsuite.lang
new file mode 100644
index 00000000..f91c01ad
--- /dev/null
+++ b/testsuite/testsuite.lang
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ This file is part of GtkSourceView
+
+ GtkSourceView is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ GtkSourceView 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<language id="testsuite" name="testsuite" version="2.0" _section="Other">
+  <styles>
+    <style id="escaped-character" name="Escaped character"     map-to="def:special-char"/>
+    <style id="string"            name="String"                map-to="def:string"/>
+  </styles>
+  <definitions>
+    <context id="string" style-ref="string" class="string" class-disabled="no-spell-check">
+      <start>"</start>
+      <end>"</end>
+      <include>
+        <context id="escaped-character" style-ref="escaped-character">
+          <match extended="true">
+            \"\"
+          </match>
+        </context>
+      </include>
+    </context>
+    <context id="testsuite" class="no-spell-check">
+      <include>
+        <context ref="string"/>
+      </include>
+    </context>
+  </definitions>
+</language>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]