unofficial mirror of guix-devel@gnu.org 
 help / color / mirror / code / Atom feed
* tree-sitter grammars for emacs memo
@ 2022-12-04 16:04 Murad Mamedov
  2023-01-26 17:18 ` Simon Tournier
  0 siblings, 1 reply; 2+ messages in thread
From: Murad Mamedov @ 2022-12-04 16:04 UTC (permalink / raw)
  To: Guix-devel

[-- Attachment #1: Type: text/plain, Size: 957 bytes --]


Hi,

Today I spent some time on trying latest emacs with
--with-tree-siter enabled. It enables native support
for tree-sitter. However, language grammars are still
external. I came up with below snippet that makes
grammar packages. But I didn't find it worth committing.
So sharing it here if someone will want to try,
or may be form it to commit.

Current issues related to guix with tree-sitter below:

- Emacs tries to dlopen libraries with grammars.
  Since we are under guix, one has to add grammar
  packages to profile and use treesit-extra-load-path
  variable. In the long run, this will require different
  solution, probably patching emacs it self, idk.

--8<---------------cut here---------------start------------->8---
(use-package treesit
  :demand t
  :init
  (setq treesit-extra-load-path
        '("/home/muradm/.cache/guix-extra-profiles/desktop/lib")))
--8<---------------cut here---------------end--------------->8---

Regards,
muradm


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: emacs-tree-sitter-module.patch --]
[-- Type: text/x-patch, Size: 28539 bytes --]

From c8a8db2d46b5320185aaa5ba4ec9d7e8764af592 Mon Sep 17 00:00:00 2001
From: muradm <mail@muradm.net>
Date: Sun, 4 Dec 2022 13:22:07 +0300
Subject: [PATCH] tree-sitter-module

---
 src/emacs-module.h      | 763 ++++++++++++++++++++++++++++++++++++++++
 src/tree-sitter-lang.in |  79 +++++
 2 files changed, 842 insertions(+)
 create mode 100644 src/emacs-module.h
 create mode 100644 src/tree-sitter-lang.in

diff --git a/src/emacs-module.h b/src/emacs-module.h
new file mode 100644
index 0000000..1185c06
--- /dev/null
+++ b/src/emacs-module.h
@@ -0,0 +1,763 @@
+/* emacs-module.h - GNU Emacs module API.
+
+Copyright (C) 2015-2021 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs 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 3 of the License, or (at
+your option) any later version.
+
+GNU Emacs 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 GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/*
+This file defines the Emacs module API.  Please see the chapter
+`Dynamic Modules' in the GNU Emacs Lisp Reference Manual for
+information how to write modules and use this header file.
+*/
+
+#ifndef EMACS_MODULE_H
+#define EMACS_MODULE_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <time.h>
+
+#ifndef __cplusplus
+#include <stdbool.h>
+#endif
+
+#define EMACS_MAJOR_VERSION 28
+
+#if defined __cplusplus && __cplusplus >= 201103L
+# define EMACS_NOEXCEPT noexcept
+#else
+# define EMACS_NOEXCEPT
+#endif
+
+#if defined __cplusplus && __cplusplus >= 201703L
+# define EMACS_NOEXCEPT_TYPEDEF noexcept
+#else
+# define EMACS_NOEXCEPT_TYPEDEF
+#endif
+
+#if 3 < __GNUC__ + (3 <= __GNUC_MINOR__)
+# define EMACS_ATTRIBUTE_NONNULL(...) \
+   __attribute__ ((__nonnull__ (__VA_ARGS__)))
+#elif (defined __has_attribute \
+       && (!defined __clang_minor__ \
+	   || 3 < __clang_major__ + (5 <= __clang_minor__)))
+# if __has_attribute (__nonnull__)
+#  define EMACS_ATTRIBUTE_NONNULL(...) \
+    __attribute__ ((__nonnull__ (__VA_ARGS__)))
+# endif
+#endif
+#ifndef EMACS_ATTRIBUTE_NONNULL
+# define EMACS_ATTRIBUTE_NONNULL(...)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Current environment.  */
+typedef struct emacs_env_28 emacs_env;
+
+/* Opaque pointer representing an Emacs Lisp value.
+   BEWARE: Do not assume NULL is a valid value!  */
+typedef struct emacs_value_tag *emacs_value;
+
+enum { emacs_variadic_function = -2 };
+
+/* Struct passed to a module init function (emacs_module_init).  */
+struct emacs_runtime
+{
+  /* Structure size (for version checking).  */
+  ptrdiff_t size;
+
+  /* Private data; users should not touch this.  */
+  struct emacs_runtime_private *private_members;
+
+  /* Return an environment pointer.  */
+  emacs_env *(*get_environment) (struct emacs_runtime *runtime)
+    EMACS_ATTRIBUTE_NONNULL (1);
+};
+
+/* Type aliases for function pointer types used in the module API.
+   Note that we don't use these aliases directly in the API to be able
+   to mark the function arguments as 'noexcept' before C++20.
+   However, users can use them if they want.  */
+
+/* Function prototype for the module Lisp functions.  These must not
+   throw C++ exceptions.  */
+typedef emacs_value (*emacs_function) (emacs_env *env, ptrdiff_t nargs,
+                                       emacs_value *args,
+                                       void *data)
+  EMACS_NOEXCEPT_TYPEDEF EMACS_ATTRIBUTE_NONNULL (1);
+
+/* Function prototype for module user-pointer and function finalizers.
+   These must not throw C++ exceptions.  */
+typedef void (*emacs_finalizer) (void *data) EMACS_NOEXCEPT_TYPEDEF;
+
+/* Possible Emacs function call outcomes.  */
+enum emacs_funcall_exit
+{
+  /* Function has returned normally.  */
+  emacs_funcall_exit_return = 0,
+
+  /* Function has signaled an error using `signal'.  */
+  emacs_funcall_exit_signal = 1,
+
+  /* Function has exit using `throw'.  */
+  emacs_funcall_exit_throw = 2
+};
+
+/* Possible return values for emacs_env.process_input.  */
+enum emacs_process_input_result
+{
+  /* Module code may continue  */
+  emacs_process_input_continue = 0,
+
+  /* Module code should return control to Emacs as soon as possible.  */
+  emacs_process_input_quit = 1
+};
+
+/* Define emacs_limb_t so that it is likely to match GMP's mp_limb_t.
+   This micro-optimization can help modules that use mpz_export and
+   mpz_import, which operate more efficiently on mp_limb_t.  It's OK
+   (if perhaps a bit slower) if the two types do not match, and
+   modules shouldn't rely on the two types matching.  */
+typedef size_t emacs_limb_t;
+#define EMACS_LIMB_MAX SIZE_MAX
+
+struct emacs_env_25
+{
+  /* Structure size (for version checking).  */
+  ptrdiff_t size;
+
+  /* Private data; users should not touch this.  */
+  struct emacs_env_private *private_members;
+
+  /* Memory management.  */
+
+  emacs_value (*make_global_ref) (emacs_env *env, emacs_value value)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*free_global_ref) (emacs_env *env, emacs_value global_value)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Non-local exit handling.  */
+
+  enum emacs_funcall_exit (*non_local_exit_check) (emacs_env *env)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*non_local_exit_clear) (emacs_env *env)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  enum emacs_funcall_exit (*non_local_exit_get)
+    (emacs_env *env, emacs_value *symbol, emacs_value *data)
+    EMACS_ATTRIBUTE_NONNULL(1, 2, 3);
+
+  void (*non_local_exit_signal) (emacs_env *env,
+				 emacs_value symbol, emacs_value data)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*non_local_exit_throw) (emacs_env *env,
+				emacs_value tag, emacs_value value)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Function registration.  */
+
+  emacs_value (*make_function) (emacs_env *env,
+				ptrdiff_t min_arity,
+				ptrdiff_t max_arity,
+				emacs_value (*func) (emacs_env *env,
+                                                     ptrdiff_t nargs,
+                                                     emacs_value* args,
+                                                     void *data)
+				  EMACS_NOEXCEPT
+                                  EMACS_ATTRIBUTE_NONNULL(1),
+				const char *docstring,
+				void *data)
+    EMACS_ATTRIBUTE_NONNULL(1, 4);
+
+  emacs_value (*funcall) (emacs_env *env,
+                          emacs_value func,
+                          ptrdiff_t nargs,
+                          emacs_value* args)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  emacs_value (*intern) (emacs_env *env, const char *name)
+    EMACS_ATTRIBUTE_NONNULL(1, 2);
+
+  /* Type conversion.  */
+
+  emacs_value (*type_of) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  bool (*is_not_nil) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  bool (*eq) (emacs_env *env, emacs_value a, emacs_value b)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  intmax_t (*extract_integer) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  emacs_value (*make_integer) (emacs_env *env, intmax_t n)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  double (*extract_float) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  emacs_value (*make_float) (emacs_env *env, double d)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Copy the content of the Lisp string VALUE to BUFFER as an utf8
+     null-terminated string.
+
+     SIZE must point to the total size of the buffer.  If BUFFER is
+     NULL or if SIZE is not big enough, write the required buffer size
+     to SIZE and return true.
+
+     Note that SIZE must include the last null byte (e.g. "abc" needs
+     a buffer of size 4).
+
+     Return true if the string was successfully copied.  */
+
+  bool (*copy_string_contents) (emacs_env *env,
+                                emacs_value value,
+                                char *buf,
+                                ptrdiff_t *len)
+    EMACS_ATTRIBUTE_NONNULL(1, 4);
+
+  /* Create a Lisp string from a utf8 encoded string.  */
+  emacs_value (*make_string) (emacs_env *env,
+			      const char *str, ptrdiff_t len)
+    EMACS_ATTRIBUTE_NONNULL(1, 2);
+
+  /* Embedded pointer type.  */
+  emacs_value (*make_user_ptr) (emacs_env *env,
+				void (*fin) (void *) EMACS_NOEXCEPT,
+				void *ptr)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void *(*get_user_ptr) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+  void (*set_user_ptr) (emacs_env *env, emacs_value arg, void *ptr)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*(*get_user_finalizer) (emacs_env *env, emacs_value uptr))
+    (void *) EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL(1);
+  void (*set_user_finalizer) (emacs_env *env, emacs_value arg,
+			      void (*fin) (void *) EMACS_NOEXCEPT)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Vector functions.  */
+  emacs_value (*vec_get) (emacs_env *env, emacs_value vector, ptrdiff_t index)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*vec_set) (emacs_env *env, emacs_value vector, ptrdiff_t index,
+		   emacs_value value)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  ptrdiff_t (*vec_size) (emacs_env *env, emacs_value vector)
+    EMACS_ATTRIBUTE_NONNULL(1);
+};
+
+struct emacs_env_26
+{
+  /* Structure size (for version checking).  */
+  ptrdiff_t size;
+
+  /* Private data; users should not touch this.  */
+  struct emacs_env_private *private_members;
+
+  /* Memory management.  */
+
+  emacs_value (*make_global_ref) (emacs_env *env, emacs_value value)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*free_global_ref) (emacs_env *env, emacs_value global_value)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Non-local exit handling.  */
+
+  enum emacs_funcall_exit (*non_local_exit_check) (emacs_env *env)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*non_local_exit_clear) (emacs_env *env)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  enum emacs_funcall_exit (*non_local_exit_get)
+    (emacs_env *env, emacs_value *symbol, emacs_value *data)
+    EMACS_ATTRIBUTE_NONNULL(1, 2, 3);
+
+  void (*non_local_exit_signal) (emacs_env *env,
+				 emacs_value symbol, emacs_value data)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*non_local_exit_throw) (emacs_env *env,
+				emacs_value tag, emacs_value value)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Function registration.  */
+
+  emacs_value (*make_function) (emacs_env *env,
+				ptrdiff_t min_arity,
+				ptrdiff_t max_arity,
+				emacs_value (*func) (emacs_env *env,
+                                                     ptrdiff_t nargs,
+                                                     emacs_value* args,
+                                                     void *data)
+				  EMACS_NOEXCEPT
+                                  EMACS_ATTRIBUTE_NONNULL(1),
+				const char *docstring,
+				void *data)
+    EMACS_ATTRIBUTE_NONNULL(1, 4);
+
+  emacs_value (*funcall) (emacs_env *env,
+                          emacs_value func,
+                          ptrdiff_t nargs,
+                          emacs_value* args)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  emacs_value (*intern) (emacs_env *env, const char *name)
+    EMACS_ATTRIBUTE_NONNULL(1, 2);
+
+  /* Type conversion.  */
+
+  emacs_value (*type_of) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  bool (*is_not_nil) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  bool (*eq) (emacs_env *env, emacs_value a, emacs_value b)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  intmax_t (*extract_integer) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  emacs_value (*make_integer) (emacs_env *env, intmax_t n)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  double (*extract_float) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  emacs_value (*make_float) (emacs_env *env, double d)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Copy the content of the Lisp string VALUE to BUFFER as an utf8
+     null-terminated string.
+
+     SIZE must point to the total size of the buffer.  If BUFFER is
+     NULL or if SIZE is not big enough, write the required buffer size
+     to SIZE and return true.
+
+     Note that SIZE must include the last null byte (e.g. "abc" needs
+     a buffer of size 4).
+
+     Return true if the string was successfully copied.  */
+
+  bool (*copy_string_contents) (emacs_env *env,
+                                emacs_value value,
+                                char *buf,
+                                ptrdiff_t *len)
+    EMACS_ATTRIBUTE_NONNULL(1, 4);
+
+  /* Create a Lisp string from a utf8 encoded string.  */
+  emacs_value (*make_string) (emacs_env *env,
+			      const char *str, ptrdiff_t len)
+    EMACS_ATTRIBUTE_NONNULL(1, 2);
+
+  /* Embedded pointer type.  */
+  emacs_value (*make_user_ptr) (emacs_env *env,
+				void (*fin) (void *) EMACS_NOEXCEPT,
+				void *ptr)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void *(*get_user_ptr) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+  void (*set_user_ptr) (emacs_env *env, emacs_value arg, void *ptr)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*(*get_user_finalizer) (emacs_env *env, emacs_value uptr))
+    (void *) EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL(1);
+  void (*set_user_finalizer) (emacs_env *env, emacs_value arg,
+			      void (*fin) (void *) EMACS_NOEXCEPT)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Vector functions.  */
+  emacs_value (*vec_get) (emacs_env *env, emacs_value vector, ptrdiff_t index)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*vec_set) (emacs_env *env, emacs_value vector, ptrdiff_t index,
+		   emacs_value value)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  ptrdiff_t (*vec_size) (emacs_env *env, emacs_value vector)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Returns whether a quit is pending.  */
+  bool (*should_quit) (emacs_env *env)
+    EMACS_ATTRIBUTE_NONNULL(1);
+};
+
+struct emacs_env_27
+{
+  /* Structure size (for version checking).  */
+  ptrdiff_t size;
+
+  /* Private data; users should not touch this.  */
+  struct emacs_env_private *private_members;
+
+  /* Memory management.  */
+
+  emacs_value (*make_global_ref) (emacs_env *env, emacs_value value)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*free_global_ref) (emacs_env *env, emacs_value global_value)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Non-local exit handling.  */
+
+  enum emacs_funcall_exit (*non_local_exit_check) (emacs_env *env)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*non_local_exit_clear) (emacs_env *env)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  enum emacs_funcall_exit (*non_local_exit_get)
+    (emacs_env *env, emacs_value *symbol, emacs_value *data)
+    EMACS_ATTRIBUTE_NONNULL(1, 2, 3);
+
+  void (*non_local_exit_signal) (emacs_env *env,
+				 emacs_value symbol, emacs_value data)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*non_local_exit_throw) (emacs_env *env,
+				emacs_value tag, emacs_value value)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Function registration.  */
+
+  emacs_value (*make_function) (emacs_env *env,
+				ptrdiff_t min_arity,
+				ptrdiff_t max_arity,
+				emacs_value (*func) (emacs_env *env,
+                                                     ptrdiff_t nargs,
+                                                     emacs_value* args,
+                                                     void *data)
+				  EMACS_NOEXCEPT
+                                  EMACS_ATTRIBUTE_NONNULL(1),
+				const char *docstring,
+				void *data)
+    EMACS_ATTRIBUTE_NONNULL(1, 4);
+
+  emacs_value (*funcall) (emacs_env *env,
+                          emacs_value func,
+                          ptrdiff_t nargs,
+                          emacs_value* args)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  emacs_value (*intern) (emacs_env *env, const char *name)
+    EMACS_ATTRIBUTE_NONNULL(1, 2);
+
+  /* Type conversion.  */
+
+  emacs_value (*type_of) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  bool (*is_not_nil) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  bool (*eq) (emacs_env *env, emacs_value a, emacs_value b)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  intmax_t (*extract_integer) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  emacs_value (*make_integer) (emacs_env *env, intmax_t n)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  double (*extract_float) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  emacs_value (*make_float) (emacs_env *env, double d)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Copy the content of the Lisp string VALUE to BUFFER as an utf8
+     null-terminated string.
+
+     SIZE must point to the total size of the buffer.  If BUFFER is
+     NULL or if SIZE is not big enough, write the required buffer size
+     to SIZE and return true.
+
+     Note that SIZE must include the last null byte (e.g. "abc" needs
+     a buffer of size 4).
+
+     Return true if the string was successfully copied.  */
+
+  bool (*copy_string_contents) (emacs_env *env,
+                                emacs_value value,
+                                char *buf,
+                                ptrdiff_t *len)
+    EMACS_ATTRIBUTE_NONNULL(1, 4);
+
+  /* Create a Lisp string from a utf8 encoded string.  */
+  emacs_value (*make_string) (emacs_env *env,
+			      const char *str, ptrdiff_t len)
+    EMACS_ATTRIBUTE_NONNULL(1, 2);
+
+  /* Embedded pointer type.  */
+  emacs_value (*make_user_ptr) (emacs_env *env,
+				void (*fin) (void *) EMACS_NOEXCEPT,
+				void *ptr)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void *(*get_user_ptr) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+  void (*set_user_ptr) (emacs_env *env, emacs_value arg, void *ptr)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*(*get_user_finalizer) (emacs_env *env, emacs_value uptr))
+    (void *) EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL(1);
+  void (*set_user_finalizer) (emacs_env *env, emacs_value arg,
+			      void (*fin) (void *) EMACS_NOEXCEPT)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Vector functions.  */
+  emacs_value (*vec_get) (emacs_env *env, emacs_value vector, ptrdiff_t index)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*vec_set) (emacs_env *env, emacs_value vector, ptrdiff_t index,
+		   emacs_value value)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  ptrdiff_t (*vec_size) (emacs_env *env, emacs_value vector)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Returns whether a quit is pending.  */
+  bool (*should_quit) (emacs_env *env)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Processes pending input events and returns whether the module
+     function should quit.  */
+  enum emacs_process_input_result (*process_input) (emacs_env *env)
+    EMACS_ATTRIBUTE_NONNULL (1);
+
+  struct timespec (*extract_time) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL (1);
+
+  emacs_value (*make_time) (emacs_env *env, struct timespec time)
+    EMACS_ATTRIBUTE_NONNULL (1);
+
+  bool (*extract_big_integer) (emacs_env *env, emacs_value arg, int *sign,
+                               ptrdiff_t *count, emacs_limb_t *magnitude)
+    EMACS_ATTRIBUTE_NONNULL (1);
+
+  emacs_value (*make_big_integer) (emacs_env *env, int sign, ptrdiff_t count,
+                                   const emacs_limb_t *magnitude)
+    EMACS_ATTRIBUTE_NONNULL (1);
+};
+
+struct emacs_env_28
+{
+  /* Structure size (for version checking).  */
+  ptrdiff_t size;
+
+  /* Private data; users should not touch this.  */
+  struct emacs_env_private *private_members;
+
+  /* Memory management.  */
+
+  emacs_value (*make_global_ref) (emacs_env *env, emacs_value value)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*free_global_ref) (emacs_env *env, emacs_value global_value)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Non-local exit handling.  */
+
+  enum emacs_funcall_exit (*non_local_exit_check) (emacs_env *env)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*non_local_exit_clear) (emacs_env *env)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  enum emacs_funcall_exit (*non_local_exit_get)
+    (emacs_env *env, emacs_value *symbol, emacs_value *data)
+    EMACS_ATTRIBUTE_NONNULL(1, 2, 3);
+
+  void (*non_local_exit_signal) (emacs_env *env,
+				 emacs_value symbol, emacs_value data)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*non_local_exit_throw) (emacs_env *env,
+				emacs_value tag, emacs_value value)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Function registration.  */
+
+  emacs_value (*make_function) (emacs_env *env,
+				ptrdiff_t min_arity,
+				ptrdiff_t max_arity,
+				emacs_value (*func) (emacs_env *env,
+                                                     ptrdiff_t nargs,
+                                                     emacs_value* args,
+                                                     void *data)
+				  EMACS_NOEXCEPT
+                                  EMACS_ATTRIBUTE_NONNULL(1),
+				const char *docstring,
+				void *data)
+    EMACS_ATTRIBUTE_NONNULL(1, 4);
+
+  emacs_value (*funcall) (emacs_env *env,
+                          emacs_value func,
+                          ptrdiff_t nargs,
+                          emacs_value* args)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  emacs_value (*intern) (emacs_env *env, const char *name)
+    EMACS_ATTRIBUTE_NONNULL(1, 2);
+
+  /* Type conversion.  */
+
+  emacs_value (*type_of) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  bool (*is_not_nil) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  bool (*eq) (emacs_env *env, emacs_value a, emacs_value b)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  intmax_t (*extract_integer) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  emacs_value (*make_integer) (emacs_env *env, intmax_t n)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  double (*extract_float) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  emacs_value (*make_float) (emacs_env *env, double d)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Copy the content of the Lisp string VALUE to BUFFER as an utf8
+     null-terminated string.
+
+     SIZE must point to the total size of the buffer.  If BUFFER is
+     NULL or if SIZE is not big enough, write the required buffer size
+     to SIZE and return true.
+
+     Note that SIZE must include the last null byte (e.g. "abc" needs
+     a buffer of size 4).
+
+     Return true if the string was successfully copied.  */
+
+  bool (*copy_string_contents) (emacs_env *env,
+                                emacs_value value,
+                                char *buf,
+                                ptrdiff_t *len)
+    EMACS_ATTRIBUTE_NONNULL(1, 4);
+
+  /* Create a Lisp string from a utf8 encoded string.  */
+  emacs_value (*make_string) (emacs_env *env,
+			      const char *str, ptrdiff_t len)
+    EMACS_ATTRIBUTE_NONNULL(1, 2);
+
+  /* Embedded pointer type.  */
+  emacs_value (*make_user_ptr) (emacs_env *env,
+				void (*fin) (void *) EMACS_NOEXCEPT,
+				void *ptr)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void *(*get_user_ptr) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL(1);
+  void (*set_user_ptr) (emacs_env *env, emacs_value arg, void *ptr)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*(*get_user_finalizer) (emacs_env *env, emacs_value uptr))
+    (void *) EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL(1);
+  void (*set_user_finalizer) (emacs_env *env, emacs_value arg,
+			      void (*fin) (void *) EMACS_NOEXCEPT)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Vector functions.  */
+  emacs_value (*vec_get) (emacs_env *env, emacs_value vector, ptrdiff_t index)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  void (*vec_set) (emacs_env *env, emacs_value vector, ptrdiff_t index,
+		   emacs_value value)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  ptrdiff_t (*vec_size) (emacs_env *env, emacs_value vector)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Returns whether a quit is pending.  */
+  bool (*should_quit) (emacs_env *env)
+    EMACS_ATTRIBUTE_NONNULL(1);
+
+  /* Processes pending input events and returns whether the module
+     function should quit.  */
+  enum emacs_process_input_result (*process_input) (emacs_env *env)
+    EMACS_ATTRIBUTE_NONNULL (1);
+
+  struct timespec (*extract_time) (emacs_env *env, emacs_value arg)
+    EMACS_ATTRIBUTE_NONNULL (1);
+
+  emacs_value (*make_time) (emacs_env *env, struct timespec time)
+    EMACS_ATTRIBUTE_NONNULL (1);
+
+  bool (*extract_big_integer) (emacs_env *env, emacs_value arg, int *sign,
+                               ptrdiff_t *count, emacs_limb_t *magnitude)
+    EMACS_ATTRIBUTE_NONNULL (1);
+
+  emacs_value (*make_big_integer) (emacs_env *env, int sign, ptrdiff_t count,
+                                   const emacs_limb_t *magnitude)
+    EMACS_ATTRIBUTE_NONNULL (1);
+
+  /* Add module environment functions newly added in Emacs 28 here.
+     Before Emacs 28 is released, remove this comment and start
+     module-env-29.h on the master branch.  */
+
+  void (*(*EMACS_ATTRIBUTE_NONNULL (1)
+            get_function_finalizer) (emacs_env *env,
+                                     emacs_value arg)) (void *) EMACS_NOEXCEPT;
+
+  void (*set_function_finalizer) (emacs_env *env, emacs_value arg,
+                                  void (*fin) (void *) EMACS_NOEXCEPT)
+    EMACS_ATTRIBUTE_NONNULL (1);
+
+  int (*open_channel) (emacs_env *env, emacs_value pipe_process)
+    EMACS_ATTRIBUTE_NONNULL (1);
+
+  void (*make_interactive) (emacs_env *env, emacs_value function,
+                            emacs_value spec)
+    EMACS_ATTRIBUTE_NONNULL (1);
+
+  /* Create a unibyte Lisp string from a string.  */
+  emacs_value (*make_unibyte_string) (emacs_env *env,
+				      const char *str, ptrdiff_t len)
+    EMACS_ATTRIBUTE_NONNULL(1, 2);
+};
+
+/* Every module should define a function as follows.  */
+extern int emacs_module_init (struct emacs_runtime *runtime)
+  EMACS_NOEXCEPT
+  EMACS_ATTRIBUTE_NONNULL (1);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EMACS_MODULE_H */
diff --git a/src/tree-sitter-lang.in b/src/tree-sitter-lang.in
new file mode 100644
index 0000000..4d27421
--- /dev/null
+++ b/src/tree-sitter-lang.in
@@ -0,0 +1,79 @@
+#include <string.h>
+#include <tree_sitter/parser.h>
+#include "emacs-module.h"
+
+int plugin_is_GPL_compatible;
+
+extern TSLanguage *tree_sitter_LANG_C(void);
+
+/* REF: http://diobla.info/blog-archive/modules-tut.html  */
+
+/* Return a USER_PTR to the language definition.  */
+static emacs_value
+Ftree_sitter_language
+(emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data)
+{
+  TSLanguage *language = tree_sitter_LANG_C();
+  return env->make_user_ptr (env, NULL, language);
+}
+
+/* Use this command to "dump" the file:
+   xxd -i < grammar.js > parser.c.dump
+ */
+static emacs_value
+Ftree_sitter_grammar
+(emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data)
+{
+  char grammar[] = {
+#include "grammar.js.dump"
+    , '\0' };
+  return env->make_string (env, grammar, strlen(grammar));
+}
+
+/* Bind NAME to FUN.  */
+static void
+bind_function (emacs_env *env, const char *name, emacs_value Sfun)
+{
+  /* Set the function cell of the symbol named NAME to SFUN using
+     the 'fset' function.  */
+
+  /* Convert the strings to symbols by interning them.  */
+  emacs_value Qfset = env->intern (env, "fset");
+  emacs_value Qsym = env->intern (env, name);
+
+  emacs_value args[] = { Qsym, Sfun };
+  env->funcall (env, Qfset, 2, args);
+}
+
+/* Provide FEATURE to Emacs.  */
+static void
+provide (emacs_env *env, const char *feature)
+{
+  /* Call 'provide' with FEATURE converted to a symbol.  */
+  emacs_value Qfeat = env->intern (env, feature);
+  emacs_value Qprovide = env->intern (env, "provide");
+  emacs_value args[] = { Qfeat };
+
+  env->funcall (env, Qprovide, 1, args);
+}
+
+int
+emacs_module_init (struct emacs_runtime *ert)
+{
+  emacs_env *env = ert->get_environment (ert);
+
+  emacs_value lang = env->make_function
+    (env, 0, 0, &Ftree_sitter_language,
+     "Return a language object.", NULL);
+
+    emacs_value grammar = env->make_function
+      (env, 0, 0, &Ftree_sitter_grammar,
+       "Return a language definition.", NULL);
+
+  bind_function (env, "tree-sitter-LANG", lang);
+  bind_function (env, "tree-sitter-LANG-grammar", grammar);
+  provide (env, "tree-sitter-LANG");
+
+  /* Return 0 to indicate module loaded successfully.  */
+  return 0;
+}
-- 
2.38.1


