Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
i/prompting: render path patterns variants using recursive descent pa…
…rser (#14059) * i/prompting: implement path pattern expansion Path patterns may include arbitrary nested groups, delimited by '{' and '}', up to a limit on the total number of groups. In order to compare the precedence of path patterns which match a given path, these path patterns must be expanded until no groups remain, and thus the particular group-free patterns which was resolved from the original patterns when matching the path can be compared. Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting: add PathPattern type for pattern validation and expansion Rather than separately validate and expand path patterns, storing the result as a list of expanded patterns, parse a pattern into a PathPattern type, which can dynamically render expanded path patterns as needed with minimal overhead. When path patterns are received from prompting clients, path patterns can be unmarshalled and automatically validated, and any future use of the pattern in-memory can use the pre-parsed PathPattern to iterate through expanded path patterns without needing to explicitly expand and store all path patterns. Additionally, the new PathPattern type should be used in Constraints in place of the old path pattern string. Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting: refactor path pattern parsing Rather than keep separate stacks for the sequences and paths which the parser is currently inside, instead keep a single stack, to which the existing sequence and a new group is added whenever a '{' rune is encountered. Then there is no need to no need for a variable to hold the current group, peeking the stack yields the most recent group, to which the current sequence can be added whenever a ',' or '}' is encountered. When a '}' is encountered, the most recent group is popped off the stack, the current sequence is added to it (completing the group), and then the previous sequence is popped off the stack and the completed group is added to it. From there, that previous sequence is now considered the current sequence until another '{' is encountered. Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting: use stack instead of non-temp current sequence variable Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting: improve error message prefixes Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting: moved patterns to dedicated subpackage of prompting Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: add scanner, parser, and renderer for path patterns Co-authored-by: Oliver Calder <oliver.calder@canonical.com> Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: add minimal tests for scan and render Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: replace parser in path pattern struct Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: add recursion depth check for nested groups Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: adjusted error messages Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: preserve escape characters in expanded patterns Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: scanner detects invalid chars and returns error Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting: fix formatting Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: add helper for converting read runes into text token Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: consolidate render node types into render.go Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: only re-render differences from previous configuration Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: remove GoString functions from render config types Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting{,/patterns}: added dedicated Match method to PathPattern Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: unexport all internal types and interfaces Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: rename renderConfig to variantState Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: unexported internal renderAllVariants Also improved naming and documentation. Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: renamed local variables to match new variantState naming Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: variantState has Render method and renderNode Add a reference to the `renderNode` used to generate a given `variantState` to that state itself. This allows methods on `variantState` to be called without needing to pass as a parameter the same `renderNode` which was used to generate the `variantState`. Also, move the `Render` function to be a method on `variantState` instead of `renderNode`. This makes sense semantically, since we render particular variants, rather than nodes themselves, and makes sense ergonomically since we now have a reference to the `renderNode` within each `variantState`, so there is no need to pass parameters around for nodes and variants which are required to be associated anyway. Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: consolidate optimize and fix nodeEqual Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: add tests for tokenType.String Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: use dedicated flag to tell when all seq variants are exhausted Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: use ..._internal_test.go for non-exported test files Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: fix growing of render buffer, unexport peek Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: merge literalVariant into literal Add comment as such to the `literal` type definition, and have `literal.NextVariant` return length 0 to make it consistent with other `variantState` types. Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: preallocate render buffer for initial variant Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: improve error handling Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: moved simple bad pattern checks to scanner Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: return length along with initial variant Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * i/prompting/patterns: simplify check if more variants remain when rendering Signed-off-by: Oliver Calder <oliver.calder@canonical.com> --------- Signed-off-by: Oliver Calder <oliver.calder@canonical.com> Co-authored-by: Zygmunt Krynicki <me@zygoon.pl>
- Loading branch information