From 4b2b2c36243cfb8502a62f55b82ad70c380c2680 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Mon, 5 Aug 2024 23:01:04 +0200 Subject: [PATCH 1/5] Add more mount options to common-documentation Related to #1 Add documentation for adfs, affs, and debugfs filesystem mount options. * **common-documentation/filesystems/mountoptions/adfs.go** - Add documentation for adfs filesystem options including uid, gid, ownmask, and othmask. * **common-documentation/filesystems/mountoptions/affs.go** - Add documentation for affs filesystem options including uid, gid, setuid, setgid, mode, and other options. * **common-documentation/filesystems/mountoptions/debugfs.go** - Add documentation for debugfs filesystem options including uid, gid, and mode. * **handlers/fstab/documentation/documentation-mountoptions.go** - Update to include the new mount options for adfs, affs, and debugfs filesystems. - Add entries for adfs, affs, and debugfs in the `MountOptionsMapField`. * **common.go** - Add common constants like "zero" to common-documentation/filesystems/mountoptions/common.go. --- .../filesystems/mountoptions/adfs.go | 22 +++++ .../filesystems/mountoptions/affs.go | 82 +++++++++++++++++++ .../filesystems/mountoptions/debugfs.go | 18 ++++ common.go | 3 + .../documentation-mountoptions.go | 31 +++---- 5 files changed, 137 insertions(+), 19 deletions(-) create mode 100644 common-documentation/filesystems/mountoptions/adfs.go create mode 100644 common-documentation/filesystems/mountoptions/affs.go create mode 100644 common-documentation/filesystems/mountoptions/debugfs.go create mode 100644 common.go diff --git a/common-documentation/filesystems/mountoptions/adfs.go b/common-documentation/filesystems/mountoptions/adfs.go new file mode 100644 index 0000000..7b4a489 --- /dev/null +++ b/common-documentation/filesystems/mountoptions/adfs.go @@ -0,0 +1,22 @@ +package commondocumentation + +import docvalues "config-lsp/doc-values" + +var AdfsDocumentationAssignable = map[docvalues.EnumString]docvalues.Value{ + docvalues.CreateEnumStringWithDoc( + "uid", + "Set the owner of the files in the filesystem (default: uid=0).", + ): docvalues.PositiveNumbeValue(), + docvalues.CreateEnumStringWithDoc( + "gid", + "Set the group of the files in the filesystem (default: gid=0).", + ): docvalues.PositiveNumbeValue(), + docvalues.CreateEnumStringWithDoc( + "ownmask", + "Set the permission mask for ADFS 'owner' permissions (default: 0700).", + ): docvalues.StringValue{}, + docvalues.CreateEnumStringWithDoc( + "othmask", + "Set the permission mask for ADFS 'other' permissions (default: 0077).", + ): docvalues.StringValue{}, +} diff --git a/common-documentation/filesystems/mountoptions/affs.go b/common-documentation/filesystems/mountoptions/affs.go new file mode 100644 index 0000000..5731a12 --- /dev/null +++ b/common-documentation/filesystems/mountoptions/affs.go @@ -0,0 +1,82 @@ +package commondocumentation + +import docvalues "config-lsp/doc-values" + +var AffsDocumentationAssignable = map[docvalues.EnumString]docvalues.Value{ + docvalues.CreateEnumStringWithDoc( + "uid", + "Set the owner and group of the root of the filesystem (default: uid=gid=0, but with option uid or gid without specified value, the UID and GID of the current process are taken).", + ): docvalues.NumberValue{Min: &zero}, + docvalues.CreateEnumStringWithDoc( + "gid", + "Set the owner and group of the root of the filesystem (default: uid=gid=0, but with option uid or gid without specified value, the UID and GID of the current process are taken).", + ): docvalues.NumberValue{Min: &zero}, + docvalues.CreateEnumStringWithDoc( + "setuid", + "Set the owner of all files.", + ): docvalues.NumberValue{Min: &zero}, + docvalues.CreateEnumStringWithDoc( + "setgid", + "Set the group of all files.", + ): docvalues.NumberValue{Min: &zero}, + docvalues.CreateEnumStringWithDoc( + "mode", + "Set the mode of all files to value & 0777 disregarding the original permissions. Add search permission to directories that have read permission. The value is given in octal.", + ): docvalues.StringValue{}, + docvalues.CreateEnumStringWithDoc( + "protect", + "Do not allow any changes to the protection bits on the filesystem.", + ): docvalues.StringValue{}, + docvalues.CreateEnumStringWithDoc( + "usemp", + "Set UID and GID of the root of the filesystem to the UID and GID of the mount point upon the first sync or umount, and then clear this option. Strange...", + ): docvalues.StringValue{}, + docvalues.CreateEnumStringWithDoc( + "verbose", + "Print an informational message for each successful mount.", + ): docvalues.StringValue{}, + docvalues.CreateEnumStringWithDoc( + "prefix", + "Prefix used before volume name, when following a link.", + ): docvalues.StringValue{}, + docvalues.CreateEnumStringWithDoc( + "volume", + "Prefix (of length at most 30) used before '/' when following a symbolic link.", + ): docvalues.StringValue{}, + docvalues.CreateEnumStringWithDoc( + "reserved", + "(Default: 2.) Number of unused blocks at the start of the device.", + ): docvalues.NumberValue{Min: &zero}, + docvalues.CreateEnumStringWithDoc( + "root", + "Give explicitly the location of the root block.", + ): docvalues.NumberValue{Min: &zero}, + docvalues.CreateEnumStringWithDoc( + "bs", + "Give blocksize. Allowed values are 512, 1024, 2048, 4096.", + ): docvalues.EnumValue{ + EnforceValues: true, + Values: []docvalues.EnumString{ + docvalues.CreateEnumString("512"), + docvalues.CreateEnumString("1024"), + docvalues.CreateEnumString("2048"), + docvalues.CreateEnumString("4096"), + }, + }, + docvalues.CreateEnumStringWithDoc( + "grpquota", + "These options are accepted but ignored. (However, quota utilities may react to such strings in /etc/fstab.)", + ): docvalues.StringValue{}, + docvalues.CreateEnumStringWithDoc( + "noquota", + "These options are accepted but ignored. (However, quota utilities may react to such strings in /etc/fstab.)", + ): docvalues.StringValue{}, + docvalues.CreateEnumStringWithDoc( + "quota", + "These options are accepted but ignored. (However, quota utilities may react to such strings in /etc/fstab.)", + ): docvalues.StringValue{}, + docvalues.CreateEnumStringWithDoc( + "usrquota", + "These options are accepted but ignored. (However, quota utilities may react to such strings in /etc/fstab.)", + ): docvalues.StringValue{}, +} diff --git a/common-documentation/filesystems/mountoptions/debugfs.go b/common-documentation/filesystems/mountoptions/debugfs.go new file mode 100644 index 0000000..b698fc6 --- /dev/null +++ b/common-documentation/filesystems/mountoptions/debugfs.go @@ -0,0 +1,18 @@ +package commondocumentation + +import docvalues "config-lsp/doc-values" + +var DebugfsDocumentationAssignable = map[docvalues.EnumString]docvalues.Value{ + docvalues.CreateEnumStringWithDoc( + "uid", + "Set the owner of the mountpoint.", + ): docvalues.NumberValue{Min: &zero}, + docvalues.CreateEnumStringWithDoc( + "gid", + "Set the group of the mountpoint.", + ): docvalues.NumberValue{Min: &zero}, + docvalues.CreateEnumStringWithDoc( + "mode", + "Sets the mode of the mountpoint.", + ): docvalues.StringValue{}, +} diff --git a/common.go b/common.go new file mode 100644 index 0000000..63b4710 --- /dev/null +++ b/common.go @@ -0,0 +1,3 @@ +package commondocumentation + +var zero = 0 diff --git a/handlers/fstab/documentation/documentation-mountoptions.go b/handlers/fstab/documentation/documentation-mountoptions.go index fe3018a..40d0a6e 100644 --- a/handlers/fstab/documentation/documentation-mountoptions.go +++ b/handlers/fstab/documentation/documentation-mountoptions.go @@ -245,25 +245,18 @@ func createMountOptionField( var DefaultMountOptionsField = createMountOptionField([]docvalues.EnumString{}, map[docvalues.EnumString]docvalues.Value{}) var MountOptionsMapField = map[string]docvalues.Value{ - // "adfs": createMountOptionField( - // []docvalues.EnumString{}, - // map[string]commondocumentation.AssignableOption{ - // "uid": { - // Documentation: "Set the owner of the files in the filesystem", - // Handler: func(context docvalues.KeyValueAssignmentContext) docvalues.Value { - // min := 0 - // return docvalues.NumberValue{Min: &min} - // }, - // }, - // "gid": { - // Documentation: "Set the group of the files in the filesystem", - // Handler: func(context docvalues.KeyValueAssignmentContext) docvalues.Value { - // min := 0 - // return docvalues.NumberValue{Min: &min} - // }, - // }, - // }, - // ), + "adfs": createMountOptionField( + []docvalues.EnumString{}, + commondocumentation.AdfsDocumentationAssignable, + ), + "affs": createMountOptionField( + []docvalues.EnumString{}, + commondocumentation.AffsDocumentationAssignable, + ), + "debugfs": createMountOptionField( + []docvalues.EnumString{}, + commondocumentation.DebugfsDocumentationAssignable, + ), "ext2": createMountOptionField( commondocumentation.Ext2DocumentationEnums, commondocumentation.Ext2DocumentationAssignable, From 4d4d8a137657c4ff6d181ada3c3cd2df1d42e44e Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Wed, 7 Aug 2024 22:34:33 +0200 Subject: [PATCH 2/5] chore: Add more documentation --- .../filesystems/mountoptions/adfs.go | 10 ++++- .../filesystems/mountoptions/affs.go | 43 +++++++++++-------- .../filesystems/mountoptions/debugfs.go | 10 ++++- 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/common-documentation/filesystems/mountoptions/adfs.go b/common-documentation/filesystems/mountoptions/adfs.go index 7b4a489..cccb4b2 100644 --- a/common-documentation/filesystems/mountoptions/adfs.go +++ b/common-documentation/filesystems/mountoptions/adfs.go @@ -6,11 +6,15 @@ var AdfsDocumentationAssignable = map[docvalues.EnumString]docvalues.Value{ docvalues.CreateEnumStringWithDoc( "uid", "Set the owner of the files in the filesystem (default: uid=0).", - ): docvalues.PositiveNumbeValue(), + ): docvalues.UIDValue{ + EnforceUsingExisting: true, + }, docvalues.CreateEnumStringWithDoc( "gid", "Set the group of the files in the filesystem (default: gid=0).", - ): docvalues.PositiveNumbeValue(), + ): docvalues.GIDValue{ + EnforceUsingExisting: true, + }, docvalues.CreateEnumStringWithDoc( "ownmask", "Set the permission mask for ADFS 'owner' permissions (default: 0700).", @@ -20,3 +24,5 @@ var AdfsDocumentationAssignable = map[docvalues.EnumString]docvalues.Value{ "Set the permission mask for ADFS 'other' permissions (default: 0077).", ): docvalues.StringValue{}, } + +var AdfsDocumentationEnums = []docvalues.EnumString{} diff --git a/common-documentation/filesystems/mountoptions/affs.go b/common-documentation/filesystems/mountoptions/affs.go index 5731a12..1a0f6e6 100644 --- a/common-documentation/filesystems/mountoptions/affs.go +++ b/common-documentation/filesystems/mountoptions/affs.go @@ -2,39 +2,33 @@ package commondocumentation import docvalues "config-lsp/doc-values" +var prefixMaxLength = uint32(30) + var AffsDocumentationAssignable = map[docvalues.EnumString]docvalues.Value{ docvalues.CreateEnumStringWithDoc( "uid", "Set the owner and group of the root of the filesystem (default: uid=gid=0, but with option uid or gid without specified value, the UID and GID of the current process are taken).", - ): docvalues.NumberValue{Min: &zero}, + ): docvalues.UIDValue{ + EnforceUsingExisting: true, + }, docvalues.CreateEnumStringWithDoc( "gid", "Set the owner and group of the root of the filesystem (default: uid=gid=0, but with option uid or gid without specified value, the UID and GID of the current process are taken).", - ): docvalues.NumberValue{Min: &zero}, + ): docvalues.GIDValue{ + EnforceUsingExisting: true, + }, docvalues.CreateEnumStringWithDoc( "setuid", "Set the owner of all files.", - ): docvalues.NumberValue{Min: &zero}, + ): docvalues.StringValue{}, docvalues.CreateEnumStringWithDoc( "setgid", "Set the group of all files.", - ): docvalues.NumberValue{Min: &zero}, + ): docvalues.StringValue{}, docvalues.CreateEnumStringWithDoc( "mode", "Set the mode of all files to value & 0777 disregarding the original permissions. Add search permission to directories that have read permission. The value is given in octal.", ): docvalues.StringValue{}, - docvalues.CreateEnumStringWithDoc( - "protect", - "Do not allow any changes to the protection bits on the filesystem.", - ): docvalues.StringValue{}, - docvalues.CreateEnumStringWithDoc( - "usemp", - "Set UID and GID of the root of the filesystem to the UID and GID of the mount point upon the first sync or umount, and then clear this option. Strange...", - ): docvalues.StringValue{}, - docvalues.CreateEnumStringWithDoc( - "verbose", - "Print an informational message for each successful mount.", - ): docvalues.StringValue{}, docvalues.CreateEnumStringWithDoc( "prefix", "Prefix used before volume name, when following a link.", @@ -42,7 +36,7 @@ var AffsDocumentationAssignable = map[docvalues.EnumString]docvalues.Value{ docvalues.CreateEnumStringWithDoc( "volume", "Prefix (of length at most 30) used before '/' when following a symbolic link.", - ): docvalues.StringValue{}, + ): docvalues.StringValue{MaxLength: &prefixMaxLength}, docvalues.CreateEnumStringWithDoc( "reserved", "(Default: 2.) Number of unused blocks at the start of the device.", @@ -80,3 +74,18 @@ var AffsDocumentationAssignable = map[docvalues.EnumString]docvalues.Value{ "These options are accepted but ignored. (However, quota utilities may react to such strings in /etc/fstab.)", ): docvalues.StringValue{}, } + +var AffsDocumentationEnums = []docvalues.EnumString{ + docvalues.CreateEnumStringWithDoc( + "protect", + "Do not allow any changes to the protection bits on the filesystem.", + ), + docvalues.CreateEnumStringWithDoc( + "usemp", + "Set UID and GID of the root of the filesystem to the UID and GID of the mount point upon the first sync or umount, and then clear this option. Strange...", + ), + docvalues.CreateEnumStringWithDoc( + "verbose", + "Print an informational message for each successful mount.", + ), +} diff --git a/common-documentation/filesystems/mountoptions/debugfs.go b/common-documentation/filesystems/mountoptions/debugfs.go index b698fc6..c425e8f 100644 --- a/common-documentation/filesystems/mountoptions/debugfs.go +++ b/common-documentation/filesystems/mountoptions/debugfs.go @@ -6,13 +6,19 @@ var DebugfsDocumentationAssignable = map[docvalues.EnumString]docvalues.Value{ docvalues.CreateEnumStringWithDoc( "uid", "Set the owner of the mountpoint.", - ): docvalues.NumberValue{Min: &zero}, + ): docvalues.UIDValue{ + EnforceUsingExisting: true, + }, docvalues.CreateEnumStringWithDoc( "gid", "Set the group of the mountpoint.", - ): docvalues.NumberValue{Min: &zero}, + ): docvalues.GIDValue{ + EnforceUsingExisting: true, + }, docvalues.CreateEnumStringWithDoc( "mode", "Sets the mode of the mountpoint.", ): docvalues.StringValue{}, } + +var DebugfsDocumentationEnums = []docvalues.EnumString{} From 4aa54ffcc1e760bd277ab5587f5f3cdae5f4f1bc Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Wed, 7 Aug 2024 22:34:59 +0200 Subject: [PATCH 3/5] fix(doc-values): Overall improvements --- doc-values/extra-values.go | 6 ++ doc-values/utils.go | 2 +- doc-values/value-array.go | 4 +- doc-values/value-enum.go | 11 ++ doc-values/value-gid.go | 128 +++++++++++++++++++++++ doc-values/value-key-enum-assignment.go | 14 ++- doc-values/value-or.go | 21 ++++ doc-values/value-power-of-two.go | 2 +- doc-values/value-regex.go | 9 +- doc-values/value-string.go | 18 +++- doc-values/value-uid.go | 129 ++++++++++++++++++++++++ 11 files changed, 332 insertions(+), 12 deletions(-) create mode 100644 doc-values/value-gid.go create mode 100644 doc-values/value-uid.go diff --git a/doc-values/extra-values.go b/doc-values/extra-values.go index 4b224f2..3a47e9c 100644 --- a/doc-values/extra-values.go +++ b/doc-values/extra-values.go @@ -159,6 +159,12 @@ func PositiveNumberValue() Value { } } +func MaskValue() Value { + min := 0 + max := 777 + return NumberValue{Min: &min, Max: &max} +} + func SingleEnumValue(value string) EnumValue { return EnumValue{ EnforceValues: true, diff --git a/doc-values/utils.go b/doc-values/utils.go index 772e215..68e7326 100644 --- a/doc-values/utils.go +++ b/doc-values/utils.go @@ -29,7 +29,7 @@ func MergeKeyEnumAssignmentMaps(maps ...map[EnumString]Value) map[EnumString]Val for _, m := range maps { for key, value := range m { - if _, ok := existingEnums[key.InsertText]; !ok { + if _, ok := existingEnums[key.InsertText]; ok { continue } diff --git a/doc-values/value-array.go b/doc-values/value-array.go index 23fc486..94a59ff 100644 --- a/doc-values/value-array.go +++ b/doc-values/value-array.go @@ -122,8 +122,8 @@ func (v ArrayValue) FetchCompletions(line string, cursor uint32) []protocol.Comp relativePosition, found := utils.FindPreviousCharacter(line, v.Separator, int(cursor-1)) if found { - line = line[uint32(relativePosition):] - cursor -= uint32(relativePosition) + line = line[uint32(relativePosition+1):] + cursor -= uint32(relativePosition + 1) } return v.SubValue.FetchCompletions(line, cursor) diff --git a/doc-values/value-enum.go b/doc-values/value-enum.go index b180bf9..8e5cd98 100644 --- a/doc-values/value-enum.go +++ b/doc-values/value-enum.go @@ -30,6 +30,17 @@ type EnumString struct { Documentation string } +func (v EnumString) ToCompletionItem() protocol.CompletionItem { + textFormat := protocol.InsertTextFormatPlainText + kind := protocol.CompletionItemKindEnum + return protocol.CompletionItem{ + Label: v.InsertText, + InsertTextFormat: &textFormat, + Kind: &kind, + Documentation: &v.Documentation, + } +} + func CreateEnumString(value string) EnumString { return EnumString{ InsertText: value, diff --git a/doc-values/value-gid.go b/doc-values/value-gid.go new file mode 100644 index 0000000..5fca78c --- /dev/null +++ b/doc-values/value-gid.go @@ -0,0 +1,128 @@ +package docvalues + +import ( + "config-lsp/utils" + "strconv" + + protocol "github.com/tliron/glsp/protocol_3_16" +) + +type GIDNotInPasswdErr struct{} + +func (e GIDNotInPasswdErr) Error() string { + return "This UID does not exist" +} + +type InvalidGIDError struct{} + +func (e InvalidGIDError) Error() string { + return "This UID is invalid" +} + +type GIDNotInRangeError struct{} + +func (e GIDNotInRangeError) Error() string { + return "UIDs must be between 0 and 65535" +} + +type GIDValue struct { + EnforceUsingExisting bool +} + +func (v GIDValue) GetTypeDescription() []string { + return []string{"Group ID"} +} + +func (v GIDValue) CheckIsValid(value string) []*InvalidValue { + uid, err := strconv.Atoi(value) + + if err != nil { + return []*InvalidValue{{ + Err: InvalidGIDError{}, + Start: 0, + End: uint32(len(value)), + }} + } + + if uid < 0 || uid > 65535 { + return []*InvalidValue{{ + Err: GIDNotInRangeError{}, + Start: 0, + End: uint32(len(value)), + }} + } + + if v.EnforceUsingExisting { + infos, err := fetchPasswdInfo() + + if err != nil { + return []*InvalidValue{} + } + + found := false + + for _, info := range infos { + if info.GID == value { + found = true + break + } + } + + if !found { + return []*InvalidValue{{ + Err: GIDNotInPasswdErr{}, + Start: 0, + End: uint32(len(value)), + }} + } + } + + return []*InvalidValue{} +} + +var defaultGIDsExplanation = []EnumString{ + { + InsertText: "0", + DescriptionText: "root", + Documentation: "The group of the root user", + }, +} + +func (v GIDValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem { + infos, err := fetchGroupInfo() + + if err != nil { + return utils.Map(defaultUIDsExplanation, func(enum EnumString) protocol.CompletionItem { + return enum.ToCompletionItem() + }) + } + + textFormat := protocol.InsertTextFormatPlainText + kind := protocol.CompletionItemKindValue + completions := make([]protocol.CompletionItem, len(infos)) + + for index, info := range infos { + // Find default gids + var existingGID *EnumString + + for _, defaultGID := range defaultUIDsExplanation { + if defaultGID.InsertText == info.GID { + existingGID = &defaultGID + break + } + } + + if existingGID != nil { + completions[index] = existingGID.ToCompletionItem() + } else { + completions[index] = protocol.CompletionItem{ + InsertTextFormat: &textFormat, + Kind: &kind, + InsertText: &info.GID, + Documentation: info.Name, + } + } + } + + return completions +} diff --git a/doc-values/value-key-enum-assignment.go b/doc-values/value-key-enum-assignment.go index 226583d..3f69a13 100644 --- a/doc-values/value-key-enum-assignment.go +++ b/doc-values/value-key-enum-assignment.go @@ -111,13 +111,23 @@ func (v KeyEnumAssignmentValue) FetchEnumCompletions() []protocol.CompletionItem for enumKey := range v.Values { textFormat := protocol.InsertTextFormatPlainText - kind := protocol.CompletionItemKindEnum + kind := protocol.CompletionItemKindField + val := v.Values[enumKey] + description := val.GetTypeDescription() + + var documentation string + + if len(description) == 1 { + documentation = fmt.Sprintf("%s%s<%s> \n\n%s", enumKey.InsertText, v.Separator, description[0], enumKey.Documentation) + } else { + documentation = fmt.Sprintf("%s%s \n\n%s", enumKey.InsertText, v.Separator, enumKey.Documentation) + } completions = append(completions, protocol.CompletionItem{ Label: enumKey.InsertText, InsertTextFormat: &textFormat, Kind: &kind, - Documentation: &enumKey.Documentation, + Documentation: documentation, }) } diff --git a/doc-values/value-or.go b/doc-values/value-or.go index 296d7eb..0e9a6e5 100644 --- a/doc-values/value-or.go +++ b/doc-values/value-or.go @@ -1,6 +1,7 @@ package docvalues import ( + "config-lsp/utils" "strings" protocol "github.com/tliron/glsp/protocol_3_16" @@ -49,6 +50,26 @@ func (v OrValue) CheckIsValid(value string) []*InvalidValue { return errors } func (v OrValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem { + // Check for special cases + if len(v.Values) == 2 { + switch v.Values[0].(type) { + case KeyEnumAssignmentValue: + if cursor > 0 { + // KeyEnumAssignment + other values + // If there is an separator, we only want to show + // the values of the KeyEnumAssignment + keyEnumValue := v.Values[0].(KeyEnumAssignmentValue) + + println("line eta cursor", line, cursor) + _, found := utils.FindPreviousCharacter(line, keyEnumValue.Separator, int(cursor-1)) + + if found { + return keyEnumValue.FetchCompletions(line, cursor) + } + } + } + } + completions := make([]protocol.CompletionItem, 0) for _, subValue := range v.Values { diff --git a/doc-values/value-power-of-two.go b/doc-values/value-power-of-two.go index 8cf1d12..75bba30 100644 --- a/doc-values/value-power-of-two.go +++ b/doc-values/value-power-of-two.go @@ -62,7 +62,7 @@ var powers = []int{1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 func (v PowerOfTwoValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem { textFormat := protocol.InsertTextFormatPlainText - kind := protocol.CompletionItemKindEnum + kind := protocol.CompletionItemKindValue return utils.Map( powers, diff --git a/doc-values/value-regex.go b/doc-values/value-regex.go index 2d5fbfc..2be9481 100644 --- a/doc-values/value-regex.go +++ b/doc-values/value-regex.go @@ -26,16 +26,15 @@ func (v RegexValue) GetTypeDescription() []string { } func (v RegexValue) CheckIsValid(value string) []*InvalidValue { - if value == "" { + if !v.Regex.MatchString(value) { return []*InvalidValue{{ - Err: EmptyStringError{}, + Err: RegexInvalidError{Regex: v.Regex.String()}, Start: 0, End: uint32(len(value)), - }, - } + }} } - return nil + return []*InvalidValue{} } func (v RegexValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem { diff --git a/doc-values/value-string.go b/doc-values/value-string.go index f5f8b7c..67b163e 100644 --- a/doc-values/value-string.go +++ b/doc-values/value-string.go @@ -10,7 +10,15 @@ func (e EmptyStringError) Error() string { return "This setting may not be empty" } -type StringValue struct{} +type StringTooLongError struct{} + +func (e StringTooLongError) Error() string { + return "This setting is too long" +} + +type StringValue struct { + MaxLength *uint32 +} func (v StringValue) GetTypeDescription() []string { return []string{"String"} @@ -26,6 +34,14 @@ func (v StringValue) CheckIsValid(value string) []*InvalidValue { } } + if v.MaxLength != nil && uint32(len(value)) > *v.MaxLength { + return []*InvalidValue{{ + Err: StringTooLongError{}, + Start: 0, + End: uint32(len(value)), + }} + } + return nil } diff --git a/doc-values/value-uid.go b/doc-values/value-uid.go new file mode 100644 index 0000000..bfc436e --- /dev/null +++ b/doc-values/value-uid.go @@ -0,0 +1,129 @@ +package docvalues + +import ( + "config-lsp/utils" + "fmt" + "strconv" + + protocol "github.com/tliron/glsp/protocol_3_16" +) + +type UIDNotInPasswdErr struct{} + +func (e UIDNotInPasswdErr) Error() string { + return "This UID does not exist" +} + +type InvalidUIDError struct{} + +func (e InvalidUIDError) Error() string { + return "This UID is invalid" +} + +type UIDNotInRangeError struct{} + +func (e UIDNotInRangeError) Error() string { + return "UIDs must be between 0 and 65535" +} + +type UIDValue struct { + EnforceUsingExisting bool +} + +func (v UIDValue) GetTypeDescription() []string { + return []string{"User ID"} +} + +func (v UIDValue) CheckIsValid(value string) []*InvalidValue { + uid, err := strconv.Atoi(value) + + if err != nil { + return []*InvalidValue{{ + Err: InvalidUIDError{}, + Start: 0, + End: uint32(len(value)), + }} + } + + if uid < 0 || uid > 65535 { + return []*InvalidValue{{ + Err: UIDNotInRangeError{}, + Start: 0, + End: uint32(len(value)), + }} + } + + if v.EnforceUsingExisting { + infos, err := fetchPasswdInfo() + + if err != nil { + return []*InvalidValue{} + } + + found := false + + for _, info := range infos { + if info.UID == value { + found = true + break + } + } + + if !found { + return []*InvalidValue{{ + Err: UIDNotInPasswdErr{}, + Start: 0, + End: uint32(len(value)), + }} + } + } + + return []*InvalidValue{} +} + +var defaultUIDsExplanation = []EnumString{ + { + InsertText: "0", + DescriptionText: "root", + Documentation: "The root user", + }, +} + +func (v UIDValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem { + infos, err := fetchPasswdInfo() + + if err != nil { + return utils.Map(defaultUIDsExplanation, func(enum EnumString) protocol.CompletionItem { + return enum.ToCompletionItem() + }) + } + + textFormat := protocol.InsertTextFormatPlainText + kind := protocol.CompletionItemKindValue + completions := make([]protocol.CompletionItem, len(infos)) + + for index, info := range infos { + // Find default uids + var existingUID *EnumString + + for _, defaultUID := range defaultUIDsExplanation { + if defaultUID.InsertText == info.UID { + existingUID = &defaultUID + break + } + } + + if existingUID != nil { + completions[index] = existingUID.ToCompletionItem() + } else { + completions[index] = protocol.CompletionItem{ + InsertTextFormat: &textFormat, + Kind: &kind, + InsertText: &info.UID, + Documentation: fmt.Sprintf("User %s; Home: %s", info.Name, info.HomePath), + } + } + } + + return completions +} From 54c4f516fe1c9b3aa43ff9e11eebed71c159089d Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Wed, 7 Aug 2024 22:35:30 +0200 Subject: [PATCH 4/5] feat(handlers): Working on the WIP --- .../documentation-mountoptions.go | 6 +- .../fstab/documentation/documentation-type.go | 106 ++---------------- handlers/fstab/text-document-completion.go | 11 +- handlers/openssh/text-document-did-open.go | 2 - 4 files changed, 16 insertions(+), 109 deletions(-) diff --git a/handlers/fstab/documentation/documentation-mountoptions.go b/handlers/fstab/documentation/documentation-mountoptions.go index 40d0a6e..cc17c9d 100644 --- a/handlers/fstab/documentation/documentation-mountoptions.go +++ b/handlers/fstab/documentation/documentation-mountoptions.go @@ -246,15 +246,15 @@ var DefaultMountOptionsField = createMountOptionField([]docvalues.EnumString{}, var MountOptionsMapField = map[string]docvalues.Value{ "adfs": createMountOptionField( - []docvalues.EnumString{}, + commondocumentation.AdfsDocumentationEnums, commondocumentation.AdfsDocumentationAssignable, ), "affs": createMountOptionField( - []docvalues.EnumString{}, + commondocumentation.AffsDocumentationEnums, commondocumentation.AffsDocumentationAssignable, ), "debugfs": createMountOptionField( - []docvalues.EnumString{}, + commondocumentation.DebugfsDocumentationEnums, commondocumentation.DebugfsDocumentationAssignable, ), "ext2": createMountOptionField( diff --git a/handlers/fstab/documentation/documentation-type.go b/handlers/fstab/documentation/documentation-type.go index c159b62..8a6f8f8 100644 --- a/handlers/fstab/documentation/documentation-type.go +++ b/handlers/fstab/documentation/documentation-type.go @@ -1,108 +1,20 @@ package fstabdocumentation -import docvalues "config-lsp/doc-values" +import ( + docvalues "config-lsp/doc-values" + "config-lsp/utils" +) var FileSystemTypeField = docvalues.ArrayValue{ Separator: ",", DuplicatesExtractor: &docvalues.SimpleDuplicatesExtractor, SubValue: docvalues.EnumValue{ EnforceValues: false, - Values: []docvalues.EnumString{ - { - InsertText: "none", - DescriptionText: "none", - Documentation: "An entry _none_ is useful for bind or move mounts.", + Values: utils.Map( + utils.KeysOfMap(MountOptionsMapField), + func(key string) docvalues.EnumString { + return docvalues.CreateEnumString(key) }, - { - InsertText: "swap", - DescriptionText: "swap", - Documentation: "An entry _swap_ denotes a file or partition to be used for swapping, cf. swapon(8)", - }, - { - InsertText: "ext2", - DescriptionText: "ext2", - Documentation: "Mount as ext2 filesystem", - }, - { - InsertText: "ext3", - DescriptionText: "ext3", - Documentation: "Mount as ext2 filesystem", - }, - { - InsertText: "ext4", - DescriptionText: "ext4", - Documentation: "Mount as ext4 filesystem", - }, - { - InsertText: "xfs", - DescriptionText: "xfs", - Documentation: "Mount as xfs filesystem", - }, - { - InsertText: "btrfs", - DescriptionText: "btrfs", - Documentation: "Mount as btrfs filesystem", - }, - { - InsertText: "f2fs", - DescriptionText: "f2fs", - Documentation: "Mount as f2fs filesystem", - }, - { - InsertText: "vfat", - DescriptionText: "vfat", - Documentation: "Mount as vfat filesystem", - }, - { - InsertText: "ntfs", - DescriptionText: "ntfs", - Documentation: "Mount as ntfs filesystem", - }, - { - InsertText: "hfsplus", - DescriptionText: "hfsplus", - Documentation: "Mount as hfsplus filesystem", - }, - { - InsertText: "tmpfs", - DescriptionText: "tmpfs", - Documentation: "Mount as tmpfs filesystem", - }, - { - InsertText: "sysfs", - DescriptionText: "sysfs", - Documentation: "Mount as sysfs filesystem", - }, - { - InsertText: "proc", - DescriptionText: "proc", - Documentation: "Mount as proc filesystem", - }, - { - InsertText: "iso9660", - DescriptionText: "iso9660", - Documentation: "Mount as iso9660 filesystem", - }, - { - InsertText: "udf", - DescriptionText: "udf", - Documentation: "Mount as udf filesystem", - }, - { - InsertText: "squashfs", - DescriptionText: "squashfs", - Documentation: "Mount as squashfs filesystem", - }, - { - InsertText: "nfs", - DescriptionText: "nfs", - Documentation: "Mount as nfs filesystem", - }, - { - InsertText: "cifs", - DescriptionText: "cifs", - Documentation: "Mount as cifs filesystem", - }, - }, + ), }, } diff --git a/handlers/fstab/text-document-completion.go b/handlers/fstab/text-document-completion.go index ff800cf..0378f68 100644 --- a/handlers/fstab/text-document-completion.go +++ b/handlers/fstab/text-document-completion.go @@ -3,7 +3,6 @@ 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" @@ -25,8 +24,6 @@ func TextDocumentCompletion(context *glsp.Context, params *protocol.CompletionPa 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) @@ -43,9 +40,7 @@ func TextDocumentCompletion(context *glsp.Context, params *protocol.CompletionPa 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, @@ -64,10 +59,12 @@ func TextDocumentCompletion(context *glsp.Context, params *protocol.CompletionPa value, cursor := GetFieldSafely(entry.Fields.Options, cursor) - return optionsField.FetchCompletions( + completions := optionsField.FetchCompletions( value, cursor, - ), nil + ) + + return completions, nil case FstabFieldFreq: value, cursor := GetFieldSafely(entry.Fields.Freq, cursor) diff --git a/handlers/openssh/text-document-did-open.go b/handlers/openssh/text-document-did-open.go index 652cfba..7c533e3 100644 --- a/handlers/openssh/text-document-did-open.go +++ b/handlers/openssh/text-document-did-open.go @@ -11,8 +11,6 @@ import ( func TextDocumentDidOpen(context *glsp.Context, params *protocol.DidOpenTextDocumentParams) error { readBytes, err := os.ReadFile(params.TextDocument.URI[len("file://"):]) - println("opened i la language eta", params.TextDocument.LanguageID) - if err != nil { return err } From 0f0797e8f9fe04cb5470a4f785a71a158a0d682b Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Wed, 7 Aug 2024 22:35:41 +0200 Subject: [PATCH 5/5] fix: Remove unwanted changes --- common.go | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 common.go diff --git a/common.go b/common.go deleted file mode 100644 index 63b4710..0000000 --- a/common.go +++ /dev/null @@ -1,3 +0,0 @@ -package commondocumentation - -var zero = 0