Skip to content

Commit

Permalink
Merge pull request #177 from forkeith/set_with_prototype
Browse files Browse the repository at this point in the history
keep with_prototype when switching contexts with `set`
  • Loading branch information
trishume authored Jun 12, 2018
2 parents 231eafc + c0e1a2c commit 9374fe9
Showing 1 changed file with 75 additions and 10 deletions.
85 changes: 75 additions & 10 deletions src/parsing/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,11 +595,11 @@ impl ParseState {

/// Returns true if the stack was changed
fn perform_op(&mut self, line: &str, regions: &Region, pat: &MatchPattern) -> bool {
let ctx_refs = match pat.operation {
MatchOperation::Push(ref ctx_refs) => ctx_refs,
let (ctx_refs, old_proto) = match pat.operation {
MatchOperation::Push(ref ctx_refs) => (ctx_refs, None),
MatchOperation::Set(ref ctx_refs) => {
self.stack.pop();
ctx_refs
let old_proto = self.stack.pop().and_then(|s| s.prototype);
(ctx_refs, old_proto)
}
MatchOperation::Pop => {
self.stack.pop();
Expand All @@ -608,13 +608,16 @@ impl ParseState {
MatchOperation::None => return false,
};
for (i, r) in ctx_refs.iter().enumerate() {
// if a with_prototype was specified, and multiple contexts were pushed,
// then the with_prototype applies only to the last context pushed, i.e.
// top most on the stack after all the contexts are pushed - this is also
// referred to as the "target" of the push by sublimehq - see
// https://forum.sublimetext.com/t/dev-build-3111/19240/17 for more info
let proto = if i == ctx_refs.len() - 1 {
pat.with_prototype.clone()
// a `with_prototype` stays active when the context is `set`
// until the context layer in the stack (where the `with_prototype`
// was initially applied) is popped off.
// if a with_prototype was specified, and multiple contexts were pushed,
// then the with_prototype applies only to the last context pushed, i.e.
// top most on the stack after all the contexts are pushed - this is also
// referred to as the "target" of the push by sublimehq - see
// https://forum.sublimetext.com/t/dev-build-3111/19240/17 for more info
pat.with_prototype.clone().or_else(|| old_proto.clone())
} else {
None
};
Expand Down Expand Up @@ -1257,6 +1260,68 @@ contexts:
expect_scope_stacks_with_syntax("/** * */", &["<comment.block.documentation.javadoc>, <punctuation.definition.comment.begin.javadoc>", "<comment.block.documentation.javadoc>, <text.html.javadoc>, <punctuation.definition.comment.javadoc>", "<comment.block.documentation.javadoc>, <punctuation.definition.comment.end.javadoc>"], syntax);
}

#[test]
fn can_parse_with_prototype_set() {
let syntax = r#"%YAML 1.2
---
scope: source.test-set-with-proto
contexts:
main:
- match: a
scope: a
set: next1
with_prototype:
- match: '1'
scope: '1'
- match: '2'
scope: '2'
- match: '3'
scope: '3'
- match: '4'
scope: '4'
- match: '5'
scope: '5'
set: [next3, next2]
with_prototype:
- match: c
scope: cwith
next1:
- match: b
scope: b
set: next2
next2:
- match: c
scope: c
push: next3
- match: e
scope: e
pop: true
- match: f
scope: f
set: [next1, next2]
next3:
- match: d
scope: d
- match: (?=e)
pop: true
- match: c
scope: cwithout
"#;

expect_scope_stacks_with_syntax(
"a1b2c3d4e5",
&[
"<a>", "<1>", "<b>", "<2>", "<c>", "<3>", "<d>", "<4>", "<e>", "<5>"
], SyntaxDefinition::load_from_str(&syntax, true, None).unwrap()
);
expect_scope_stacks_with_syntax(
"5cfcecbedcdea",
&[
"<5>", "<cwith>", "<f>", "<e>", "<b>", "<d>", "<cwithout>", "<a>"
], SyntaxDefinition::load_from_str(&syntax, true, None).unwrap()
);
}

fn expect_scope_stacks(line_without_newline: &str, expect: &[&str], syntax: &str) {
println!("Parsing with newlines");
let line_with_newline = format!("{}\n", line_without_newline);
Expand Down

0 comments on commit 9374fe9

Please sign in to comment.