From 529d28d9439358552114c27c8d5f9b3ffac2736c Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Tue, 30 Jul 2024 22:10:04 +0200 Subject: [PATCH] feat: Make separators more dynamic --- common/parser.go | 66 ++++++++++++-------- doc-values/value-array.go | 2 +- handlers/openssh/shared.go | 11 +--- handlers/openssh/text-document-completion.go | 2 +- 4 files changed, 45 insertions(+), 36 deletions(-) diff --git a/common/parser.go b/common/parser.go index 8330e7e..a04311f 100644 --- a/common/parser.go +++ b/common/parser.go @@ -11,13 +11,21 @@ type SimpleConfigPosition struct { } type SimpleConfigLine struct { - Value string - Position SimpleConfigPosition + Value string + Separator string + Position SimpleConfigPosition +} + +// Get the character positions of [Option End, Separator End, Value End] +func (l SimpleConfigLine) GetCharacterPositions(optionName string) [3]int { + return [3]int{len(optionName), len(optionName + l.Separator), len(optionName + l.Separator + l.Value)} } type SimpleConfigOptions struct { - Separator string - IgnorePattern regexp.Regexp + Separator regexp.Regexp + IgnorePattern regexp.Regexp + // This is the separator that will be used when adding a new line + IdealSeparator string AvailableOptions *map[string]Option } @@ -27,24 +35,43 @@ type SimpleConfigParser struct { } func (p *SimpleConfigParser) AddLine(line string, lineNumber uint32) (string, error) { - parts := strings.SplitN(line, p.Options.Separator, 2) + var option string + var separator string + var value string - if len(parts) == 0 { + re := p.Options.Separator + matches := re.FindStringSubmatch(line) + + if len(matches) == 0 { return "", docvalues.MalformedLineError{} } - option := parts[0] + optionIndex := re.SubexpIndex("OptionName") + + if optionIndex == -1 { + return "", docvalues.MalformedLineError{} + } + + option = matches[optionIndex] if _, exists := (*p.Options.AvailableOptions)[option]; !exists { return option, docvalues.OptionUnknownError{} } - value := "" + separatorIndex := re.SubexpIndex("Separator") - if len(parts) > 1 { - value = parts[1] + if separatorIndex == -1 { + return option, docvalues.MalformedLineError{} } + valueIndex := re.SubexpIndex("Value") + + if valueIndex == -1 { + return option, docvalues.MalformedLineError{} + } + + value = matches[valueIndex] + if _, exists := p.Lines[option]; exists { return option, docvalues.OptionAlreadyExistsError{ AlreadyLine: p.Lines[option].Position.Line, @@ -52,7 +79,8 @@ func (p *SimpleConfigParser) AddLine(line string, lineNumber uint32) (string, er } p.Lines[option] = SimpleConfigLine{ - Value: value, + Value: value, + Separator: separator, Position: SimpleConfigPosition{ Line: lineNumber, }, @@ -75,26 +103,12 @@ func (p *SimpleConfigParser) RemoveOption(option string) { delete(p.Lines, option) } -func (p *SimpleConfigParser) UpsertOption(option string, value string) { - if _, exists := p.Lines[option]; exists { - p.ReplaceOption(option, value) - } else { - p.AddLine(option+p.Options.Separator+value, uint32(len(p.Lines))) - } -} - func (p *SimpleConfigParser) GetOption(option string) (SimpleConfigLine, error) { if _, exists := p.Lines[option]; exists { return p.Lines[option], nil } - return SimpleConfigLine{ - Value: "", - Position: SimpleConfigPosition{ - Line: 0, - }, - }, - docvalues.OptionUnknownError{} + return SimpleConfigLine{}, docvalues.OptionUnknownError{} } func (p *SimpleConfigParser) ParseFromFile(content string) []docvalues.OptionError { diff --git a/doc-values/value-array.go b/doc-values/value-array.go index 0b6cd3d..e4ec4a3 100644 --- a/doc-values/value-array.go +++ b/doc-values/value-array.go @@ -55,7 +55,7 @@ func (v ArrayValue) GetTypeDescription() []string { func (v ArrayValue) CheckIsValid(value string) error { values := strings.Split(value, v.Separator) - if v.DuplicatesExtractor != nil { + if *v.DuplicatesExtractor != nil { valuesOccurrences := utils.SliceToMap( utils.Map(values, *v.DuplicatesExtractor), 0, diff --git a/handlers/openssh/shared.go b/handlers/openssh/shared.go index 10e4ccf..877485e 100644 --- a/handlers/openssh/shared.go +++ b/handlers/openssh/shared.go @@ -6,17 +6,12 @@ import ( ) func createOpenSSHConfigParser() common.SimpleConfigParser { - pattern, err := regexp.Compile(`^(?:#|\s*$)`) - - if err != nil { - panic(err) - } - return common.SimpleConfigParser{ Lines: make(map[string]common.SimpleConfigLine), Options: common.SimpleConfigOptions{ - Separator: " ", - IgnorePattern: *pattern, + Separator: *regexp.MustCompile(`(?m)^\s*(?P\w+)(?P\s*)(?P.*)\s*$`), + IgnorePattern: *regexp.MustCompile(`^(?:#|\s*$)`), + IdealSeparator: " ", AvailableOptions: &Options, }, } diff --git a/handlers/openssh/text-document-completion.go b/handlers/openssh/text-document-completion.go index da3d439..96f7b67 100644 --- a/handlers/openssh/text-document-completion.go +++ b/handlers/openssh/text-document-completion.go @@ -19,7 +19,7 @@ func TextDocumentCompletion(context *glsp.Context, params *protocol.CompletionPa if params.Position.Character < uint32(len(optionName)) { return getRootCompletions(), nil } else { - cursor := params.Position.Character - uint32(len(optionName+Parser.Options.Separator)) + cursor := params.Position.Character - uint32(line.GetCharacterPositions(optionName)[1]) return getOptionCompletions(optionName, line.Value, cursor), nil }