mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-19 07:25:27 +02:00
fix(fstab): Improve handler
This commit is contained in:
parent
433cd9ee4c
commit
f6eb74f638
@ -17,33 +17,14 @@ var SpecField = docvalues.OrValue{
|
|||||||
// docvalues.PathValue{
|
// docvalues.PathValue{
|
||||||
// RequiredType: docvalues.PathTypeFile & docvalues.PathTypeExistenceOptional,
|
// RequiredType: docvalues.PathTypeFile & docvalues.PathTypeExistenceOptional,
|
||||||
// },
|
// },
|
||||||
docvalues.KeyValueAssignmentValue{
|
docvalues.KeyEnumAssignmentValue{
|
||||||
Separator: "=",
|
Separator: "=",
|
||||||
ValueIsOptional: false,
|
ValueIsOptional: false,
|
||||||
Key: docvalues.EnumValue{
|
Values: map[docvalues.EnumString]docvalues.Value{
|
||||||
EnforceValues: true,
|
docvalues.CreateEnumString("UUID"): UuidField,
|
||||||
Values: []docvalues.EnumString{
|
docvalues.CreateEnumString("PARTUUID"): UuidField,
|
||||||
docvalues.CreateEnumString("UUID"),
|
docvalues.CreateEnumString("LABEL"): LabelField,
|
||||||
docvalues.CreateEnumString("LABEL"),
|
docvalues.CreateEnumString("PARTLABEL"): LabelField,
|
||||||
docvalues.CreateEnumString("PARTUUID"),
|
|
||||||
docvalues.CreateEnumString("PARTLABEL"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Value: docvalues.CustomValue{
|
|
||||||
FetchValue: func(rawContext docvalues.CustomValueContext) docvalues.Value {
|
|
||||||
context := rawContext.(docvalues.KeyValueAssignmentContext)
|
|
||||||
|
|
||||||
switch context.SelectedKey {
|
|
||||||
case "UUID":
|
|
||||||
case "PARTUUID":
|
|
||||||
return UuidField
|
|
||||||
case "LABEL":
|
|
||||||
case "PARTLABEL":
|
|
||||||
return LabelField
|
|
||||||
}
|
|
||||||
|
|
||||||
return docvalues.StringValue{}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -44,6 +44,17 @@ func (f *Field) CreateRange(fieldLine uint32) protocol.Range {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FstabField string
|
||||||
|
|
||||||
|
const (
|
||||||
|
FstabFieldSpec FstabField = "spec"
|
||||||
|
FstabFieldMountPoint FstabField = "mountpoint"
|
||||||
|
FstabFieldFileSystemType FstabField = "filesystemtype"
|
||||||
|
FstabFieldOptions FstabField = "options"
|
||||||
|
FstabFieldFreq FstabField = "freq"
|
||||||
|
FstabFieldPass FstabField = "pass"
|
||||||
|
)
|
||||||
|
|
||||||
type FstabFields struct {
|
type FstabFields struct {
|
||||||
Spec *Field
|
Spec *Field
|
||||||
MountPoint *Field
|
MountPoint *Field
|
||||||
@ -146,6 +157,30 @@ func (e *FstabEntry) CheckIsValid() []protocol.Diagnostic {
|
|||||||
return diagnostics
|
return diagnostics
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e FstabEntry) GetFieldAtPosition(cursor uint32) FstabField {
|
||||||
|
if e.Fields.Spec == nil || (cursor >= e.Fields.Spec.Start && cursor <= e.Fields.Spec.End) {
|
||||||
|
return FstabFieldSpec
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.Fields.MountPoint == nil || (cursor >= e.Fields.MountPoint.Start && cursor <= e.Fields.MountPoint.End) {
|
||||||
|
return FstabFieldMountPoint
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.Fields.FilesystemType == nil || (cursor >= e.Fields.FilesystemType.Start && cursor <= e.Fields.FilesystemType.End) {
|
||||||
|
return FstabFieldFileSystemType
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.Fields.Options == nil || (cursor >= e.Fields.Options.Start && cursor <= e.Fields.Options.End) {
|
||||||
|
return FstabFieldOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.Fields.Freq == nil || (cursor >= e.Fields.Freq.Start && cursor <= e.Fields.Freq.End) {
|
||||||
|
return FstabFieldFreq
|
||||||
|
}
|
||||||
|
|
||||||
|
return FstabFieldPass
|
||||||
|
}
|
||||||
|
|
||||||
type FstabParser struct {
|
type FstabParser struct {
|
||||||
entries []FstabEntry
|
entries []FstabEntry
|
||||||
}
|
}
|
||||||
@ -157,83 +192,83 @@ func (p *FstabParser) AddLine(line string, lineNumber int) error {
|
|||||||
return MalformedLineError{}
|
return MalformedLineError{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var spec Field
|
var spec *Field
|
||||||
var mountPoint Field
|
var mountPoint *Field
|
||||||
var filesystemType Field
|
var filesystemType *Field
|
||||||
var options Field
|
var options *Field
|
||||||
var freq Field
|
var freq *Field
|
||||||
var pass Field
|
var pass *Field
|
||||||
|
|
||||||
switch len(fields) {
|
switch len(fields) {
|
||||||
case 6:
|
case 6:
|
||||||
value := fields[5]
|
value := fields[5]
|
||||||
start := uint32(strings.Index(line, value))
|
start := uint32(strings.Index(line, value))
|
||||||
pass = Field{
|
pass = &Field{
|
||||||
Value: fields[5],
|
Value: fields[5],
|
||||||
Start: start,
|
Start: start,
|
||||||
End: start + uint32(len(value)),
|
End: start + uint32(len(value)) - 1,
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
case 5:
|
case 5:
|
||||||
value := fields[4]
|
value := fields[4]
|
||||||
start := uint32(strings.Index(line, value))
|
start := uint32(strings.Index(line, value))
|
||||||
|
|
||||||
freq = Field{
|
freq = &Field{
|
||||||
Value: value,
|
Value: value,
|
||||||
Start: start,
|
Start: start,
|
||||||
End: start + uint32(len(value)),
|
End: start + uint32(len(value)) - 1,
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
case 4:
|
case 4:
|
||||||
value := fields[3]
|
value := fields[3]
|
||||||
start := uint32(strings.Index(line, value))
|
start := uint32(strings.Index(line, value))
|
||||||
|
|
||||||
options = Field{
|
options = &Field{
|
||||||
Value: value,
|
Value: value,
|
||||||
Start: start,
|
Start: start,
|
||||||
End: start + uint32(len(value)),
|
End: start + uint32(len(value)) - 1,
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
case 3:
|
case 3:
|
||||||
value := fields[2]
|
value := fields[2]
|
||||||
start := uint32(strings.Index(line, value))
|
start := uint32(strings.Index(line, value))
|
||||||
|
|
||||||
filesystemType = Field{
|
filesystemType = &Field{
|
||||||
Value: value,
|
Value: value,
|
||||||
Start: start,
|
Start: start,
|
||||||
End: start + uint32(len(value)),
|
End: start + uint32(len(value)) - 1,
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
case 2:
|
case 2:
|
||||||
value := fields[1]
|
value := fields[1]
|
||||||
start := uint32(strings.Index(line, value))
|
start := uint32(strings.Index(line, value))
|
||||||
|
|
||||||
mountPoint = Field{
|
mountPoint = &Field{
|
||||||
Value: value,
|
Value: value,
|
||||||
Start: start,
|
Start: start,
|
||||||
End: start + uint32(len(value)),
|
End: start + uint32(len(value)) - 1,
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
case 1:
|
case 1:
|
||||||
value := fields[0]
|
value := fields[0]
|
||||||
start := uint32(strings.Index(line, value))
|
start := uint32(strings.Index(line, value))
|
||||||
|
|
||||||
spec = Field{
|
spec = &Field{
|
||||||
Value: value,
|
Value: value,
|
||||||
Start: start,
|
Start: start,
|
||||||
End: start + uint32(len(value)),
|
End: start + uint32(len(value)) - 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
entry := FstabEntry{
|
entry := FstabEntry{
|
||||||
Line: uint32(lineNumber),
|
Line: uint32(lineNumber),
|
||||||
Fields: FstabFields{
|
Fields: FstabFields{
|
||||||
Spec: &spec,
|
Spec: spec,
|
||||||
MountPoint: &mountPoint,
|
MountPoint: mountPoint,
|
||||||
FilesystemType: &filesystemType,
|
FilesystemType: filesystemType,
|
||||||
Options: &options,
|
Options: options,
|
||||||
Freq: &freq,
|
Freq: freq,
|
||||||
Pass: &pass,
|
Pass: pass,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
p.entries = append(p.entries, entry)
|
p.entries = append(p.entries, entry)
|
||||||
@ -263,7 +298,7 @@ func (p *FstabParser) ParseFromContent(content string) []common.ParseError {
|
|||||||
return errors
|
return errors
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *FstabParser) GetEntry(line uint32) (FstabEntry, bool) {
|
func (p *FstabParser) GetEntry(line uint32) (*FstabEntry, bool) {
|
||||||
index, found := slices.BinarySearchFunc(p.entries, line, func(entry FstabEntry, line uint32) int {
|
index, found := slices.BinarySearchFunc(p.entries, line, func(entry FstabEntry, line uint32) int {
|
||||||
if entry.Line < line {
|
if entry.Line < line {
|
||||||
return -1
|
return -1
|
||||||
@ -277,10 +312,10 @@ func (p *FstabParser) GetEntry(line uint32) (FstabEntry, bool) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
return FstabEntry{}, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.entries[index], true
|
return &p.entries[index], true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *FstabParser) Clear() {
|
func (p *FstabParser) Clear() {
|
||||||
|
102
handlers/fstab/text-document-completion.go
Normal file
102
handlers/fstab/text-document-completion.go
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
package fstab
|
||||||
|
|
||||||
|
import (
|
||||||
|
docvalues "config-lsp/doc-values"
|
||||||
|
fstabdocumentation "config-lsp/handlers/fstab/documentation"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/tliron/glsp"
|
||||||
|
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TextDocumentCompletion(context *glsp.Context, params *protocol.CompletionParams) (any, error) {
|
||||||
|
parser := documentParserMap[params.TextDocument.URI]
|
||||||
|
|
||||||
|
entry, found := parser.GetEntry(params.Position.Line)
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
// Empty line, return spec completions
|
||||||
|
return fstabdocumentation.SpecField.FetchCompletions(
|
||||||
|
"",
|
||||||
|
params.Position.Character,
|
||||||
|
), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor := params.Position.Character
|
||||||
|
targetField := entry.GetFieldAtPosition(cursor - 1)
|
||||||
|
|
||||||
|
println("cursor at", cursor, "target field", targetField)
|
||||||
|
|
||||||
|
switch targetField {
|
||||||
|
case FstabFieldSpec:
|
||||||
|
value, cursor := GetFieldSafely(entry.Fields.Spec, cursor)
|
||||||
|
|
||||||
|
return fstabdocumentation.SpecField.FetchCompletions(
|
||||||
|
value,
|
||||||
|
cursor,
|
||||||
|
), nil
|
||||||
|
case FstabFieldMountPoint:
|
||||||
|
value, cursor := GetFieldSafely(entry.Fields.MountPoint, cursor)
|
||||||
|
|
||||||
|
return fstabdocumentation.MountPointField.FetchCompletions(
|
||||||
|
value,
|
||||||
|
cursor,
|
||||||
|
), nil
|
||||||
|
case FstabFieldFileSystemType:
|
||||||
|
println(fmt.Sprintf("file system type: %s", entry.Fields.FilesystemType))
|
||||||
|
value, cursor := GetFieldSafely(entry.Fields.FilesystemType, cursor)
|
||||||
|
println("CURSOR", cursor)
|
||||||
|
|
||||||
|
return fstabdocumentation.FileSystemTypeField.FetchCompletions(
|
||||||
|
value,
|
||||||
|
cursor,
|
||||||
|
), nil
|
||||||
|
case FstabFieldOptions:
|
||||||
|
fileSystemType := entry.Fields.FilesystemType.Value
|
||||||
|
|
||||||
|
var optionsField docvalues.Value
|
||||||
|
|
||||||
|
if foundField, found := fstabdocumentation.MountOptionsMapField[fileSystemType]; found {
|
||||||
|
optionsField = foundField
|
||||||
|
} else {
|
||||||
|
optionsField = fstabdocumentation.DefaultMountOptionsField
|
||||||
|
}
|
||||||
|
|
||||||
|
value, cursor := GetFieldSafely(entry.Fields.Options, cursor)
|
||||||
|
|
||||||
|
return optionsField.FetchCompletions(
|
||||||
|
value,
|
||||||
|
cursor,
|
||||||
|
), nil
|
||||||
|
case FstabFieldFreq:
|
||||||
|
value, cursor := GetFieldSafely(entry.Fields.Freq, cursor)
|
||||||
|
|
||||||
|
return fstabdocumentation.FreqField.FetchCompletions(
|
||||||
|
value,
|
||||||
|
cursor,
|
||||||
|
), nil
|
||||||
|
case FstabFieldPass:
|
||||||
|
value, cursor := GetFieldSafely(entry.Fields.Pass, cursor)
|
||||||
|
|
||||||
|
return fstabdocumentation.PassField.FetchCompletions(
|
||||||
|
value,
|
||||||
|
cursor,
|
||||||
|
), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Safely get value and new cursor position
|
||||||
|
// If field is nil, return empty string and 0
|
||||||
|
func GetFieldSafely(field *Field, character uint32) (string, uint32) {
|
||||||
|
if field == nil {
|
||||||
|
return "", 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if field.Value == "" {
|
||||||
|
return "", 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return field.Value, character - field.Start
|
||||||
|
}
|
@ -15,7 +15,6 @@ func TextDocumentDidOpen(
|
|||||||
common.ClearDiagnostics(context, params.TextDocument.URI)
|
common.ClearDiagnostics(context, params.TextDocument.URI)
|
||||||
|
|
||||||
parser := FstabParser{}
|
parser := FstabParser{}
|
||||||
|
|
||||||
documentParserMap[params.TextDocument.URI] = &parser
|
documentParserMap[params.TextDocument.URI] = &parser
|
||||||
|
|
||||||
errors := parser.ParseFromContent(params.TextDocument.Text)
|
errors := parser.ParseFromContent(params.TextDocument.Text)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user