mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-18 06:55:26 +02:00
132 lines
3.7 KiB
Go
132 lines
3.7 KiB
Go
package openssh
|
|
|
|
import (
|
|
"config-lsp/common"
|
|
"errors"
|
|
"unicode/utf8"
|
|
|
|
"github.com/tliron/glsp"
|
|
protocol "github.com/tliron/glsp/protocol_3_16"
|
|
"golang.org/x/exp/maps"
|
|
|
|
_ "github.com/tliron/commonlog/simple"
|
|
)
|
|
|
|
func TextDocumentCompletion(context *glsp.Context, params *protocol.CompletionParams) (interface{}, error) {
|
|
optionName, line, err := Parser.FindByLineNumber(uint32(params.Position.Line))
|
|
|
|
if err == nil {
|
|
if line.IsCursorAtRootOption(int(params.Position.Character)) {
|
|
return getRootCompletions(), nil
|
|
} else {
|
|
rawLine, cursor := common.OffsetLineAtLeft(
|
|
uint32(utf8.RuneCountInString(optionName + " ")),
|
|
line.Value,
|
|
params.Position.Character,
|
|
)
|
|
|
|
return getOptionCompletions(optionName, rawLine, cursor), nil
|
|
}
|
|
} else if errors.Is(err, common.LineNotFoundError{}) {
|
|
return getRootCompletions(), nil
|
|
}
|
|
|
|
return nil, err
|
|
}
|
|
|
|
func getRootCompletions() []protocol.CompletionItem {
|
|
completions := make([]protocol.CompletionItem, len(Options))
|
|
|
|
optionsKey := maps.Keys(Options)
|
|
for index := 0; index < len(maps.Keys(Options)); index++ {
|
|
label := optionsKey[index]
|
|
option := Options[label]
|
|
insertText := label + " " + "${1:value}"
|
|
|
|
format := protocol.InsertTextFormatSnippet
|
|
kind := protocol.CompletionItemKindField
|
|
|
|
|
|
completions[index] = protocol.CompletionItem{
|
|
Label: label,
|
|
Documentation: common.GetDocumentation(&option),
|
|
InsertText: &insertText,
|
|
InsertTextFormat: &format,
|
|
Kind: &kind,
|
|
}
|
|
}
|
|
|
|
return completions
|
|
}
|
|
|
|
func getCompletionsFromValue(requiredValue common.Value, line string, cursor uint32) []protocol.CompletionItem {
|
|
switch requiredValue.(type) {
|
|
case common.EnumValue:
|
|
enumValue := requiredValue.(common.EnumValue)
|
|
completions := make([]protocol.CompletionItem, len(requiredValue.(common.EnumValue).Values))
|
|
|
|
for index, value := range enumValue.Values {
|
|
textFormat := protocol.InsertTextFormatPlainText
|
|
kind := protocol.CompletionItemKindEnum
|
|
|
|
completions[index] = protocol.CompletionItem{
|
|
Label: value,
|
|
InsertTextFormat: &textFormat,
|
|
Kind: &kind,
|
|
}
|
|
}
|
|
|
|
return completions
|
|
case common.CustomValue:
|
|
customValue := requiredValue.(common.CustomValue)
|
|
val := customValue.FetchValue()
|
|
|
|
return getCompletionsFromValue(val, line, cursor)
|
|
case common.ArrayValue:
|
|
arrayValue := requiredValue.(common.ArrayValue)
|
|
relativePosition, found := common.FindPreviousCharacter(line, arrayValue.Separator)
|
|
|
|
if found {
|
|
line, cursor = common.OffsetLineAtLeft(relativePosition, line, cursor)
|
|
}
|
|
|
|
return getCompletionsFromValue(arrayValue.SubValue, line, cursor)
|
|
case common.OrValue:
|
|
orValue := requiredValue.(common.OrValue)
|
|
|
|
completions := make([]protocol.CompletionItem, 0)
|
|
|
|
for _, subValue := range orValue.Values {
|
|
completions = append(completions, getCompletionsFromValue(subValue, line, cursor)...)
|
|
}
|
|
|
|
return completions
|
|
case common.PrefixWithMeaningValue:
|
|
prefixWithMeaningValue := requiredValue.(common.PrefixWithMeaningValue)
|
|
|
|
return getCompletionsFromValue(prefixWithMeaningValue.SubValue, line, cursor)
|
|
case common.KeyValueAssignmentValue:
|
|
keyValueAssignmentValue := requiredValue.(common.KeyValueAssignmentValue)
|
|
|
|
relativePosition, found := common.FindPreviousCharacter(line, keyValueAssignmentValue.Separator)
|
|
|
|
if found {
|
|
line, cursor = common.OffsetLineAtLeft(relativePosition, line, cursor)
|
|
|
|
return getCompletionsFromValue(keyValueAssignmentValue.Value, line, cursor)
|
|
} else {
|
|
return getCompletionsFromValue(keyValueAssignmentValue.Key, line, cursor)
|
|
}
|
|
}
|
|
|
|
return []protocol.CompletionItem{}
|
|
}
|
|
|
|
func getOptionCompletions(optionName string, line string, cursor uint32) []protocol.CompletionItem {
|
|
option := Options[optionName]
|
|
|
|
completions := getCompletionsFromValue(option.Value, line, cursor)
|
|
|
|
return completions
|
|
}
|