mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-18 15:05:28 +02:00
feat(aliases): Add hover info
This commit is contained in:
parent
3a1b38400c
commit
3538a37203
@ -42,7 +42,10 @@
|
||||
};
|
||||
};
|
||||
devShells.default = pkgs.mkShell {
|
||||
buildInputs = inputs;
|
||||
buildInputs = inputs ++ (with pkgs; [
|
||||
mailutils
|
||||
swaks
|
||||
]);
|
||||
};
|
||||
}
|
||||
);
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"config-lsp/handlers/aliases/fields"
|
||||
"config-lsp/utils"
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type AliasValueInterface interface {
|
||||
@ -102,6 +103,16 @@ type AliasValueErrorCode struct {
|
||||
AliasValue
|
||||
}
|
||||
|
||||
func (a AliasValueErrorCode) ErrorCodeAsInt() uint16 {
|
||||
code, err := strconv.Atoi(a.Value)
|
||||
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return uint16(code)
|
||||
}
|
||||
|
||||
type AliasValueErrorMessage struct {
|
||||
AliasValue
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ func GetCompletionsForEntry(
|
||||
return completions, nil
|
||||
}
|
||||
|
||||
value := getValueAtCursor(cursor, entry)
|
||||
value := GetValueAtCursor(cursor, entry)
|
||||
relativeCursor := cursor - entry.Key.Location.Start.Character
|
||||
|
||||
if value == nil {
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"slices"
|
||||
)
|
||||
|
||||
func getValueAtCursor(
|
||||
func GetValueAtCursor(
|
||||
cursor uint32,
|
||||
entry *ast.AliasEntry,
|
||||
) *ast.AliasValueInterface {
|
||||
|
158
handlers/aliases/handlers/hover.go
Normal file
158
handlers/aliases/handlers/hover.go
Normal file
@ -0,0 +1,158 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"config-lsp/handlers/aliases/ast"
|
||||
"config-lsp/handlers/aliases/indexes"
|
||||
"config-lsp/utils"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Get hover information for an alias entry
|
||||
// Expects `entry` to contain at least a key
|
||||
func GetAliasHoverInfo(
|
||||
i indexes.AliasesIndexes,
|
||||
entry ast.AliasEntry,
|
||||
) string {
|
||||
header := []string{
|
||||
fmt.Sprintf("Emails targeted for `%s` will be passed to:", entry.Key.Value),
|
||||
"",
|
||||
}
|
||||
|
||||
var forwards []string
|
||||
|
||||
if entry.Values == nil {
|
||||
forwards = []string{
|
||||
"No forwards configured",
|
||||
}
|
||||
} else {
|
||||
if len(entry.Values.Values) == 1 {
|
||||
forwards = []string{
|
||||
GetAliasValueHoverInfo(
|
||||
i,
|
||||
entry.Values.Values[0],
|
||||
),
|
||||
}
|
||||
} else {
|
||||
forwards = utils.Map(
|
||||
entry.Values.Values,
|
||||
func(value ast.AliasValueInterface) string {
|
||||
return fmt.Sprintf(
|
||||
"* %s",
|
||||
GetAliasValueHoverInfo(
|
||||
i,
|
||||
value,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
content := append(header, forwards...)
|
||||
return strings.Join(
|
||||
content,
|
||||
"\n",
|
||||
)
|
||||
}
|
||||
|
||||
func GetAliasValueHoverInfo(
|
||||
i indexes.AliasesIndexes,
|
||||
value ast.AliasValueInterface,
|
||||
) string {
|
||||
switch value.(type) {
|
||||
case ast.AliasValueUser:
|
||||
return fmt.Sprintf("User: **%s**", value.GetAliasValue().Value)
|
||||
case ast.AliasValueEmail:
|
||||
return fmt.Sprintf("Email: **%s**", value.GetAliasValue().Value)
|
||||
case ast.AliasValueInclude:
|
||||
includeValue := value.(ast.AliasValueInclude)
|
||||
return fmt.Sprintf("Included file: `%s`", string(includeValue.Path.Path))
|
||||
case ast.AliasValueFile:
|
||||
fileValue := value.(ast.AliasValueFile)
|
||||
return fmt.Sprintf("File: Email will be written to `%s`", string(fileValue.Path))
|
||||
case ast.AliasValueCommand:
|
||||
commandValue := value.(ast.AliasValueCommand)
|
||||
return fmt.Sprintf("Command: Will be passed as stdin to `%s`", commandValue.Command)
|
||||
case ast.AliasValueError:
|
||||
errorValue := value.(ast.AliasValueError)
|
||||
|
||||
if errorValue.Code == nil || errorValue.Message == nil {
|
||||
return "Error: An error will show up"
|
||||
}
|
||||
|
||||
return fmt.Sprintf(
|
||||
"Error: An error will show up; code: **%s** (%s), message: '%s'",
|
||||
errorValue.Code.Value,
|
||||
getErrorCodeInfo(errorValue.Code.ErrorCodeAsInt()),
|
||||
errorValue.Message.Value,
|
||||
)
|
||||
}
|
||||
|
||||
panic("Unknown value type")
|
||||
}
|
||||
|
||||
func GetAliasValueTypeInfo(
|
||||
value ast.AliasValueInterface,
|
||||
) []string {
|
||||
switch value.(type) {
|
||||
case ast.AliasValueUser:
|
||||
return []string{
|
||||
"### User",
|
||||
"`user`",
|
||||
"",
|
||||
"A user on the host machine. The user must have a valid entry in the passwd(5) database file.",
|
||||
}
|
||||
case ast.AliasValueEmail:
|
||||
return []string{
|
||||
"### Email",
|
||||
"`user-part@domain-part`",
|
||||
"",
|
||||
"An email address in RFC 5322 format. If an address extension is appended to the user-part, it is first compared for an exact match. It is then stripped so that an address such as user+ext@example.com will only use the part that precedes ‘+’ as a key.",
|
||||
}
|
||||
case ast.AliasValueInclude:
|
||||
return []string{
|
||||
"### Include",
|
||||
"`include:/path/to/file`",
|
||||
"",
|
||||
"Include any definitions in file as alias entries. The format of the file is identical to this one.",
|
||||
}
|
||||
case ast.AliasValueFile:
|
||||
return []string{
|
||||
"### File",
|
||||
"`/path/to/file`",
|
||||
"",
|
||||
"Append messages to file, specified by its absolute pathname.",
|
||||
}
|
||||
case ast.AliasValueCommand:
|
||||
return []string{
|
||||
"### Command",
|
||||
"`|command`",
|
||||
"",
|
||||
"Pipe the message to command on its standard input. The command is run under the privileges of the daemon's unprivileged account.",
|
||||
}
|
||||
case ast.AliasValueError:
|
||||
return []string{
|
||||
"### Error",
|
||||
"`error:code message`",
|
||||
"",
|
||||
"A status code and message to return. The code must be 3 digits, starting 4XX (TempFail) or 5XX (PermFail). The message must be present and can be freely chosen.",
|
||||
}
|
||||
}
|
||||
|
||||
panic("Unknown value type")
|
||||
}
|
||||
|
||||
func getErrorCodeInfo(
|
||||
code uint16,
|
||||
) string {
|
||||
if code >= 400 && code <= 499 {
|
||||
return "4XX: TempFail"
|
||||
}
|
||||
|
||||
if code >= 500 && code <= 599 {
|
||||
return "5XX: PermFail"
|
||||
}
|
||||
|
||||
return "Unknown code"
|
||||
}
|
@ -1,7 +1,10 @@
|
||||
package lsp
|
||||
|
||||
import (
|
||||
"config-lsp/handlers/hosts"
|
||||
"config-lsp/handlers/aliases"
|
||||
"config-lsp/handlers/aliases/ast"
|
||||
"config-lsp/handlers/aliases/handlers"
|
||||
"strings"
|
||||
|
||||
"github.com/tliron/glsp"
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
@ -11,76 +14,51 @@ func TextDocumentHover(
|
||||
context *glsp.Context,
|
||||
params *protocol.HoverParams,
|
||||
) (*protocol.Hover, error) {
|
||||
document := hosts.DocumentParserMap[params.TextDocument.URI]
|
||||
document := aliases.DocumentParserMap[params.TextDocument.URI]
|
||||
|
||||
line := params.Position.Line
|
||||
// character := params.Position.Character
|
||||
character := params.Position.Character
|
||||
|
||||
if _, found := document.Parser.CommentLines[line]; found {
|
||||
// Comment
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// entry, found := document.Parser.Tree.Entries[line]
|
||||
//
|
||||
// if !found {
|
||||
// // Empty line
|
||||
// return nil, nil
|
||||
// }
|
||||
//
|
||||
// target := handlers.GetHoverTargetInEntry(*entry, character)
|
||||
//
|
||||
// var hostname *ast.HostsHostname
|
||||
//
|
||||
// switch *target {
|
||||
// case handlers.HoverTargetIPAddress:
|
||||
// relativeCursor := character - entry.IPAddress.Location.Start.Character
|
||||
// hover := fields.IPAddressField.FetchHoverInfo(entry.IPAddress.Value.String(), relativeCursor)
|
||||
//
|
||||
// return &protocol.Hover{
|
||||
// Contents: hover,
|
||||
// }, nil
|
||||
// case handlers.HoverTargetHostname:
|
||||
// hostname = entry.Hostname
|
||||
// case handlers.HoverTargetAlias:
|
||||
// for _, alias := range entry.Aliases {
|
||||
// if alias.Location.Start.Character <= character && character <= alias.Location.End.Character {
|
||||
// hostname = alias
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if hostname != nil {
|
||||
// contents := []string{
|
||||
// "## Hostname",
|
||||
// }
|
||||
// contents = append(
|
||||
// contents,
|
||||
// fields.HostnameField.GetTypeDescription()...,
|
||||
// )
|
||||
// contents = append(
|
||||
// contents,
|
||||
// []string{
|
||||
// "",
|
||||
// }...,
|
||||
// )
|
||||
// contents = append(
|
||||
// contents,
|
||||
// fields.HostnameField.Documentation,
|
||||
// )
|
||||
// contents = append(
|
||||
// contents,
|
||||
// handlers.GetHoverInfoForHostname(*document, *hostname, character)...,
|
||||
// )
|
||||
//
|
||||
// return &protocol.Hover{
|
||||
// Contents: &protocol.MarkupContent{
|
||||
// Kind: protocol.MarkupKindMarkdown,
|
||||
// Value: strings.Join(contents, "\n"),
|
||||
// },
|
||||
// }, nil
|
||||
// }
|
||||
rawEntry, found := document.Parser.Aliases.Get(line)
|
||||
|
||||
if !found {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
entry := rawEntry.(*ast.AliasEntry)
|
||||
|
||||
if entry.Key != nil && character >= entry.Key.Location.Start.Character && character <= entry.Key.Location.End.Character {
|
||||
text := handlers.GetAliasHoverInfo(*document.Indexes, *entry)
|
||||
|
||||
return &protocol.Hover{
|
||||
Contents: text,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if entry.Values != nil && character >= entry.Values.Location.Start.Character && character <= entry.Values.Location.End.Character {
|
||||
value := handlers.GetValueAtCursor(character, entry)
|
||||
|
||||
if value == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
contents := []string{}
|
||||
contents = append(contents, handlers.GetAliasValueTypeInfo(*value)...)
|
||||
contents = append(contents, "")
|
||||
contents = append(contents, "#### Value")
|
||||
contents = append(contents, handlers.GetAliasValueHoverInfo(*document.Indexes, *value))
|
||||
|
||||
text := strings.Join(contents, "\n")
|
||||
|
||||
return &protocol.Hover{
|
||||
Contents: text,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user