aboutsummaryrefslogtreecommitdiff
path: root/gdb/python
diff options
context:
space:
mode:
authorTom Tromey <tromey@adacore.com>2020-01-03 13:59:27 -0700
committerTom Tromey <tromey@adacore.com>2020-01-21 12:39:17 -0700
commitf6474de9aacec990d44d2d65a337668b389efd99 (patch)
tree4d70c7c91fba9b49b5b0c62baa7759b6e1d5b13e /gdb/python
parentb4654b109bd023d0a22f445db7d4e27f769593f4 (diff)
downloadbinutils-f6474de9aacec990d44d2d65a337668b389efd99.zip
binutils-f6474de9aacec990d44d2d65a337668b389efd99.tar.gz
binutils-f6474de9aacec990d44d2d65a337668b389efd99.tar.bz2
Allow use of Pygments to colorize source code
While GNU Source Highlight is good, it's also difficult to build and distribute. For one thing, it needs Boost. For another, it has an unusual configuration and installation setup. Pygments, a Python library, doesn't suffer from these issues, and so I thought it would be a reasonable fallback. This patch implements this idea. GNU Source Highlight is preferred, but if it is unavailable (or fails), the extension languages are tried. This patch also implements support for Pygments. Something similar could be done for Guile, using: https://dthompson.us/projects/guile-syntax-highlight.html However, I don't know enough about Guile internals to make this happen, so I have not done it here. gdb/ChangeLog 2020-01-21 Tom Tromey <tromey@adacore.com> * source-cache.c (source_cache::ensure): Call ext_lang_colorize. * python/python.c (python_extension_ops): Update. (gdbpy_colorize): New function. * python/lib/gdb/__init__.py (colorize): New function. * extension.h (ext_lang_colorize): Declare. * extension.c (ext_lang_colorize): New function. * extension-priv.h (struct extension_language_ops) <colorize>: New member. * cli/cli-style.c (_initialize_cli_style): Update help text. Change-Id: I5e21623ee05f1f66baaa6deaeca78b578c031bf4
Diffstat (limited to 'gdb/python')
-rw-r--r--gdb/python/lib/gdb/__init__.py14
-rw-r--r--gdb/python/python.c72
2 files changed, 86 insertions, 0 deletions
diff --git a/gdb/python/lib/gdb/__init__.py b/gdb/python/lib/gdb/__init__.py
index 09d43b2..a1aac00 100644
--- a/gdb/python/lib/gdb/__init__.py
+++ b/gdb/python/lib/gdb/__init__.py
@@ -210,3 +210,17 @@ def find_pc_line(pc):
"""find_pc_line (pc) -> Symtab_and_line.
Return the gdb.Symtab_and_line object corresponding to the pc value."""
return current_progspace().find_pc_line(pc)
+
+try:
+ from pygments import formatters, lexers, highlight
+ def colorize(filename, contents):
+ # Don't want any errors.
+ try:
+ lexer = lexers.get_lexer_for_filename(filename)
+ formatter = formatters.TerminalFormatter()
+ return highlight(contents, lexer, formatter)
+ except:
+ return None
+except:
+ def colorize(filename, contents):
+ return None
diff --git a/gdb/python/python.c b/gdb/python/python.c
index d6f7f99..f75c7b1 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -149,6 +149,8 @@ static void gdbpy_set_quit_flag (const struct extension_language_defn *);
static int gdbpy_check_quit_flag (const struct extension_language_defn *);
static enum ext_lang_rc gdbpy_before_prompt_hook
(const struct extension_language_defn *, const char *current_gdb_prompt);
+static gdb::optional<std::string> gdbpy_colorize
+ (const std::string &filename, const std::string &contents);
/* The interface between gdb proper and loading of python scripts. */
@@ -188,6 +190,8 @@ const struct extension_language_ops python_extension_ops =
gdbpy_before_prompt_hook,
gdbpy_get_matching_xmethod_workers,
+
+ gdbpy_colorize,
};
/* Architecture and language to be used in callbacks from
@@ -1104,6 +1108,74 @@ gdbpy_before_prompt_hook (const struct extension_language_defn *extlang,
return EXT_LANG_RC_NOP;
}
+/* This is the extension_language_ops.colorize "method". */
+
+static gdb::optional<std::string>
+gdbpy_colorize (const std::string &filename, const std::string &contents)
+{
+ if (!gdb_python_initialized)
+ return {};
+
+ gdbpy_enter enter_py (get_current_arch (), current_language);
+
+ if (gdb_python_module == nullptr
+ || !PyObject_HasAttrString (gdb_python_module, "colorize"))
+ return {};
+
+ gdbpy_ref<> hook (PyObject_GetAttrString (gdb_python_module, "colorize"));
+ if (hook == nullptr)
+ {
+ gdbpy_print_stack ();
+ return {};
+ }
+
+ if (!PyCallable_Check (hook.get ()))
+ return {};
+
+ gdbpy_ref<> fname_arg (PyString_FromString (filename.c_str ()));
+ if (fname_arg == nullptr)
+ {
+ gdbpy_print_stack ();
+ return {};
+ }
+ gdbpy_ref<> contents_arg (PyString_FromString (contents.c_str ()));
+ if (contents_arg == nullptr)
+ {
+ gdbpy_print_stack ();
+ return {};
+ }
+
+ gdbpy_ref<> result (PyObject_CallFunctionObjArgs (hook.get (),
+ fname_arg.get (),
+ contents_arg.get (),
+ nullptr));
+ if (result == nullptr)
+ {
+ gdbpy_print_stack ();
+ return {};
+ }
+
+ if (!gdbpy_is_string (result.get ()))
+ return {};
+
+ gdbpy_ref<> unic = python_string_to_unicode (result.get ());
+ if (unic == nullptr)
+ {
+ gdbpy_print_stack ();
+ return {};
+ }
+ gdbpy_ref<> host_str (PyUnicode_AsEncodedString (unic.get (),
+ host_charset (),
+ nullptr));
+ if (host_str == nullptr)
+ {
+ gdbpy_print_stack ();
+ return {};
+ }
+
+ return std::string (PyBytes_AsString (host_str.get ()));
+}
+
/* Printing. */