Handle zero-length segments properly
parent
b37b8eac18
commit
55df4f1823
|
@ -73,6 +73,8 @@
|
|||
(!(context)->definition->extend_parent || \
|
||||
!(context)->all_ancestors_extend)
|
||||
|
||||
#define SEGMENT_END_AT_LINE_END(s) ((s)->context->definition->end_at_line_end)
|
||||
|
||||
#define CONTEXT_IS_SIMPLE(c) ((c)->definition->type == CONTEXT_TYPE_SIMPLE)
|
||||
#define CONTEXT_IS_CONTAINER(c) ((c)->definition->type == CONTEXT_TYPE_CONTAINER)
|
||||
#define SEGMENT_IS_INVALID(s) ((s)->context == NULL)
|
||||
|
@ -374,6 +376,9 @@ static void erase_segments (GtkSourceContextEngine *ce,
|
|||
gint start,
|
||||
gint end,
|
||||
Segment *hint);
|
||||
static void segment_remove (GtkSourceContextEngine *ce,
|
||||
Segment *segment);
|
||||
|
||||
static void find_insertion_place (Segment *segment,
|
||||
gint offset,
|
||||
Segment **parent,
|
||||
|
@ -2480,6 +2485,9 @@ apply_match (Segment *state,
|
|||
segment_extend (state, line->start_at + match_end);
|
||||
apply_sub_patterns (state, line, regex, where);
|
||||
*line_pos = match_end;
|
||||
|
||||
g_assert (state->end_at >= line->start_at + *line_pos);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -3288,6 +3296,7 @@ segment_ends_here (Segment *state,
|
|||
gint pos)
|
||||
{
|
||||
g_assert (SEGMENT_IS_CONTAINER (state));
|
||||
|
||||
return state->context->definition->u.start_end.end &&
|
||||
regex_match (state->context->end,
|
||||
line->text,
|
||||
|
@ -3494,11 +3503,8 @@ next_segment (GtkSourceContextEngine *ce,
|
|||
* Still, it may happen that parent context ends in
|
||||
* the middle of the end regex match, apply_match()
|
||||
* checks this. */
|
||||
if (apply_match (state, line, &pos,
|
||||
state->context->end,
|
||||
SUB_PATTERN_WHERE_END))
|
||||
if (apply_match (state, line, &pos, state->context->end, SUB_PATTERN_WHERE_END))
|
||||
{
|
||||
g_assert (state->end_at >= line->start_at + pos);
|
||||
g_assert (pos <= line->length);
|
||||
/* FIXME: if child may terminate parent */
|
||||
*new_state = state->parent;
|
||||
|
@ -3519,7 +3525,6 @@ next_segment (GtkSourceContextEngine *ce,
|
|||
* check_line_end:
|
||||
*
|
||||
* @state: current state.
|
||||
* @line: analyzed line.
|
||||
* @hint: child of @state used in analyze_line() and next_segment().
|
||||
*
|
||||
* Closes the contexts that cannot contain end of lines if needed.
|
||||
|
@ -3529,7 +3534,6 @@ next_segment (GtkSourceContextEngine *ce,
|
|||
*/
|
||||
static Segment *
|
||||
check_line_end (Segment *state,
|
||||
LineInfo *line,
|
||||
Segment **hint)
|
||||
{
|
||||
Segment *current_segment;
|
||||
|
@ -3543,29 +3547,17 @@ check_line_end (Segment *state,
|
|||
terminating_segment = NULL;
|
||||
current_segment = state;
|
||||
|
||||
do
|
||||
while (current_segment)
|
||||
{
|
||||
if (current_segment->context->definition->end_at_line_end)
|
||||
if (SEGMENT_END_AT_LINE_END (current_segment))
|
||||
terminating_segment = current_segment;
|
||||
else if (!ANCESTOR_CAN_END_CONTEXT(current_segment->context))
|
||||
break;
|
||||
current_segment = current_segment->parent;
|
||||
}
|
||||
while (current_segment &&
|
||||
(ANCESTOR_CAN_END_CONTEXT (current_segment->context) ||
|
||||
(terminating_segment && terminating_segment->parent == current_segment)));
|
||||
|
||||
if (terminating_segment)
|
||||
{
|
||||
/* We have found a context that ends here, so we close
|
||||
* it and its descendants. */
|
||||
current_segment = state;
|
||||
|
||||
do
|
||||
{
|
||||
g_assert (current_segment->end_at >= line->length);
|
||||
current_segment = current_segment->parent;
|
||||
}
|
||||
while (current_segment != terminating_segment->parent);
|
||||
|
||||
*hint = terminating_segment;
|
||||
return terminating_segment->parent;
|
||||
}
|
||||
|
@ -3575,6 +3567,69 @@ check_line_end (Segment *state,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
delete_zero_length_segments (GtkSourceContextEngine *ce,
|
||||
GList *list,
|
||||
Segment **hint)
|
||||
{
|
||||
while (list)
|
||||
{
|
||||
Segment *s = list->data;
|
||||
|
||||
if (s->start_at == s->end_at)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = list->next; l != NULL; )
|
||||
{
|
||||
GList *next = l->next;
|
||||
Segment *s2 = l->data;
|
||||
gboolean child = FALSE;
|
||||
|
||||
while (s2)
|
||||
{
|
||||
if (s2 == s)
|
||||
{
|
||||
child = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
s2 = s2->parent;
|
||||
}
|
||||
|
||||
if (child)
|
||||
list = g_list_delete_link (list, l);
|
||||
|
||||
l = next;
|
||||
}
|
||||
|
||||
if (*hint)
|
||||
{
|
||||
Segment *s2 = *hint;
|
||||
gboolean child = FALSE;
|
||||
|
||||
while (s2)
|
||||
{
|
||||
if (s2 == s)
|
||||
{
|
||||
child = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
s2 = s2->parent;
|
||||
}
|
||||
|
||||
if (child)
|
||||
*hint = s->parent;
|
||||
}
|
||||
|
||||
segment_remove (ce, s);
|
||||
}
|
||||
|
||||
list = g_list_delete_link (list, list);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* analyze_line:
|
||||
*
|
||||
|
@ -3594,6 +3649,7 @@ analyze_line (GtkSourceContextEngine *ce,
|
|||
Segment **hint)
|
||||
{
|
||||
gint line_pos = 0;
|
||||
GList *new_segments = NULL;
|
||||
|
||||
g_assert (SEGMENT_IS_CONTAINER (state));
|
||||
g_assert (!(*hint) || (*hint)->parent == state);
|
||||
|
@ -3607,8 +3663,14 @@ analyze_line (GtkSourceContextEngine *ce,
|
|||
break;
|
||||
|
||||
g_assert (new_state != NULL);
|
||||
g_assert (SEGMENT_IS_CONTAINER (new_state));
|
||||
|
||||
state = new_state;
|
||||
g_assert (SEGMENT_IS_CONTAINER (state));
|
||||
|
||||
/* state may be extended later, so not all elements of new_segments
|
||||
* really have zero length */
|
||||
if (state->start_at == state->end_at)
|
||||
new_segments = g_list_prepend (new_segments, state);
|
||||
}
|
||||
|
||||
/* Extend current state to the end of line. */
|
||||
|
@ -3618,14 +3680,21 @@ analyze_line (GtkSourceContextEngine *ce,
|
|||
/* Verify if we need to close the context because we are at
|
||||
* the end of the line. */
|
||||
if (ANCESTOR_CAN_END_CONTEXT (state->context) ||
|
||||
state->context->definition->end_at_line_end)
|
||||
SEGMENT_END_AT_LINE_END (state))
|
||||
{
|
||||
state = check_line_end (state, line, hint);
|
||||
state = check_line_end (state, hint);
|
||||
}
|
||||
|
||||
/* Extend the segment to the beginning of next line. */
|
||||
g_assert (SEGMENT_IS_CONTAINER (state));
|
||||
segment_extend (state, NEXT_LINE_OFFSET (line));
|
||||
|
||||
/* if it's the last line, don't bother with zero length segments */
|
||||
if (!line->eol_length)
|
||||
g_list_free (new_segments);
|
||||
else
|
||||
delete_zero_length_segments (ce, new_segments, hint);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,5 +44,9 @@
|
|||
|
||||
<style name="changelog:release" foreground="#0095ff" bold="true"/>
|
||||
|
||||
<style name="makefile:trailing-tab" background="pink"/>
|
||||
<style name="makefile:trailing-tab" background="pink"/>
|
||||
<!-- <style name="makefile:assignment-rhs" background="red"/>-->
|
||||
<!-- <style name="makefile:assignment-lhs" background="blue"/>-->
|
||||
<!-- <style name="makefile:prereq" background="yellow"/>-->
|
||||
<!-- <style name="makefile:command" background="green"/>-->
|
||||
</style-scheme>
|
||||
|
|
|
@ -2,13 +2,14 @@
|
|||
<language id="makefile" _name="Makefile" version="2.0" _section="Sources"
|
||||
mimetypes="text/x-makefile" globs="Makefile*">
|
||||
<styles>
|
||||
<style id="comment" name="Comment" map-to="def:comment"/>
|
||||
<style id="function" name="Function" map-to="def:function"/>
|
||||
<style id="string" name="String" map-to="def:string"/>
|
||||
<style id="keyword" name="Keyword" map-to="def:keyword"/>
|
||||
<style id="variable" name="Variable" map-to="def:data-type"/>
|
||||
<style id="target" name="Target" map-to="def:function"/>
|
||||
<style id="trailing-tab" name="Trailing Tab"/>
|
||||
<style id="variable" name="Variable" map-to="def:data-type"/>
|
||||
<style id="assignment-rhs" name="assignment-rhs"/>
|
||||
<style id="assignment-lhs" name="assignment-lhs"/>
|
||||
<style id="targets" name="targets" map-to="def:function"/>
|
||||
<style id="prereq" name="prereq"/>
|
||||
<style id="command" name="command"/>
|
||||
<style id="trailing-tab" name="Trailing Tab"/>
|
||||
<style id="function" name="function" map-to="def:function"/>
|
||||
</styles>
|
||||
|
||||
<definitions>
|
||||
|
@ -21,7 +22,77 @@
|
|||
</include>
|
||||
</context>
|
||||
|
||||
<context id="backtick-string" style-ref="function" end-at-line-end="true">
|
||||
<start>`</start>
|
||||
<end>`</end>
|
||||
<include>
|
||||
<context ref="def:escape"/>
|
||||
<context ref="def:line-continue"/>
|
||||
</include>
|
||||
</context>
|
||||
|
||||
<context id="assignment-rhs" style-ref="assignment-rhs" end-at-line-end="true">
|
||||
<start></start>
|
||||
<include>
|
||||
<context ref="def:line-continue"/>
|
||||
<context ref="def:shell-like-comment"/>
|
||||
<context ref="variable"/>
|
||||
<context ref="def:string"/>
|
||||
<context ref="def:single-quoted-string"/>
|
||||
<context ref="backtick-string"/>
|
||||
</include>
|
||||
</context>
|
||||
|
||||
<context id="command" style-ref="command" extend-parent="false" end-at-line-end="true">
|
||||
<start></start>
|
||||
<include>
|
||||
<context ref="def:line-continue"/>
|
||||
<context ref="def:shell-like-comment"/>
|
||||
<context ref="variable"/>
|
||||
<context ref="def:string"/>
|
||||
<context ref="def:single-quoted-string"/>
|
||||
<context ref="backtick-string"/>
|
||||
</include>
|
||||
</context>
|
||||
|
||||
<context id="makefile">
|
||||
<include>
|
||||
<context ref="def:shebang"/>
|
||||
<context ref="def:shell-like-comment"/>
|
||||
|
||||
<context id="assignment" end-at-line-end="true">
|
||||
<start>^(\%{variable})\s*=</start>
|
||||
<include>
|
||||
<context sub-pattern="1" where="start" style-ref="assignment-lhs"/>
|
||||
<context ref="assignment-rhs"/>
|
||||
</include>
|
||||
</context>
|
||||
|
||||
<context id="rule">
|
||||
<start>^([^\t\:][^\:]*)\:</start>
|
||||
<end>^(?!\t)</end>
|
||||
<include>
|
||||
<context sub-pattern="1" where="start" style-ref="targets"/>
|
||||
<context id="prereq" end-at-line-end="true" style-ref="prereq">
|
||||
<start>(?<=:)</start>
|
||||
<end>;</end>
|
||||
<include>
|
||||
<context ref="def:escape"/>
|
||||
<context ref="def:line-continue"/>
|
||||
<context ref="variable"/>
|
||||
</include>
|
||||
</context>
|
||||
<context id="trailing-tab" style-ref="trailing-tab">
|
||||
<match>^\t+$</match>
|
||||
</context>
|
||||
<context ref="command"/>
|
||||
</include>
|
||||
</context>
|
||||
|
||||
</include>
|
||||
</context>
|
||||
|
||||
<!-- <context id="somecontext">
|
||||
<include>
|
||||
<context ref="def:shebang"/>
|
||||
<context ref="def:shell-like-comment"/>
|
||||
|
@ -111,6 +182,6 @@
|
|||
<keyword>\.SUFFIXES</keyword>
|
||||
</context>
|
||||
</include>
|
||||
</context>
|
||||
</context>-->
|
||||
</definitions>
|
||||
</language>
|
||||
|
|
Loading…
Reference in New Issue