feat: Add DataAmountValue; bugfixes

This commit is contained in:
Myzel394 2024-07-31 23:18:52 +02:00
parent 1254ebfd8a
commit ea5d9deaee
No known key found for this signature in database
GPG Key ID: DEC4AAB876F73185
7 changed files with 142 additions and 22 deletions

20
doc-values/utils.go Normal file
View File

@ -0,0 +1,20 @@
package docvalues
import (
"config-lsp/utils"
protocol "github.com/tliron/glsp/protocol_3_16"
)
func GenerateBase10Completions(prefix string) []protocol.CompletionItem {
kind := protocol.CompletionItemKindValue
return utils.Map(
[]string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
func(index string) protocol.CompletionItem {
return protocol.CompletionItem{
Label: prefix + index,
Kind: &kind,
}
},
)
}

View File

@ -22,11 +22,20 @@ type KeyValueAssignmentValue struct {
} }
func (v KeyValueAssignmentValue) GetTypeDescription() []string { func (v KeyValueAssignmentValue) GetTypeDescription() []string {
keyDescription := v.Key.GetTypeDescription()
valueDescription := v.Value.GetTypeDescription()
if len(keyDescription) == 1 && len(valueDescription) == 1 {
return []string{
fmt.Sprintf("Key-Value pair in form of '<%s>%s<%s>'", keyDescription[0], v.Separator, valueDescription[0]),
}
} else {
return []string{ return []string{
fmt.Sprintf("Key-Value pair in form of 'key%svalue'", v.Separator), fmt.Sprintf("Key-Value pair in form of 'key%svalue'", v.Separator),
fmt.Sprintf("#### Key\n%s", strings.Join(v.Key.GetTypeDescription(), "\n")), fmt.Sprintf("#### Key\n%s", strings.Join(v.Key.GetTypeDescription(), "\n")),
fmt.Sprintf("#### Value:\n%s", strings.Join(v.Value.GetTypeDescription(), "\n")), fmt.Sprintf("#### Value:\n%s", strings.Join(v.Value.GetTypeDescription(), "\n")),
} }
}
} }
func (v KeyValueAssignmentValue) CheckIsValid(value string) error { func (v KeyValueAssignmentValue) CheckIsValid(value string) error {

View File

@ -10,7 +10,7 @@ import (
type NotANumberError struct{} type NotANumberError struct{}
func (e NotANumberError) Error() string { func (e NotANumberError) Error() string {
return "This must be number" return "This must be a number"
} }
type NumberNotInRangeError struct { type NumberNotInRangeError struct {

View File

@ -755,7 +755,14 @@ See PATTERNS in ssh_config(5) for more information on patterns. This keyword may
"PubkeyAuthentication": common.NewOption(`Specifies whether public key authentication is allowed. The default is yes.`, "PubkeyAuthentication": common.NewOption(`Specifies whether public key authentication is allowed. The default is yes.`,
BooleanEnumValue, BooleanEnumValue,
), ),
// "RekeyLimit": `Specifies the maximum amount of data that may be transmitted or received before the session key is renegotiated, optionally followed by a maximum amount of time that may pass before the session key is renegotiated. The first argument is specified in bytes and may have a suffix of K, M, or G to indicate Kilobytes, Megabytes, or Gigabytes, respectively. The default is between 1G and 4G, depending on the cipher. The optional second value is specified in seconds and may use any of the units documented in the “TIME FORMATS” section. The default value for RekeyLimit is default none, which means that rekeying is performed after the cipher's default amount of data has been sent or received and no time based rekeying is done.`, "RekeyLimit": common.NewOption(`Specifies the maximum amount of data that may be transmitted or received before the session key is renegotiated, optionally followed by a maximum amount of time that may pass before the session key is renegotiated. The first argument is specified in bytes and may have a suffix of K, M, or G to indicate Kilobytes, Megabytes, or Gigabytes, respectively. The default is between 1G and 4G, depending on the cipher. The optional second value is specified in seconds and may use any of the units documented in the “TIME FORMATS” section. The default value for RekeyLimit is default none, which means that rekeying is performed after the cipher's default amount of data has been sent or received and no time based rekeying is done.`,
docvalues.KeyValueAssignmentValue{
Separator: " ",
ValueIsOptional: true,
Key: DataAmountValue{},
Value: TimeFormatValue{},
},
),
"RequiredRSASize": common.NewOption(`Specifies the minimum RSA key size (in bits) that sshd(8) will accept. User and host-based authentication keys smaller than this limit will be refused. The default is 1024 bits. Note that this limit may only be raised from the default.`, "RequiredRSASize": common.NewOption(`Specifies the minimum RSA key size (in bits) that sshd(8) will accept. User and host-based authentication keys smaller than this limit will be refused. The default is 1024 bits. Note that this limit may only be raised from the default.`,
docvalues.NumberValue{Min: &ZERO}, docvalues.NumberValue{Min: &ZERO},
), ),

View File

@ -0,0 +1,5 @@
package openssh
import "regexp"
var isJustDigitsPattern = regexp.MustCompile(`^\d+$`)

View File

@ -0,0 +1,87 @@
package openssh
import (
docvalues "config-lsp/doc-values"
"fmt"
"regexp"
"strconv"
protocol "github.com/tliron/glsp/protocol_3_16"
)
var dataAmountCheckPattern = regexp.MustCompile(`(?i)^(\d+)([KMG])$`)
type InvalidDataAmountError struct{}
func (e InvalidDataAmountError) Error() string {
return "Data amount is invalid. It must be in the form of: <number>[K|M|G]"
}
type DataAmountValue struct{}
func (v DataAmountValue) GetTypeDescription() []string {
return []string{"Data amount"}
}
func (v DataAmountValue) CheckIsValid(value string) error {
if !dataAmountCheckPattern.MatchString(value) {
return InvalidDataAmountError{}
}
return nil
}
func calculateLineToKilobyte(value string, unit string) string {
val, err := strconv.Atoi(value)
if err != nil {
return "<unknown>"
}
switch unit {
case "K":
return strconv.Itoa(val)
case "M":
return strconv.Itoa(val * 1000)
case "G":
return strconv.Itoa(val * 1000 * 1000)
default:
return "<unknown>"
}
}
func (v DataAmountValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem {
completions := make([]protocol.CompletionItem, 0)
if line != "" && !dataAmountCheckPattern.MatchString(line) {
kind := protocol.CompletionItemKindValue
completions = append(
completions,
protocol.CompletionItem{
Label: line + "K",
Kind: &kind,
Documentation: line + " kilobytes",
},
protocol.CompletionItem{
Label: line + "M",
Kind: &kind,
Documentation: fmt.Sprintf("%s megabytes (%s kilobytes)", line, calculateLineToKilobyte(line, "M")),
},
protocol.CompletionItem{
Label: line + "G",
Kind: &kind,
Documentation: fmt.Sprintf("%s gigabytes (%s kilobytes)", line, calculateLineToKilobyte(line, "G")),
},
)
}
if line == "" || isJustDigitsPattern.MatchString(line) {
completions = append(
completions,
docvalues.GenerateBase10Completions(line)...,
)
}
return completions
}

View File

@ -12,7 +12,12 @@ import (
var timeFormatCompletionsPattern = regexp.MustCompile(`(?i)^(\d+)([smhdw])$`) var timeFormatCompletionsPattern = regexp.MustCompile(`(?i)^(\d+)([smhdw])$`)
var timeFormatCheckPattern = regexp.MustCompile(`(?i)^(\d+)([smhdw]?)$`) var timeFormatCheckPattern = regexp.MustCompile(`(?i)^(\d+)([smhdw]?)$`)
var isJustDigitsPattern = regexp.MustCompile(`^\d+$`)
type InvalidTimeFormatError struct{}
func (e InvalidTimeFormatError) Error() string {
return "Time format is invalid. It must be in the form of: <number>[s|m|h|d|w]"
}
type TimeFormatValue struct{} type TimeFormatValue struct{}
@ -22,7 +27,7 @@ func (v TimeFormatValue) GetTypeDescription() []string {
func (v TimeFormatValue) CheckIsValid(value string) error { func (v TimeFormatValue) CheckIsValid(value string) error {
if !timeFormatCheckPattern.MatchString(value) { if !timeFormatCheckPattern.MatchString(value) {
return docvalues.RegexInvalidError{Regex: timeFormatCheckPattern.String()} return InvalidTimeFormatError{}
} }
return nil return nil
@ -88,20 +93,7 @@ func (v TimeFormatValue) FetchCompletions(line string, cursor uint32) []protocol
if line == "" || isJustDigitsPattern.MatchString(line) { if line == "" || isJustDigitsPattern.MatchString(line) {
completions = append( completions = append(
completions, completions,
utils.Map( docvalues.GenerateBase10Completions(line)...,
[]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
func(index int) protocol.CompletionItem {
kind := protocol.CompletionItemKindValue
sortText := strconv.Itoa(index)
return protocol.CompletionItem{
Label: line + strconv.Itoa(index),
Kind: &kind,
SortText: &sortText,
}
},
)...,
) )
} }