Skip to content

Commit

Permalink
scope: Improved evaluation on-hover
Browse files Browse the repository at this point in the history
Scope automatically evaluates an expression if the mouse pointer is hovered over it.
But before this change it only evaluated words. E.g. if the mouse was hovered over
"structa->item1" then scope would have evaluated "structa" or "item1" depending on
the exact position of the mouse pointer. With this change it will instead evaluate
the value of "structa" if the mouse pointer is over "structa". If the mouse pointer
is over "item1" then the expression "structa->item1" will be evaluated.
  • Loading branch information
lpaulsen93 committed May 8, 2019
1 parent e18cc0c commit 648224a
Show file tree
Hide file tree
Showing 6 changed files with 499 additions and 6 deletions.
14 changes: 14 additions & 0 deletions scope/src/Makefile.am
Expand Up @@ -61,3 +61,17 @@ scope_la_CFLAGS = $(AM_CFLAGS) $(VTE_CFLAGS) \
-I$(top_srcdir)/utils/src

include $(top_srcdir)/build/cppcheck.mk

if UNITTESTS

TESTS = unittests
check_PROGRAMS = unittests

unittests_SOURCES = tests/unittests.c tests/utils_test.c \
$(scope_la_SOURCES)
unittests_CPPFLAGS = -DTEST $(scope_la_CPPFLAGS)
unittests_CFLAGS = $(GEANY_CFLAGS) -DUNITTESTS $(scope_la_CFLAGS)
unittests_LDADD = @GEANY_LIBS@ $(INTLLIBS) @CHECK_LIBS@ \
$(scope_la_LIBADD)

endif
28 changes: 28 additions & 0 deletions scope/src/tests/unittests.c
@@ -0,0 +1,28 @@
#include <stdlib.h>
#include <stdio.h>
#include <check.h>

#include <gtk/gtk.h>
#include "geany.h"

TCase *utils_create_tests(void);

Suite *
my_suite(void)
{
Suite *s = suite_create("Scope");
suite_add_tcase(s, utils_create_tests());
return s;
}

int
main(void)
{
int nf;
Suite *s = my_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
nf = srunner_ntests_failed(sr);
srunner_free(sr);
return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
73 changes: 73 additions & 0 deletions scope/src/tests/utils_test.c
@@ -0,0 +1,73 @@
#include <check.h>
#include "../src/common.h"
#include "../src/utils.h"

typedef struct S_EXPR_TEST_ITEM
{
const gchar *input;
guint peek_index;
const gchar *expected;
}EXPR_TEST_ITEM;

EXPR_TEST_ITEM expr_test_items [] =
{
{ " variable ", sizeof(" var")-1, "variable" },
{ " (variable) ", sizeof(" (var")-1, "variable" },
{ "struct.item", sizeof("str")-1, "struct" },
{ "struct.item", sizeof("str")-1, "struct" },
{ "struct.item", sizeof("struct.it")-1, "struct.item" },
{ "struct->item", sizeof("str")-1, "struct" },
{ "struct->item", sizeof("struct->it")-1, "struct->item" },
{ "&(struct->item)", sizeof("&(str")-1, "struct" },
{ "&(struct->item)", sizeof("&(struct->it")-1, "struct->item" },
{ "foobar(item)", sizeof("foobar(it")-1, "item" },
{ "sizeof(item)", sizeof("sizeof(it")-1, "sizeof(item)" },
{ "array[5]", sizeof("arr")-1, "array" },
{ "array[5]", sizeof("array[")-1, "array[5]" },
{ "*pointer", sizeof("*poi")-1, "pointer" },
{ "*pointer", 0, "*pointer" },
{ "&variable", sizeof("&var")-1, "variable" },
{ "&variable", 0, "&variable" },
{ "foo variable", sizeof("foo var")-1, "variable" },
{ "variable foo", sizeof("var")-1, "variable" },
{ "int var_a, var_b;", sizeof("int var")-1, "var_a" },
{ "int var_a, var_b;", sizeof("int var_a, va")-1, "var_b" },
{ "foo(var_a, var_b);", sizeof("foo(var")-1, "var_a" },
{ "foo(var_a, var_b);", sizeof("foo(var_a, va")-1, "var_b" },
{ "array[index].item", sizeof("array[index].i")-1, "array[index].item" },
{ "array[index]->item", sizeof("array[index]->i")-1, "array[index]->item" },
{ NULL, 0, NULL },
};

START_TEST(test_parser_for_evaluate)
{
EXPR_TEST_ITEM *test_item;
guint index = 0;
gchar *expr, *chunk;

test_item = &(expr_test_items[index]);
while (test_item->input != NULL)
{
chunk = g_strdup(test_item->input);
expr = utils_evaluate_expr_from_string (chunk, test_item->peek_index);
ck_assert_ptr_ne(expr, NULL);
if (g_strcmp0(expr, test_item->expected) != 0)
{
ck_abort_msg("Index #%lu: Input: '%s', Peek-Ind.: %lu, Result: '%s' != '%s' (expected)",
index, test_item->input, test_item->peek_index, expr, test_item->expected);
}
g_free(chunk);
g_free(expr);

index++;
test_item = &(expr_test_items[index]);
}
}
END_TEST;

TCase *utils_create_tests(void)
{
TCase *tc_utils = tcase_create("utils");
tcase_add_test(tc_utils, test_parser_for_evaluate);
return tc_utils;
}
40 changes: 34 additions & 6 deletions scope/src/tooltip.c
Expand Up @@ -22,6 +22,9 @@

#include "common.h"

/* Wordchars defining possible signs in an expression. */
#define SCOPE_EXPR_WORDCHARS "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.->[]"

static void tooltip_trigger(void)
{
GdkDisplay *display = gdk_display_get_default();
Expand All @@ -48,6 +51,7 @@ static void tooltip_trigger(void)
}
}