[-- Attachment #3: Type: text/plain, Size: 7775 bytes --]


--8<---------------cut here---------------start------------->8---

(define (emacs-tree-sitter-grammar org lang version commit hash 
synopsis)
  (let ((name
         (string-append "emacs-tree-sitter-grammar-" lang))
        (home-page
         (string-append "https://github.com/" org "/tree-sitter-" 
         lang))
        (src-dir (if (equal? "typescript" lang) "tsx/" ""))
        (lib (format #f "libtree-sitter-~a.so"
                     (if (equal? "typescript" lang) "tsx" lang))))
    (package
      (name name)
      (version version)
      (home-page home-page)
      (source (origin
                (method git-fetch)
                (uri (git-reference
                      (url home-page)
                      (commit commit)))
                (file-name (git-file-name name version))
                ;; Patch includes two files necessary to build 
                each grammar
                ;; in emacs-with-tree-sitter loadable way. Files 
                are
                ;; emacs-module.h and tree-sitter-lang.in, 
                originated
                ;; from 
                https://github.com/casouri/tree-sitter-module.
                (patches (list (local-file 
                "emacs-tree-sitter-module.patch")))
                (modules '((guix build utils)))
                (snippet
                 #~(begin
                     (copy-file (string-append #$src-dir 
                     "grammar.js")
                                (string-append #$src-dir 
                                "src/grammar.js"))
                     (for-each
                      (lambda (f) (rename-file f (string-append 
                      #$src-dir f)))
                      '("src/emacs-module.h" 
                      "src/tree-sitter-lang.in"))))
                (sha256 (base32 hash))))
      (build-system gnu-build-system)
      (arguments
       (list
        ;; Phases below and snippet above mimics actions from:
        ;; 
        https://github.com/casouri/tree-sitter-module/blob/master/build.sh
        #:phases
        #~(modify-phases %standard-phases
            (delete 'configure)
            (replace 'build
              (lambda _
                (with-directory-excursion (string-append #$src-dir 
                "src")
                  (let* ((scanner? (or (file-exists? "scanner.c")
                                       (file-exists? 
                                       "scanner.cc")))
                         (CC (if (file-exists? "scanner.cc") "g++" 
                         "gcc"))
                         (compile (lambda (f) (invoke CC "-fPIC" 
                         "-c" "-I." f)))
                         (link-args `("-fPIC" "-shared" "parser.o"
                                      ,@(if scanner? 
                                      '("scanner.o") '())
                                      "-o" ,#$lib)))
                    (invoke "gcc" "-fPIC" "-c" "-I." "parser.c")
                    (for-each
                     (lambda (f) (when (file-exists? f) (compile 
                     f)))
                     '("scanner.c" "scanner.cc"))
                    (apply invoke CC link-args)))))
            (delete 'check)
            (replace 'install
              (lambda _
                (install-file (string-append #$src-dir "src/" 
                #$lib)
                              (string-append #$output 
                              "/lib")))))))
      (synopsis synopsis)
      (description (string-append synopsis "."))
      (license license:expat))))

(define-public emacs-tree-sitter-grammar-bash
  (emacs-tree-sitter-grammar
   "tree-sitter" "bash" "0.19.0" "v0.19.0"
   "18c030bb65r50i6z37iy7jb9z9i8i36y7b08dbc9bchdifqsijs5"
   "Bash grammar for tree-sitter in Emacs"))

(define-public emacs-tree-sitter-grammar-c
  (emacs-tree-sitter-grammar
   "tree-sitter" "c" "0.20.2" "v0.20.2"
   "1w03r4l773ki4iq2xxsc2pqxf3pjsbybq3xq4glmnsihgylibn8v"
   "C grammar for tree-sitter in Emacs"))

(define-public emacs-tree-sitter-grammar-cpp
  (emacs-tree-sitter-grammar
   "tree-sitter" "cpp" "0.20.0" "v0.20.0"
   "0hxcpdvyyig8njga1mxp4qcnbbnr1d0aiy27vahijwbh98b081nr"
   "C++ grammar for tree-sitter in Emacs"))

(define-public emacs-tree-sitter-grammar-css
  (emacs-tree-sitter-grammar
   "tree-sitter" "css" "0.19.0" "v0.19.0"
   "014jrlgi7zfza9g38hsr4vlbi8964i5p7iglaih6qmzaiml7bja2"
   "CSS grammar for tree-sitter in Emacs"))

(define-public emacs-tree-sitter-grammar-c-sharp
  (emacs-tree-sitter-grammar
   "tree-sitter" "c-sharp" "0.20.0" "v0.20.0"
   "0lijbi5q49g50ji00p2lb45rvd76h07sif3xjl9b31yyxwillr6l"
   "C# grammar for tree-sitter in Emacs"))

(define-public emacs-tree-sitter-grammar-elixir
  (emacs-tree-sitter-grammar
   "elixir-lang" "elixir" "0.0.1" 
   "0ba537df8692179f34cccc7efed05de6cf5178aa"
   "1k35nfwnz8zjiw2mg8d6nphxp3gb7yhb0a5vw4cz2h3n10yyq75i"
   "Elixir grammar for tree-sitter in Emacs"))

(define-public emacs-tree-sitter-grammar-go
  (emacs-tree-sitter-grammar
   "tree-sitter" "go" "0.19.1" "rust-0.19.1"
   "0nxs47vd2fc2fr0qlxq496y852rwg39flhg334s7dlyq7d3lcx4x"
   "Go grammar for tree-sitter in Emacs"))

(define-public emacs-tree-sitter-grammar-html
  (emacs-tree-sitter-grammar
   "tree-sitter" "html" "0.19.0" "v0.19.0"
   "1hg7vbcy7bir6b8x11v0a4x0glvqnsqc3i2ixiarbxmycbgl3axy"
   "HTML grammar for tree-sitter in Emacs"))

(define-public emacs-tree-sitter-grammar-java
  (emacs-tree-sitter-grammar
   "tree-sitter" "java" "0.20.0" "v0.20.0"
   "1i9zfgqibinz3rkx6yws1wk49iys32x901dki65qihbxcmcfh341"
   "Java grammar for tree-sitter in Emacs"))

(define-public emacs-tree-sitter-grammar-javascript
  (emacs-tree-sitter-grammar
   "tree-sitter" "javascript" "0.20.0" "rust-0.20.0"
   "175yrk382n2di0c2xn4gpv8y4n83x1lg4hqn04vabf0yqynlkq67"
   "JavaScript grammar for tree-sitter in Emacs"))

(define-public emacs-tree-sitter-grammar-json
  (emacs-tree-sitter-grammar
   "tree-sitter" "json" "0.19.0" "v0.19.0"
   "06pjh31bv9ja9hlnykk257a6zh8bsxg2fqa54al7qk1r4n9ksnff"
   "JSON grammar for tree-sitter in Emacs"))

(define-public emacs-tree-sitter-grammar-python
  (emacs-tree-sitter-grammar
   "tree-sitter" "python" "0.20.0" "v0.20.0"
   "14nnnblbjxyri8x21kj59agiy3cn4fwfrab3dmidykdyq2r46f5w"
   "Python grammar for tree-sitter in Emacs"))

(define-public emacs-tree-sitter-grammar-rust
  (emacs-tree-sitter-grammar
   "tree-sitter" "rust" "0.20.3" "v0.20.3"
   "149jhy01mqvavwa8jlxb8bnn7sxpfq2x1w35si6zn60b7kqjlx8f"
   "Rust grammar for tree-sitter in Emacs"))

(define-public emacs-tree-sitter-grammar-typescript
  (emacs-tree-sitter-grammar
   "tree-sitter" "typescript" "0.20.1" "v0.20.1"
   "07fl9d968lal0aqj4f0n16p3n94cjkgfp54wynfr8gbdkjss5v5x"
   "TypeScript/TSX grammar for tree-sitter in Emacs"))

(define-public emacs-next-pgtk-tree-sitter
  (let ((commit "be67cc276a95a97a329fa633fef686ba06c8e6d2")
        (revision "3"))
    (package
      (inherit emacs-next-pgtk)
      (name "emacs-next-pgtk-tree-sitter")
      (version (git-version "29.0.50" revision commit))
      (source
       (origin
         (inherit (package-source emacs-next))
         (method git-fetch)
         (uri (git-reference
               (url "https://git.savannah.gnu.org/git/emacs.git")
               (commit commit)))
         (file-name (git-file-name name version))
         (sha256
          (base32
           "0daczbivmp1v8dzp98pn8d93m9np38avs0xyyvhd48b8ly71daia"))))
      (arguments
       (substitute-keyword-arguments (package-arguments 
       emacs-next-pgtk)
         ((#:configure-flags flags #~'())
          #~(cons* "--with-tree-sitter" #$flags))))
      (inputs
       (modify-inputs
        (package-inputs emacs-next-pgtk)
        (prepend tree-sitter))))))

--8<---------------cut here---------------end--------------->8---

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: tree-sitter grammars for emacs memo
  2022-12-04 16:04 tree-sitter grammars for emacs memo Murad Mamedov
@ 2023-01-26 17:18 ` Simon Tournier
  0 siblings, 0 replies; 2+ messages in thread
From: Simon Tournier @ 2023-01-26 17:18 UTC (permalink / raw)
  To: Murad Mamedov, Guix-devel

Hi,

Thanks for the tricks. :-)

On Sun, 04 Dec 2022 at 19:04, Murad Mamedov <muradm@encom.net> wrote:

>  create mode 100644 src/emacs-module.h
>  create mode 100644 src/tree-sitter-lang.in
>
> diff --git a/src/emacs-module.h b/src/emacs-module.h
> new file mode 100644
> index 0000000..1185c06
> --- /dev/null
> +++ b/src/emacs-module.h

[...]

> diff --git a/src/tree-sitter-lang.in b/src/tree-sitter-lang.in
> new file mode 100644
> index 0000000..4d27421
> --- /dev/null
> +++ b/src/tree-sitter-lang.in

What does Emacs upstream think about this?  Discussion on emacs-devel
about tree-sitter are really lengthy. :-)  Maybe it could be nice if
that fix would be in Emacs proper.  Well, I do not know.


Cheers,
simon


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-01-26 17:39 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-04 16:04 tree-sitter grammars for emacs memo Murad Mamedov
2023-01-26 17:18 ` Simon Tournier

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).