mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-18 23:15:26 +02:00
feat(aliases): Add hover info
This commit is contained in:
parent
3a1b38400c
commit
3538a37203
@ -42,7 +42,10 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
devShells.default = pkgs.mkShell {
|
devShells.default = pkgs.mkShell {
|
||||||
buildInputs = inputs;
|
buildInputs = inputs ++ (with pkgs; [
|
||||||
|
mailutils
|
||||||
|
swaks
|
||||||
|
]);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"config-lsp/handlers/aliases/fields"
|
"config-lsp/handlers/aliases/fields"
|
||||||
"config-lsp/utils"
|
"config-lsp/utils"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AliasValueInterface interface {
|
type AliasValueInterface interface {
|
||||||
@ -102,6 +103,16 @@ type AliasValueErrorCode struct {
|
|||||||
AliasValue
|
AliasValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a AliasValueErrorCode) ErrorCodeAsInt() uint16 {
|
||||||
|
code, err := strconv.Atoi(a.Value)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return uint16(code)
|
||||||
|
}
|
||||||
|
|
||||||
type AliasValueErrorMessage struct {
|
type AliasValueErrorMessage struct {
|
||||||
AliasValue
|
AliasValue
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ func GetCompletionsForEntry(
|
|||||||
return completions, nil
|
return completions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
value := getValueAtCursor(cursor, entry)
|
value := GetValueAtCursor(cursor, entry)
|
||||||
relativeCursor := cursor - entry.Key.Location.Start.Character
|
relativeCursor := cursor - entry.Key.Location.Start.Character
|
||||||
|
|
||||||
if value == nil {
|
if value == nil {
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getValueAtCursor(
|
func GetValueAtCursor(
|
||||||
cursor uint32,
|
cursor uint32,
|
||||||
entry *ast.AliasEntry,
|
entry *ast.AliasEntry,
|
||||||
) *ast.AliasValueInterface {
|
) *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
|
package lsp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"config-lsp/handlers/hosts"
|
"config-lsp/handlers/aliases"
|
||||||
|
"config-lsp/handlers/aliases/ast"
|
||||||
|
"config-lsp/handlers/aliases/handlers"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/tliron/glsp"
|
"github.com/tliron/glsp"
|
||||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||||
@ -11,76 +14,51 @@ func TextDocumentHover(
|
|||||||
context *glsp.Context,
|
context *glsp.Context,
|
||||||
params *protocol.HoverParams,
|
params *protocol.HoverParams,
|
||||||
) (*protocol.Hover, error) {
|
) (*protocol.Hover, error) {
|
||||||
document := hosts.DocumentParserMap[params.TextDocument.URI]
|
document := aliases.DocumentParserMap[params.TextDocument.URI]
|
||||||
|
|
||||||
line := params.Position.Line
|
line := params.Position.Line
|
||||||
// character := params.Position.Character
|
character := params.Position.Character
|
||||||
|
|
||||||
if _, found := document.Parser.CommentLines[line]; found {
|
if _, found := document.Parser.CommentLines[line]; found {
|
||||||
// Comment
|
// Comment
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// entry, found := document.Parser.Tree.Entries[line]
|
rawEntry, found := document.Parser.Aliases.Get(line)
|
||||||
//
|
|
||||||
// if !found {
|
if !found {
|
||||||
// // Empty line
|
return nil, nil
|
||||||
// return nil, nil
|
}
|
||||||
// }
|
|
||||||
//
|
entry := rawEntry.(*ast.AliasEntry)
|
||||||
// target := handlers.GetHoverTargetInEntry(*entry, character)
|
|
||||||
//
|
if entry.Key != nil && character >= entry.Key.Location.Start.Character && character <= entry.Key.Location.End.Character {
|
||||||
// var hostname *ast.HostsHostname
|
text := handlers.GetAliasHoverInfo(*document.Indexes, *entry)
|
||||||
//
|
|
||||||
// switch *target {
|
return &protocol.Hover{
|
||||||
// case handlers.HoverTargetIPAddress:
|
Contents: text,
|
||||||
// relativeCursor := character - entry.IPAddress.Location.Start.Character
|
}, nil
|
||||||
// hover := fields.IPAddressField.FetchHoverInfo(entry.IPAddress.Value.String(), relativeCursor)
|
}
|
||||||
//
|
|
||||||
// return &protocol.Hover{
|
if entry.Values != nil && character >= entry.Values.Location.Start.Character && character <= entry.Values.Location.End.Character {
|
||||||
// Contents: hover,
|
value := handlers.GetValueAtCursor(character, entry)
|
||||||
// }, nil
|
|
||||||
// case handlers.HoverTargetHostname:
|
if value == nil {
|
||||||
// hostname = entry.Hostname
|
return nil, nil
|
||||||
// case handlers.HoverTargetAlias:
|
}
|
||||||
// for _, alias := range entry.Aliases {
|
|
||||||
// if alias.Location.Start.Character <= character && character <= alias.Location.End.Character {
|
contents := []string{}
|
||||||
// hostname = alias
|
contents = append(contents, handlers.GetAliasValueTypeInfo(*value)...)
|
||||||
// break
|
contents = append(contents, "")
|
||||||
// }
|
contents = append(contents, "#### Value")
|
||||||
// }
|
contents = append(contents, handlers.GetAliasValueHoverInfo(*document.Indexes, *value))
|
||||||
// }
|
|
||||||
//
|
text := strings.Join(contents, "\n")
|
||||||
// if hostname != nil {
|
|
||||||
// contents := []string{
|
return &protocol.Hover{
|
||||||
// "## Hostname",
|
Contents: text,
|
||||||
// }
|
}, nil
|
||||||
// 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
|
|
||||||
// }
|
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user