static gchar *last_expr = NULL;
static gchar *output = NULL;
static gint last_pos = -1;
static gint peek_pos = -1;
Expand All @@ -69,6 +73,24 @@ static void tooltip_set(gchar *text)
}
}

static void tooltip_set_expr(gchar *expr, gchar *text)
{
show = text != NULL;
g_free(output);
output = g_strdup_printf ("%s =\n %s", expr, text);
g_free(text);
g_free(expr);
last_pos = peek_pos;

if (show)
{
if (pref_tooltips_length && strlen(output) > (size_t) pref_tooltips_length + 3)
strcpy(output + pref_tooltips_length, "...");

tooltip_trigger();
}
}

static gint scid_gen = 0;

void on_tooltip_error(GArray *nodes)
Expand All @@ -92,7 +114,7 @@ void on_tooltip_value(GArray *nodes)
{
if (atoi(parse_grab_token(nodes)) == scid_gen)
{
tooltip_set(parse_get_display_from_7bit(parse_lead_value(nodes),
tooltip_set_expr(last_expr, parse_get_display_from_7bit(parse_lead_value(nodes),
parse_mode_get(input, MODE_HBIT), parse_mode_get(input, MODE_MEMBER)));
}
}
Expand All @@ -107,17 +129,23 @@ static gboolean tooltip_launch(gpointer gdata)
(debug_state() & DS_SENDABLE))
{
ScintillaObject *sci = doc->editor->sci;
gchar *expr = sci_get_selection_mode(sci) == SC_SEL_STREAM &&
gchar *expr;
if (sci_get_selection_mode(sci) == SC_SEL_STREAM &&
peek_pos >= sci_get_selection_start(sci) &&
peek_pos < sci_get_selection_end(sci) ?
editor_get_default_selection(doc->editor, FALSE, NULL) :
editor_get_word_at_pos(doc->editor, peek_pos, NULL);
peek_pos < sci_get_selection_end(sci))
{
expr = editor_get_default_selection(doc->editor, FALSE, NULL);
}
else
{
expr = utils_read_evaluate_expr(doc->editor, peek_pos);
}

if ((expr = utils_verify_selection(expr)) != NULL)
{
g_free(input);
input = debug_send_evaluate('3', scid_gen, expr);
g_free(expr);
last_expr = expr;
}
else
tooltip_set(NULL);
Expand Down

0 comments on commit 648224a

Please sign in to comment.