diff --git a/server/doc-values/value-data-amount-value.go b/server/doc-values/value-data-amount-value.go index 145315b..bbc2f67 100644 --- a/server/doc-values/value-data-amount-value.go +++ b/server/doc-values/value-data-amount-value.go @@ -45,11 +45,11 @@ func calculateLineToKilobyte(value string, unit string) string { switch unit { case "K": - return strconv.Itoa(val) - case "M": return strconv.Itoa(val * 1000) - case "G": + case "M": return strconv.Itoa(val * 1000 * 1000) + case "G": + return strconv.Itoa(val * 1000 * 1000 * 1000) default: return "" } diff --git a/server/doc-values/value-hex-color.go b/server/doc-values/value-hex-color.go new file mode 100644 index 0000000..e056929 --- /dev/null +++ b/server/doc-values/value-hex-color.go @@ -0,0 +1,66 @@ +package docvalues + +import ( + "regexp" + + protocol "github.com/tliron/glsp/protocol_3_16" +) + +var color24BitPattern = regexp.MustCompile(`^#[0-9a-fA-F]{6}$`) +var color12BitPattern = regexp.MustCompile(`^#[0-9a-fA-F]{3}$`) + +type InvalidColorError struct{} + +func (e InvalidColorError) Error() string { + return "Color is invalid. It must be in the form of: #RRGGBB" +} + +type HexColorValue struct { + Allow12Bit bool +} + +func (v HexColorValue) GetTypeDescription() []string { + return []string{"Color in HEX-Format (e.g. #RRGGBB)"} +} + +func (v HexColorValue) DeprecatedCheckIsValid(value string) []*InvalidValue { + if color24BitPattern.MatchString(value) || (v.Allow12Bit && color12BitPattern.MatchString(value)) { + return nil + } + + return []*InvalidValue{ + { + Err: InvalidColorError{}, + Start: 0, + End: uint32(len(value)), + }, + } +} + +var characters = []rune{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'} + +func (v HexColorValue) DeprecatedFetchCompletions(line string, cursor uint32) []protocol.CompletionItem { + completions := make([]protocol.CompletionItem, 0) + + if line == "" { + kind := protocol.CompletionItemKindValue + completions = append(completions, protocol.CompletionItem{ + Label: "#", + Kind: &kind, + }) + } else if !color24BitPattern.MatchString(line) { + for _, c := range characters { + kind := protocol.CompletionItemKindValue + completions = append(completions, protocol.CompletionItem{ + Label: string(c), + Kind: &kind, + }) + } + } + + return completions +} + +func (v HexColorValue) DeprecatedFetchHoverInfo(line string, cursor uint32) []string { + return []string{"Color in HEX-Format (e.g. #RRGGBB)"} +} diff --git a/server/doc-values/value-path.go b/server/doc-values/value-path.go index 1aced7c..eba79dd 100644 --- a/server/doc-values/value-path.go +++ b/server/doc-values/value-path.go @@ -46,8 +46,12 @@ func (v PathValue) GetTypeDescription() []string { return []string{strings.Join(hints, ", ")} } +func (v PathValue) createSystemPath(value string) string { + return value +} + func (v PathValue) DeprecatedCheckIsValid(value string) []*InvalidValue { - if !utils.DoesPathExist(value) { + if !utils.DoesPathExist(v.createSystemPath(value)) { return []*InvalidValue{{ Err: PathDoesNotExistError{}, Start: 0, diff --git a/server/doc-values/value-time-format.go b/server/doc-values/value-time-format.go index 4670aa9..8f99af9 100644 --- a/server/doc-values/value-time-format.go +++ b/server/doc-values/value-time-format.go @@ -107,5 +107,5 @@ func (v TimeFormatValue) DeprecatedFetchCompletions(line string, cursor uint32) } func (v TimeFormatValue) DeprecatedFetchHoverInfo(line string, cursor uint32) []string { - return []string{} + return []string{"A time value. For example: 5m (5 minutes)"} } diff --git a/server/handlers/gitconfig/ast/gitconfig.go b/server/handlers/gitconfig/ast/gitconfig.go index 912d9cb..f478749 100644 --- a/server/handlers/gitconfig/ast/gitconfig.go +++ b/server/handlers/gitconfig/ast/gitconfig.go @@ -32,9 +32,11 @@ type GitEntry struct { Value *GitValue } +type GitSectionTitle string + type GitSectionHeader struct { common.LocationRange - Title string + Title GitSectionTitle } type GitSection struct { diff --git a/server/handlers/gitconfig/ast/gitconfig_fields.go b/server/handlers/gitconfig/ast/gitconfig_fields.go index ec1afc5..3f5e54c 100644 --- a/server/handlers/gitconfig/ast/gitconfig_fields.go +++ b/server/handlers/gitconfig/ast/gitconfig_fields.go @@ -1,6 +1,11 @@ package ast -import "slices" +import ( + "fmt" + "regexp" + "slices" + "strings" +) func (c *GitConfig) Clear() { c.Sections = []*GitSection{} @@ -66,3 +71,33 @@ func (s *GitSection) FindOption(line uint32) *GitEntry { return s.Entries[index] } + +var nonWhitespacePattern = regexp.MustCompile(`\S+`) +var deprecatedSectionPattern = regexp.MustCompile(`.+?\..+`) + +func (t GitSectionTitle) NormalizedTitle() string { + entries := nonWhitespacePattern.FindAllString(string(t), -1) + + if entries == nil { + return string(t) + } + + if len(entries) == 1 { + title := entries[0] + + dotEntries := strings.Split(title, ".") + + if len(dotEntries) == 2 { + // Deprecated title format + return fmt.Sprintf(`%s "%s"`, strings.ToLower(dotEntries[0]), strings.ToLower(dotEntries[1])) + } + + return strings.ToLower(title) + } + + if len(entries) == 2 { + return fmt.Sprintf(`%s "%s"`, strings.ToLower(entries[0]), entries[1]) + } + + return string(t) +} diff --git a/server/handlers/gitconfig/ast/parser.go b/server/handlers/gitconfig/ast/parser.go index 1e33dac..a225287 100644 --- a/server/handlers/gitconfig/ast/parser.go +++ b/server/handlers/gitconfig/ast/parser.go @@ -157,7 +157,7 @@ func (c *GitConfig) parseHeader( LocationRange: location, Title: &GitSectionHeader{ LocationRange: location, - Title: input[leftBracketIndex+1 : rightBracketIndex], + Title: GitSectionTitle(input[leftBracketIndex+1 : rightBracketIndex]), }, Entries: make([]*GitEntry, 0), } diff --git a/server/handlers/gitconfig/fields/common.go b/server/handlers/gitconfig/fields/common.go new file mode 100644 index 0000000..35d0123 --- /dev/null +++ b/server/handlers/gitconfig/fields/common.go @@ -0,0 +1,9 @@ +package fields + +import "strings" + +type NormalizedOptionName string + +func CreateNormalizedName(s string) NormalizedOptionName { + return NormalizedOptionName(strings.ToLower(s)) +} diff --git a/server/handlers/gitconfig/fields/options.go b/server/handlers/gitconfig/fields/options.go new file mode 100644 index 0000000..4e4d6d8 --- /dev/null +++ b/server/handlers/gitconfig/fields/options.go @@ -0,0 +1,1046 @@ +package fields + +import docvalues "config-lsp/doc-values" + +var minusOne = -1 +var four = 4 + +// Add all remaining sections +var OptionsMap = map[string](map[NormalizedOptionName]docvalues.DeprecatedValue){ + "core": { + "filemode": docvalues.DocumentationValue{ + Documentation: `Tells Git if the executable bit of files in the working tree +is to be honored. + +Some filesystems lose the executable bit when a file that is +marked as executable is checked out, or checks out a +non-executable file with executable bit on. +git-clone[1] or git-init[1] probe the filesystem +to see if it handles the executable bit correctly +and this variable is automatically set as necessary. + + +A repository, however, may be on a filesystem that handles +the filemode correctly, and this variable is set to true +when created, but later may be made accessible from another +environment that loses the filemode (e.g. exporting ext4 via +CIFS mount, visiting a Cygwin created repository with +Git for Windows or Eclipse). +In such a case it may be necessary to set this variable to false. +See git-update-index[1]. + + +The default is true (when core.filemode is not specified in the config file).`, + Value: BooleanField, + }, + "hidedotfiles": docvalues.DocumentationValue{ + Documentation: `(Windows-only) If true, mark newly-created directories and files whose +name starts with a dot as hidden. If dotGitOnly, only the .git/ +directory is hidden, but no other files starting with a dot. The +default mode is dotGitOnly.`, + Value: docvalues.EnumValue{ + Values: []docvalues.EnumString{ + docvalues.CreateEnumString("dotGitOnly"), + + docvalues.CreateEnumString("yes"), + docvalues.CreateEnumString("on"), + docvalues.CreateEnumString("true"), + docvalues.CreateEnumString("1"), + + docvalues.CreateEnumString("no"), + docvalues.CreateEnumString("off"), + docvalues.CreateEnumString("false"), + docvalues.CreateEnumString("0"), + }, + }, + }, + "ignorecase": docvalues.DocumentationValue{ + Documentation: `Internal variable which enables various workarounds to enable +Git to work better on filesystems that are not case sensitive, +like APFS, HFS+, FAT, NTFS, etc. For example, if a directory listing +finds "makefile" when Git expects "Makefile", Git will assume +it is really the same file, and continue to remember it as +"Makefile". + +The default is false, except git-clone[1] or git-init[1] +will probe and set core.ignoreCase true if appropriate when the repository +is created. + + +Git relies on the proper configuration of this variable for your operating +and file system. Modifying this value may result in unexpected behavior.`, + Value: BooleanField, + }, + "precomposeunicode": docvalues.DocumentationValue{ + Documentation: `This option is only used by Mac OS implementation of Git. +When core.precomposeUnicode=true, Git reverts the unicode decomposition +of filenames done by Mac OS. This is useful when sharing a repository +between Mac OS and Linux or Windows. +(Git for Windows 1.7.10 or higher is needed, or Git under cygwin 1.7). +When false, file names are handled fully transparent by Git, +which is backward compatible with older versions of Git.`, + Value: BooleanField, + }, + "protecthfs": docvalues.DocumentationValue{ + Documentation: `If set to true, do not allow checkout of paths that would +be considered equivalent to .git on an HFS+ filesystem. +Defaults to true on Mac OS, and false elsewhere.`, + Value: BooleanField, + }, + "protectntfs": docvalues.DocumentationValue{ + Documentation: `If set to true, do not allow checkout of paths that would +cause problems with the NTFS filesystem, e.g. conflict with +8.3 "short" names. +Defaults to true on Windows, and false elsewhere.`, + Value: BooleanField, + }, + "fsmonitor": docvalues.DocumentationValue{ + Documentation: `If set to true, enable the built-in file system monitor +daemon for this working directory (git-fsmonitor--daemon[1]). + +Like hook-based file system monitors, the built-in file system monitor +can speed up Git commands that need to refresh the Git index +(e.g. git status) in a working directory with many files. The +built-in monitor eliminates the need to install and maintain an +external third-party tool. + +The built-in file system monitor is currently available only on a +limited set of supported platforms. Currently, this includes Windows +and MacOS. + +Otherwise, this variable contains the pathname of the "fsmonitor" +hook command. + +This hook command is used to identify all files that may have changed +since the requested date/time. This information is used to speed up +git by avoiding unnecessary scanning of files that have not changed. + +See the "fsmonitor-watchman" section of githooks[5]. + +Note that if you concurrently use multiple versions of Git, such +as one version on the command line and another version in an IDE +tool, that the definition of core.fsmonitor was extended to +allow boolean values in addition to hook pathnames. Git versions +2.35.1 and prior will not understand the boolean values and will +consider the "true" or "false" values as hook pathnames to be +invoked. Git versions 2.26 thru 2.35.1 default to hook protocol +V2 and will fall back to no fsmonitor (full scan). Git versions +prior to 2.26 default to hook protocol V1 and will silently +assume there were no changes to report (no scan), so status +commands may report incomplete results. For this reason, it is +best to upgrade all of your Git versions before using the built-in +file system monitor.`, + Value: docvalues.OrValue{ + Values: []docvalues.DeprecatedValue{ + BooleanField, + docvalues.StringValue{}, + }, + }, + }, + "fsmonitorhookversion": docvalues.DocumentationValue{ + Documentation: `Sets the protocol version to be used when invoking the +"fsmonitor" hook. + +There are currently versions 1 and 2. When this is not set, +version 2 will be tried first and if it fails then version 1 +will be tried. Version 1 uses a timestamp as input to determine +which files have changes since that time but some monitors +like Watchman have race conditions when used with a timestamp. +Version 2 uses an opaque string so that the monitor can return +something that can be used to determine what files have changed +without race conditions.`, + Value: docvalues.EnumValue{ + Values: []docvalues.EnumString{ + docvalues.CreateEnumString("1"), + docvalues.CreateEnumString("2"), + }, + }, + }, + "trustctime": docvalues.DocumentationValue{ + Documentation: `If false, the ctime differences between the index and the +working tree are ignored; useful when the inode change time +is regularly modified by something outside Git (file system +crawlers and some backup systems). +See git-update-index[1]. True by default.`, + Value: BooleanField, + }, + "splitindex": docvalues.DocumentationValue{ + Documentation: `If true, the split-index feature of the index will be used. +See git-update-index[1]. False by default.`, + Value: BooleanField, + }, + "untrackedcache": docvalues.DocumentationValue{ + Documentation: `Determines what to do about the untracked cache feature of the +index. It will be kept, if this variable is unset or set to +keep. It will automatically be added if set to true. And +it will automatically be removed, if set to false. Before +setting it to true, you should check that mtime is working +properly on your system. +See git-update-index[1]. keep by default, unless +feature.manyFiles is enabled which sets this setting to +true by default.`, + Value: BooleanField, + }, + "checkstat": docvalues.DocumentationValue{ + Documentation: `When missing or is set to default, many fields in the stat +structure are checked to detect if a file has been modified +since Git looked at it. When this configuration variable is +set to minimal, sub-second part of mtime and ctime, the +uid and gid of the owner of the file, the inode number (and +the device number, if Git was compiled to use it), are +excluded from the check among these fields, leaving only the +whole-second part of mtime (and ctime, if core.trustCtime +is set) and the filesize to be checked. + +There are implementations of Git that do not leave usable values in +some fields (e.g. JGit); by excluding these fields from the +comparison, the minimal mode may help interoperability when the +same repository is used by these other systems at the same time.`, + Value: docvalues.EnumValue{ + Values: []docvalues.EnumString{ + docvalues.CreateEnumString("default"), + docvalues.CreateEnumString("minimal"), + }, + }, + }, + "quotepath": docvalues.DocumentationValue{ + Documentation: `Commands that output paths (e.g. ls-files, diff), will +quote "unusual" characters in the pathname by enclosing the +pathname in double-quotes and escaping those characters with +backslashes in the same way C escapes control characters (e.g. +\\t for TAB, \ + for LF, \\\\ for backslash) or bytes with +values larger than 0x80 (e.g. octal \\302\\265 for "micro" in +UTF-8). If this variable is set to false, bytes higher than +0x80 are not considered "unusual" any more. Double-quotes, +backslash and control characters are always escaped regardless +of the setting of this variable. A simple space character is +not considered "unusual". Many commands can output pathnames +completely verbatim using the -z option. The default value +is true.`, + Value: docvalues.StringValue{}, + }, + // TODO: Add latger + "eol": docvalues.DocumentationValue{ + Documentation: `Sets the line ending type to use in the working directory for +files that are marked as text (either by having the text +attribute set, or by having text=auto and Git auto-detecting +the contents as text). +Alternatives are lf, crlf and native, which uses the platform’s +native line ending. The default value is native. See +gitattributes[5] for more information on end-of-line +conversion. Note that this value is ignored if core.autocrlf +is set to true or input.`, + Value: docvalues.StringValue{}, + }, + "safecrlf": docvalues.DocumentationValue{ + Documentation: `If true, makes Git check if converting CRLF is reversible when +end-of-line conversion is active. Git will verify if a command +modifies a file in the work tree either directly or indirectly. +For example, committing a file followed by checking out the +same file should yield the original file in the work tree. If +this is not the case for the current setting of +core.autocrlf, Git will reject the file. The variable can +be set to "warn", in which case Git will only warn about an +irreversible conversion but continue the operation. + +CRLF conversion bears a slight chance of corrupting data. +When it is enabled, Git will convert CRLF to LF during commit and LF to +CRLF during checkout. A file that contains a mixture of LF and +CRLF before the commit cannot be recreated by Git. For text +files this is the right thing to do: it corrects line endings +such that we have only LF line endings in the repository. +But for binary files that are accidentally classified as text the +conversion can corrupt data. + + +If you recognize such corruption early you can easily fix it by +setting the conversion type explicitly in .gitattributes. Right +after committing you still have the original file in your work +tree and this file is not yet corrupted. You can explicitly tell +Git that this file is binary and Git will handle the file +appropriately. + + +Unfortunately, the desired effect of cleaning up text files with +mixed line endings and the undesired effect of corrupting binary +files cannot be distinguished. In both cases CRLFs are removed +in an irreversible way. For text files this is the right thing +to do because CRLFs are line endings, while for binary files +converting CRLFs corrupts data. + + +Note, this safety check does not mean that a checkout will generate a +file identical to the original file for a different setting of +core.eol and core.autocrlf, but only for the current one. For +example, a text file with LF would be accepted with core.eol=lf +and could later be checked out with core.eol=crlf, in which case the +resulting file would contain CRLF, although the original file +contained LF. However, in both work trees the line endings would be +consistent, that is either all LF or all CRLF, but never mixed. A +file with mixed line endings would be reported by the core.safecrlf +mechanism.`, + Value: docvalues.EnumValue{ + Values: []docvalues.EnumString{ + docvalues.CreateEnumString("warn"), + + docvalues.CreateEnumString("yes"), + docvalues.CreateEnumString("on"), + docvalues.CreateEnumString("true"), + docvalues.CreateEnumString("1"), + + docvalues.CreateEnumString("no"), + docvalues.CreateEnumString("off"), + docvalues.CreateEnumString("false"), + docvalues.CreateEnumString("0"), + }, + }, + }, + "autocrlf": docvalues.DocumentationValue{ + Documentation: `Setting this variable to "true" is the same as setting +the text attribute to "auto" on all files and core.eol to "crlf". +Set to true if you want to have CRLF line endings in your +working directory and the repository has LF line endings. +This variable can be set to input, +in which case no output conversion is performed.`, + Value: BooleanField, + }, + // TODO: Add later + "checkroundtripencoding": docvalues.DocumentationValue{ + Documentation: `A comma and/or whitespace separated list of encodings that Git +performs UTF-8 round trip checks on if they are used in an +working-tree-encoding attribute (see gitattributes[5]). +The default value is SHIFT-JIS.`, + Value: docvalues.StringValue{}, + }, + "symlinks": docvalues.DocumentationValue{ + Documentation: `If false, symbolic links are checked out as small plain files that +contain the link text. git-update-index[1] and +git-add[1] will not change the recorded type to regular +file. Useful on filesystems like FAT that do not support +symbolic links. + +The default is true, except git-clone[1] or git-init[1] +will probe and set core.symlinks false if appropriate when the repository +is created.`, + Value: BooleanField, + }, + "gitproxy": docvalues.DocumentationValue{ + Documentation: `A "proxy command" to execute (as command host port) instead +of establishing direct connection to the remote server when +using the Git protocol for fetching. If the variable value is +in the "COMMAND for DOMAIN" format, the command is applied only +on hostnames ending with the specified domain string. This variable +may be set multiple times and is matched in the given order; +the first match wins. + +Can be overridden by the GIT_PROXY_COMMAND environment variable +(which always applies universally, without the special "for" +handling). + +The special string none can be used as the proxy command to +specify that no proxy be used for a given domain pattern. +This is useful for excluding servers inside a firewall from +proxy use, while defaulting to a common proxy for external domains.`, + Value: docvalues.StringValue{}, + }, + "sshcommand": docvalues.DocumentationValue{ + Documentation: `If this variable is set, git fetch and git push will +use the specified command instead of ssh when they need to +connect to a remote system. The command is in the same form as +the GIT_SSH_COMMAND environment variable and is overridden +when the environment variable is set.`, + Value: docvalues.StringValue{}, + }, + "ignorestat": docvalues.DocumentationValue{ + Documentation: `If true, Git will avoid using lstat() calls to detect if files have +changed by setting the "assume-unchanged" bit for those tracked files +which it has updated identically in both the index and working tree. + +When files are modified outside of Git, the user will need to stage +the modified files explicitly (e.g. see Examples section in +git-update-index[1]). +Git will not normally detect changes to those files. + +This is useful on systems where lstat() calls are very slow, such as +CIFS/Microsoft Windows. + +False by default.`, + Value: BooleanField, + }, + "prefersymlinkrefs": docvalues.DocumentationValue{ + Documentation: `Instead of the default "symref" format for HEAD +and other symbolic reference files, use symbolic links. +This is sometimes needed to work with old scripts that +expect HEAD to be a symbolic link.`, + Value: BooleanField, + }, + "alternaterefscommand": docvalues.DocumentationValue{ + Documentation: `When advertising tips of available history from an alternate, use the shell to +execute the specified command instead of git-for-each-ref[1]. The +first argument is the absolute path of the alternate. Output must contain one +hex object id per line (i.e., the same as produced by git for-each-ref +--format='%(objectname)'). + +Note that you cannot generally put git for-each-ref directly into the config +value, as it does not take a repository path as an argument (but you can wrap +the command above in a shell script).`, + Value: docvalues.StringValue{}, + }, + "alternaterefsprefixes": docvalues.DocumentationValue{ + Documentation: `When listing references from an alternate, list only references that begin +with the given prefix. Prefixes match as if they were given as arguments to +git-for-each-ref[1]. To list multiple prefixes, separate them with +whitespace. If core.alternateRefsCommand is set, setting +core.alternateRefsPrefixes has no effect.`, + Value: docvalues.ArrayValue{ + Separator: " ", + DuplicatesExtractor: &docvalues.SimpleDuplicatesExtractor, + SubValue: docvalues.StringValue{}, + }, + }, + "bare": docvalues.DocumentationValue{ + Documentation: `If true this repository is assumed to be bare and has no +working directory associated with it. If this is the case a +number of commands that require a working directory will be +disabled, such as git-add[1] or git-merge[1]. + +This setting is automatically guessed by git-clone[1] or +git-init[1] when the repository was created. By default a +repository that ends in "/.git" is assumed to be not bare (bare = +false), while all other repositories are assumed to be bare (bare += true).`, + Value: BooleanField, + }, + "worktree": docvalues.DocumentationValue{ + Documentation: `Set the path to the root of the working tree. +If GIT_COMMON_DIR environment variable is set, core.worktree +is ignored and not used for determining the root of working tree. +This can be overridden by the GIT_WORK_TREE environment +variable and the --work-tree command-line option. +The value can be an absolute path or relative to the path to +the .git directory, which is either specified by --git-dir +or GIT_DIR, or automatically discovered. +If --git-dir or GIT_DIR is specified but none of +--work-tree, GIT_WORK_TREE and core.worktree is specified, +the current working directory is regarded as the top level +of your working tree. + +Note that this variable is honored even when set in a configuration +file in a ".git" subdirectory of a directory and its value differs +from the latter directory (e.g. "/path/to/.git/config" has +core.worktree set to "/different/path"), which is most likely a +misconfiguration. Running Git commands in the "/path/to" directory will +still use "/different/path" as the root of the work tree and can cause +confusion unless you know what you are doing (e.g. you are creating a +read-only snapshot of the same index to a location different from the +repository’s usual working tree).`, + Value: docvalues.PathValue{ + RequiredType: docvalues.PathTypeDirectory, + }, + }, + "logallrefupdates": docvalues.DocumentationValue{ + Documentation: `Enable the reflog. Updates to a ref is logged to the file +"$GIT_DIR/logs/", by appending the new and old +SHA-1, the date/time and the reason of the update, but +only when the file exists. If this configuration +variable is set to true, missing "$GIT_DIR/logs/" +file is automatically created for branch heads (i.e. under +refs/heads/), remote refs (i.e. under refs/remotes/), +note refs (i.e. under refs/notes/), and the symbolic ref HEAD. +If it is set to always, then a missing reflog is automatically +created for any ref under refs/. + +This information can be used to determine what commit +was the tip of a branch "2 days ago". + + +This value is true by default in a repository that has +a working directory associated with it, and false by +default in a bare repository.`, + Value: BooleanField, + }, + "repositoryformatversion": docvalues.DocumentationValue{ + Documentation: `Internal variable identifying the repository format and layout version.`, + Value: docvalues.StringValue{}, + }, + "sharedrepository": docvalues.DocumentationValue{ + Documentation: `When group (or true), the repository is made shareable between +several users in a group (making sure all the files and objects are +group-writable). When all (or world or everybody), the +repository will be readable by all users, additionally to being +group-shareable. When umask (or false), Git will use permissions +reported by umask(2). When 0xxx, where 0xxx is an octal number, +files in the repository will have this mode value. 0xxx will override +user’s umask value (whereas the other options will only override +requested parts of the user’s umask value). Examples: 0660 will make +the repo read/write-able for the owner and group, but inaccessible to +others (equivalent to group unless umask is e.g. 0022). 0640 is a +repository that is group-readable but not group-writable. +See git-init[1]. False by default.`, + Value: docvalues.OrValue{ + Values: []docvalues.DeprecatedValue{ + docvalues.UmaskValue{}, + docvalues.EnumValue{ + Values: []docvalues.EnumString{ + docvalues.CreateEnumStringWithDoc( + "group", + "The repository is made shareable between several users in a group (making sure all the files and objects are group-writable)", + ), + docvalues.CreateEnumStringWithDoc( + "true", + "The repository is made shareable between several users in a group (making sure all the files and objects are group-writable)", + ), + + docvalues.CreateEnumStringWithDoc( + "all", + "The repository will be readable by all users, additionally to being group-shareable", + ), + docvalues.CreateEnumStringWithDoc( + "world", + "The repository will be readable by all users, additionally to being group-shareable", + ), + docvalues.CreateEnumStringWithDoc( + "everybody", + "The repository will be readable by all users, additionally to being group-shareable", + ), + + docvalues.CreateEnumStringWithDoc( + "umask", + "Git will use permissions reported by umask(2)", + ), + docvalues.CreateEnumStringWithDoc( + "false", + "Git will use permissions reported by umask(2)", + ), + }, + }, + }, + }, + }, + "warnambiguousrefs": docvalues.DocumentationValue{ + Documentation: `If true, Git will warn you if the ref name you passed it is ambiguous +and might match multiple refs in the repository. True by default.`, + Value: BooleanField, + }, + "compression": docvalues.DocumentationValue{ + Documentation: `An integer -1..9, indicating a default compression level. +-1 is the zlib default. 0 means no compression, +and 1..9 are various speed/size tradeoffs, 9 being slowest. +If set, this provides a default to other compression variables, +such as core.looseCompression and pack.compression.`, + Value: docvalues.NumberRangeValue(-1, 9), + }, + "loosecompression": docvalues.DocumentationValue{ + Documentation: `An integer -1..9, indicating the compression level for objects that +are not in a pack file. -1 is the zlib default. 0 means no +compression, and 1..9 are various speed/size tradeoffs, 9 being +slowest. If not set, defaults to core.compression. If that is +not set, defaults to 1 (best speed).`, + Value: docvalues.NumberRangeValue(-1, 9), + }, + "packedgitwindowsize": docvalues.DocumentationValue{ + Documentation: `Number of bytes of a pack file to map into memory in a +single mapping operation. Larger window sizes may allow +your system to process a smaller number of large pack files +more quickly. Smaller window sizes will negatively affect +performance due to increased calls to the operating system’s +memory manager, but may improve performance when accessing +a large number of large pack files. + +Default is 1 MiB if NO_MMAP was set at compile time, otherwise 32 +MiB on 32 bit platforms and 1 GiB on 64 bit platforms. This should +be reasonable for all users/operating systems. You probably do +not need to adjust this value. + + +Common unit suffixes of k, m, or g are supported.`, + Value: IntegerValue{}, + }, + "packedgitlimit": docvalues.DocumentationValue{ + Documentation: `Maximum number of bytes to map simultaneously into memory +from pack files. If Git needs to access more than this many +bytes at once to complete an operation it will unmap existing +regions to reclaim virtual address space within the process. + +Default is 256 MiB on 32 bit platforms and 32 TiB (effectively +unlimited) on 64 bit platforms. +This should be reasonable for all users/operating systems, except on +the largest projects. You probably do not need to adjust this value. + + +Common unit suffixes of k, m, or g are supported.`, + Value: IntegerValue{}, + }, + "deltabasecachelimit": docvalues.DocumentationValue{ + Documentation: `Maximum number of bytes per thread to reserve for caching base objects +that may be referenced by multiple deltified objects. By storing the +entire decompressed base objects in a cache Git is able +to avoid unpacking and decompressing frequently used base +objects multiple times. + +Default is 96 MiB on all platforms. This should be reasonable +for all users/operating systems, except on the largest projects. +You probably do not need to adjust this value. + + +Common unit suffixes of k, m, or g are supported.`, + Value: IntegerValue{}, + }, + "bigfilethreshold": docvalues.DocumentationValue{ + Documentation: `The size of files considered "big", which as discussed below +changes the behavior of numerous git commands, as well as how +such files are stored within the repository. The default is +512 MiB. Common unit suffixes of k, m, or g are +supported. + +Files above the configured limit will be: + +Stored deflated in packfiles, without attempting delta compression. + +The default limit is primarily set with this use-case in mind. With it, +most projects will have their source code and other text files delta +compressed, but not larger binary media files. + +Storing large files without delta compression avoids excessive memory +usage, at the slight expense of increased disk usage. + +Will be treated as if they were labeled "binary" (see +gitattributes[5]). e.g. git-log[1] and +git-diff[1] will not compute diffs for files above this limit. + +Will generally be streamed when written, which avoids excessive +memory usage, at the cost of some fixed overhead. Commands that make +use of this include git-archive[1], +git-fast-import[1], git-index-pack[1], +git-unpack-objects[1] and git-fsck[1].`, + Value: IntegerValue{}, + }, + // TODO: Add support for patterns + "excludesfile": docvalues.DocumentationValue{ + Documentation: `Specifies the pathname to the file that contains patterns to +describe paths that are not meant to be tracked, in addition +to .gitignore (per-directory) and .git/info/exclude. +Defaults to $XDG_CONFIG_HOME/git/ignore. +If $XDG_CONFIG_HOME is either not set or empty, $HOME/.config/git/ignore +is used instead. See gitignore[5].`, + Value: docvalues.PathValue{ + RequiredType: docvalues.PathTypeFile, + }, + }, + "askpass": docvalues.DocumentationValue{ + Documentation: `Some commands (e.g. svn and http interfaces) that interactively +ask for a password can be told to use an external program given +via the value of this variable. Can be overridden by the GIT_ASKPASS +environment variable. If not set, fall back to the value of the +SSH_ASKPASS environment variable or, failing that, a simple password +prompt. The external program shall be given a suitable prompt as +command-line argument and write the password on its STDOUT.`, + Value: docvalues.StringValue{}, + }, + // TODO: Add support for patterns + "attributesfile": docvalues.DocumentationValue{ + Documentation: `In addition to .gitattributes (per-directory) and +.git/info/attributes, Git looks into this file for attributes +(see gitattributes[5]). Path expansions are made the same +way as for core.excludesFile. Its default value is +$XDG_CONFIG_HOME/git/attributes. If $XDG_CONFIG_HOME is either not +set or empty, $HOME/.config/git/attributes is used instead.`, + Value: docvalues.StringValue{}, + }, + // TODO: Add support for patterns + "hookspath": docvalues.DocumentationValue{ + Documentation: `By default Git will look for your hooks in the +$GIT_DIR/hooks directory. Set this to different path, +e.g. /etc/git/hooks, and Git will try to find your hooks in +that directory, e.g. /etc/git/hooks/pre-receive instead of +in $GIT_DIR/hooks/pre-receive. + +The path can be either absolute or relative. A relative path is +taken as relative to the directory where the hooks are run (see +the "DESCRIPTION" section of githooks[5]). + + +This configuration variable is useful in cases where you’d like to +centrally configure your Git hooks instead of configuring them on a +per-repository basis, or as a more flexible and centralized +alternative to having an init.templateDir where you’ve changed +default hooks.`, + Value: docvalues.StringValue{}, + }, + "editor": docvalues.DocumentationValue{ + Documentation: `Commands such as commit and tag that let you edit +messages by launching an editor use the value of this +variable when it is set, and the environment variable +GIT_EDITOR is not set. See git-var[1].`, + Value: docvalues.StringValue{}, + }, + "commentstring": docvalues.DocumentationValue{ + Documentation: `Commands such as commit and tag that let you edit +messages consider a line that begins with this character +commented, and removes them after the editor returns +(default #). + +If set to "auto", git-commit would select a character that is not +the beginning character of any line in existing commit messages. + +Note that these two variables are aliases of each other, and in modern +versions of Git you are free to use a string (e.g., // or ⁑⁕⁑) with +commentChar. Versions of Git prior to v2.45.0 will ignore +commentString but will reject a value of commentChar that consists +of more than a single ASCII byte. If you plan to use your config with +older and newer versions of Git, you may want to specify both: + +[core] +# single character for older versions +commentChar = "#" +# string for newer versions (which will override commentChar +# because it comes later in the file) +commentString = "//"`, + Value: docvalues.StringValue{}, + }, + "filesreflocktimeout": docvalues.DocumentationValue{ + Documentation: `The length of time, in milliseconds, to retry when trying to +lock an individual reference. Value 0 means not to retry at +all; -1 means to try indefinitely. Default is 100 (i.e., +retry for 100ms).`, + Value: docvalues.NumberValue{ + Min: &minusOne, + }, + }, + "packedrefstimeout": docvalues.DocumentationValue{ + Documentation: `The length of time, in milliseconds, to retry when trying to +lock the packed-refs file. Value 0 means not to retry at +all; -1 means to try indefinitely. Default is 1000 (i.e., +retry for 1 second).`, + Value: docvalues.NumberValue{ + Min: &minusOne, + }, + }, + "pager": docvalues.DocumentationValue{ + Documentation: `Text viewer for use by Git commands (e.g., less). The value +is meant to be interpreted by the shell. The order of preference +is the $GIT_PAGER environment variable, then core.pager +configuration, then $PAGER, and then the default chosen at +compile time (usually less). + +When the LESS environment variable is unset, Git sets it to FRX +(if LESS environment variable is set, Git does not change it at +all). If you want to selectively override Git’s default setting +for LESS, you can set core.pager to e.g. less -S. This will +be passed to the shell by Git, which will translate the final +command to LESS=FRX less -S. The environment does not set the +S option but the command line does, instructing less to truncate +long lines. Similarly, setting core.pager to less -+F will +deactivate the F option specified by the environment from the +command-line, deactivating the "quit if one screen" behavior of +less. One can specifically activate some flags for particular +commands: for example, setting pager.blame to less -S enables +line truncation only for git blame. + + +Likewise, when the LV environment variable is unset, Git sets it +to -c. You can override this setting by exporting LV with +another value or setting core.pager to lv +c.`, + Value: docvalues.StringValue{}, + }, + "whitespace": docvalues.DocumentationValue{ + Documentation: `A comma separated list of common whitespace problems to +notice. git diff will use color.diff.whitespace to +highlight them, and git apply --whitespace=error will +consider them as errors. You can prefix - to disable +any of them (e.g. -trailing-space): + +blank-at-eol treats trailing whitespaces at the end of the line +as an error (enabled by default). + +space-before-tab treats a space character that appears immediately +before a tab character in the initial indent part of the line as an +error (enabled by default). + +indent-with-non-tab treats a line that is indented with space +characters instead of the equivalent tabs as an error (not enabled by +default). + +tab-in-indent treats a tab character in the initial indent part of +the line as an error (not enabled by default). + +blank-at-eof treats blank lines added at the end of file as an error +(enabled by default). + +trailing-space is a short-hand to cover both blank-at-eol and +blank-at-eof. + +cr-at-eol treats a carriage-return at the end of line as +part of the line terminator, i.e. with it, trailing-space +does not trigger if the character before such a carriage-return +is not a whitespace (not enabled by default). + +tabwidth= tells how many character positions a tab occupies; this +is relevant for indent-with-non-tab and when Git fixes tab-in-indent +errors. The default tab width is 8. Allowed values are 1 to 63.`, + Value: docvalues.ArrayValue{ + Separator: ",", + DuplicatesExtractor: &docvalues.SimpleDuplicatesExtractor, + SubValue: docvalues.OrValue{ + Values: []docvalues.DeprecatedValue{ + docvalues.EnumValue{ + EnforceValues: true, + Values: []docvalues.EnumString{ + docvalues.CreateEnumString("blank-at-eol"), + docvalues.CreateEnumString("space-before-tab"), + docvalues.CreateEnumString("indent-with-non-tab"), + docvalues.CreateEnumString("tab-in-indent"), + docvalues.CreateEnumString("blank-at-eof"), + docvalues.CreateEnumString("trailing-space"), + docvalues.CreateEnumString("cr-at-eol"), + }, + }, + docvalues.KeyEnumAssignmentValue{ + Separator: "=", + Values: map[docvalues.EnumString]docvalues.DeprecatedValue{ + docvalues.CreateEnumString("tabwidth"): docvalues.NumberRangeValue(1, 63), + }, + }, + }, + }, + }, + }, + "fsync": docvalues.DocumentationValue{ + Documentation: `A comma-separated list of components of the repository that +should be hardened via the core.fsyncMethod when created or +modified. You can disable hardening of any component by +prefixing it with a -. Items that are not hardened may be +lost in the event of an unclean\tsystem shutdown. Unless you +have special requirements, it is recommended that you leave +this option empty or pick one of committed, added, +or all. + +When this configuration is encountered, the set of components starts with +the platform default value, disabled components are removed, and additional +components are added. none resets the state so that the platform default +is ignored. + +The empty string resets the fsync configuration to the platform +default. The default on most platforms is equivalent to +core.fsync=committed,-loose-object, which has good performance, +but risks losing recent work in the event of an unclean system shutdown. + + +none clears the set of fsynced components. + +loose-object hardens objects added to the repo in loose-object form. + +pack hardens objects added to the repo in packfile form. + +pack-metadata hardens packfile bitmaps and indexes. + +commit-graph hardens the commit-graph file. + +index hardens the index when it is modified. + +objects is an aggregate option that is equivalent to +loose-object,pack. + +reference hardens references modified in the repo. + +derived-metadata is an aggregate option that is equivalent to +pack-metadata,commit-graph. + +committed is an aggregate option that is currently equivalent to +objects. This mode sacrifices some performance to ensure that work +that is committed to the repository with git commit or similar commands +is hardened. + +added is an aggregate option that is currently equivalent to +committed,index. This mode sacrifices additional performance to +ensure that the results of commands like git add and similar operations +are hardened. + +all is an aggregate option that syncs all individual components above.`, + Value: docvalues.ArrayValue{ + Separator: ",", + DuplicatesExtractor: &docvalues.SimpleDuplicatesExtractor, + SubValue: docvalues.PrefixWithMeaningValue{ + Prefixes: []docvalues.Prefix{ + { + Prefix: "-", + Meaning: "You can disable hardening of any component by prefixing it with a -", + }, + }, + SubValue: docvalues.EnumValue{ + EnforceValues: true, + Values: []docvalues.EnumString{ + docvalues.CreateEnumString("none"), + docvalues.CreateEnumString("loose-object"), + docvalues.CreateEnumString("pack"), + docvalues.CreateEnumString("pack-metadata"), + docvalues.CreateEnumString("commit-graph"), + docvalues.CreateEnumString("index"), + docvalues.CreateEnumString("objects"), + docvalues.CreateEnumString("reference"), + docvalues.CreateEnumString("derived-metadata"), + docvalues.CreateEnumString("committed"), + docvalues.CreateEnumString("added"), + docvalues.CreateEnumString("all"), + }, + }, + }, + }, + }, + "fsyncmethod": docvalues.DocumentationValue{ + Documentation: `A value indicating the strategy Git will use to harden repository data using fsync and related primitives. + +fsync uses the fsync() system call or platform equivalents. + +writeout-only issues pagecache writeback requests, but depending on the +filesystem and storage hardware, data added to the repository may not be +durable in the event of a system crash. This is the default mode on macOS. + +batch enables a mode that uses writeout-only flushes to stage multiple +updates in the disk writeback cache and then does a single full fsync of +a dummy file to trigger the disk cache flush at the end of the operation. + +Currently batch mode only applies to loose-object files. Other repository +data is made durable as if fsync was specified. This mode is expected to +be as safe as fsync on macOS for repos stored on HFS+ or APFS filesystems +and on Windows for repos stored on NTFS or ReFS filesystems.`, + Value: docvalues.EnumValue{ + Values: []docvalues.EnumString{ + docvalues.CreateEnumString("fsync"), + docvalues.CreateEnumString("writeout-only"), + docvalues.CreateEnumString("batch"), + }, + }, + }, + "fsyncobjectfiles": docvalues.DocumentationValue{ + Documentation: `This boolean will enable fsync() when writing object files. +This setting is deprecated. Use core.fsync instead. + +This setting affects data added to the Git repository in loose-object +form. When set to true, Git will issue an fsync or similar system call +to flush caches so that loose-objects remain consistent in the face +of a unclean system shutdown.`, + Value: BooleanField, + }, + "preloadindex": docvalues.DocumentationValue{ + Documentation: `Enable parallel index preload for operations like git diff + +This can speed up operations like git diff and git status especially +on filesystems like NFS that have weak caching semantics and thus +relatively high IO latencies. When enabled, Git will do the +index comparison to the filesystem data in parallel, allowing +overlapping IO’s. Defaults to true.`, + Value: BooleanField, + }, + "unsetenvvars": docvalues.DocumentationValue{ + Documentation: `Windows-only: comma-separated list of environment variables' +names that need to be unset before spawning any other process. +Defaults to PERL5LIB to account for the fact that Git for +Windows insists on using its own Perl interpreter.`, + Value: docvalues.ArrayValue{ + Separator: ",", + DuplicatesExtractor: &docvalues.SimpleDuplicatesExtractor, + SubValue: docvalues.StringValue{}, + }, + }, + "restrictinheritedhandles": docvalues.DocumentationValue{ + Documentation: `Windows-only: override whether spawned processes inherit only standard +file handles (stdin, stdout and stderr) or all handles. Can be +auto, true or false. Defaults to auto, which means true on +Windows 7 and later, and false on older Windows versions.`, + Value: docvalues.EnumValue{ + Values: []docvalues.EnumString{ + docvalues.CreateEnumString("auto"), + docvalues.CreateEnumString("true"), + docvalues.CreateEnumString("false"), + }, + }, + }, + "createobject": docvalues.DocumentationValue{ + Documentation: `You can set this to link, in which case a hardlink followed by +a delete of the source are used to make sure that object creation +will not overwrite existing objects. + +On some file system/operating system combinations, this is unreliable. +Set this config setting to rename there; however, this will remove the +check that makes sure that existing object files will not get overwritten.`, + Value: docvalues.EnumValue{ + Values: []docvalues.EnumString{ + docvalues.CreateEnumString("link"), + docvalues.CreateEnumString("rename"), + }, + }, + }, + "notesref": docvalues.DocumentationValue{ + Documentation: `When showing commit messages, also show notes which are stored in +the given ref. The ref must be fully qualified. If the given +ref does not exist, it is not an error but means that no +notes should be printed. + +This setting defaults to "refs/notes/commits", and it can be overridden by +the GIT_NOTES_REF environment variable. See git-notes[1].`, + Value: docvalues.StringValue{}, + }, + "commitgraph": docvalues.DocumentationValue{ + Documentation: `If true, then git will read the commit-graph file (if it exists) +to parse the graph structure of commits. Defaults to true. See git-commit-graph[1] for more information.`, + Value: BooleanField, + }, + "usereplacerefs": docvalues.DocumentationValue{ + Documentation: `If set to false, behave as if the --no-replace-objects +option was given on the command line. See git[1] and git-replace[1] for more information.`, + Value: BooleanField, + }, + "multipackindex": docvalues.DocumentationValue{ + Documentation: `Use the multi-pack-index file to track multiple packfiles using a +single index. See git-multi-pack-index[1] for more information. Defaults to true.`, + Value: BooleanField, + }, + // TODO: Check + "sparsecheckout": docvalues.DocumentationValue{ + Documentation: `Enable "sparse checkout" feature. See git-sparse-checkout[1] for more information.`, + Value: docvalues.StringValue{}, + }, + "sparsecheckoutcone": docvalues.DocumentationValue{ + Documentation: `Enables the "cone mode" of the sparse checkout feature. When the +sparse-checkout file contains a limited set of patterns, this +mode provides significant performance advantages. The "non-cone +mode" can be requested to allow specifying more flexible +patterns by setting this variable to false. See +git-sparse-checkout[1] for more information.`, + Value: docvalues.StringValue{}, + }, + "abbrev": docvalues.DocumentationValue{ + Documentation: `Set the length object names are abbreviated to. If +unspecified or set to "auto", an appropriate value is +computed based on the approximate number of packed objects +in your repository, which hopefully is enough for +abbreviated object names to stay unique for some time. +If set to "no", no abbreviation is made and the object names +are shown in their full length. +The minimum length is 4.`, + Value: docvalues.OrValue{ + Values: []docvalues.DeprecatedValue{ + docvalues.EnumValue{ + Values: []docvalues.EnumString{ + docvalues.CreateEnumString("auto"), + docvalues.CreateEnumString("no"), + }, + }, + docvalues.NumberValue{ + Min: &four, + }, + }, + }, + }, + "maxtreedepth": docvalues.DocumentationValue{ + Documentation: `The maximum depth Git is willing to recurse while traversing a +tree (e.g., "a/b/cde/f" has a depth of 4). This is a fail-safe +to allow Git to abort cleanly, and should not generally need to +be adjusted. When Git is compiled with MSVC, the default is 512. +Otherwise, the default is 2048.`, + Value: docvalues.PositiveNumberValue(), + }, + }, +} diff --git a/server/handlers/gitconfig/fields/values-integer.go b/server/handlers/gitconfig/fields/values-integer.go new file mode 100644 index 0000000..45357a6 --- /dev/null +++ b/server/handlers/gitconfig/fields/values-integer.go @@ -0,0 +1,98 @@ +package fields + +import ( + docvalues "config-lsp/doc-values" + "fmt" + "regexp" + "strconv" + + protocol "github.com/tliron/glsp/protocol_3_16" +) + +var isJustDigitsPattern = regexp.MustCompile(`^\d+$`) +var dataAmountCheckPattern = regexp.MustCompile(`(?i)^(\d+)([kmg])$`) + +type InvalidIntegerError struct{} + +func (e InvalidIntegerError) Error() string { + return "Integer is invalid. It must be in the form of: [k|m|g]" +} + +type IntegerValue struct{} + +func (v IntegerValue) GetTypeDescription() []string { + return []string{"Integer"} +} + +func (v IntegerValue) DeprecatedCheckIsValid(value string) []*docvalues.InvalidValue { + if !dataAmountCheckPattern.MatchString(value) { + return []*docvalues.InvalidValue{ + { + Err: InvalidIntegerError{}, + Start: 0, + End: uint32(len(value)), + }, + } + } + + return nil +} + +func calculateLineToKilobyte(value string, unit string) string { + val, err := strconv.Atoi(value) + + if err != nil { + return "" + } + + switch unit { + case "K": + return strconv.Itoa(val * 1024) + case "m": + return strconv.Itoa(val * 1024 * 1024) + case "g": + return strconv.Itoa(val * 1024 * 1024 * 1024) + default: + return "" + } +} + +func (v IntegerValue) DeprecatedFetchCompletions(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: fmt.Sprintf("scale %d by x1024", line), + }, + protocol.CompletionItem{ + Label: line + "m", + Kind: &kind, + Documentation: fmt.Sprintf("scale %d by x1024x1024", line), + }, + protocol.CompletionItem{ + Label: line + "g", + Kind: &kind, + Documentation: fmt.Sprintf("scale %d by x1024x1024x1024", line), + }, + ) + } + + if line == "" || isJustDigitsPattern.MatchString(line) { + completions = append( + completions, + docvalues.GenerateBase10Completions(line)..., + ) + } + + return completions +} + +func (v IntegerValue) DeprecatedFetchHoverInfo(line string, cursor uint32) []string { + return []string{} +} diff --git a/server/handlers/gitconfig/fields/values-pathname.go b/server/handlers/gitconfig/fields/values-pathname.go new file mode 100644 index 0000000..3378bae --- /dev/null +++ b/server/handlers/gitconfig/fields/values-pathname.go @@ -0,0 +1,53 @@ +package fields + +import ( + docvalues "config-lsp/doc-values" + "os" + "path" + "strings" +) + +type PathnameValue struct { + *docvalues.PathValue +} + +// TODO: Check if this works +func (v PathnameValue) createSystemPath(value string) string { + if strings.HasPrefix(value, "~/") { + // Path of current user + + home, err := os.UserHomeDir() + + if err != nil { + return value + } + + relativePath := strings.TrimPrefix(value, "~/") + return path.Join(home, relativePath) + } + + if strings.HasPrefix(value, "~") { + // Path of another user + + // TODO: Check how this is supposed to work. + // Why would you want to get the home directory of another user? + + return value + + // nextSlash := strings.Index(value, "/") + // + // if nextSlash == -1 { + // // Path missing + // return value + // } + // + // user := value[1:nextSlash] + // relativePath := value[nextSlash+1:] + } + + if strings.HasPrefix(value, "%(prefix)/") { + // yeah hell no + } + + return value +} diff --git a/server/handlers/gitconfig/fields/values.go b/server/handlers/gitconfig/fields/values.go new file mode 100644 index 0000000..a76b821 --- /dev/null +++ b/server/handlers/gitconfig/fields/values.go @@ -0,0 +1,88 @@ +package fields + +import ( + docvalues "config-lsp/doc-values" + "config-lsp/utils" +) + +var BooleanField = docvalues.EnumValue{ + EnforceValues: true, + Values: []docvalues.EnumString{ + docvalues.CreateEnumString("yes"), + docvalues.CreateEnumString("on"), + docvalues.CreateEnumString("true"), + docvalues.CreateEnumString("1"), + + docvalues.CreateEnumString("no"), + docvalues.CreateEnumString("off"), + docvalues.CreateEnumString("false"), + docvalues.CreateEnumString("0"), + }, +} + +var ColorField = docvalues.ArrayValue{ + DuplicatesExtractor: &docvalues.SimpleDuplicatesExtractor, + Separator: " ", + SubValue: docvalues.OrValue{ + Values: []docvalues.DeprecatedValue{ + docvalues.NumberRangeValue(0, 255), + docvalues.HexColorValue{Allow12Bit: true}, + docvalues.EnumValue{ + EnforceValues: true, + Values: utils.MergeSlices( + fetchColors(), + fetchAttributes(), + []docvalues.EnumString{ + docvalues.CreateEnumString("normal"), + docvalues.CreateEnumString("default"), + docvalues.CreateEnumString("reset"), + }, + ), + }, + }, + }, +} + +func fetchColors() []docvalues.EnumString { + colors := []string{ + "black", + "red", + "green", + "yellow", + "blue", + "magenta", + "cyan", + "white", + } + + enums := make([]docvalues.EnumString, 0) + + for _, color := range colors { + enums = append(enums, docvalues.CreateEnumString(color)) + enums = append(enums, docvalues.CreateEnumString("bright"+color)) + } + + return enums +} + +func fetchAttributes() []docvalues.EnumString { + attributes := []string{ + "bold", + "dim", + "ul", + "blink", + "reverse", + "italic", + "strike", + } + + enums := make([]docvalues.EnumString, 0) + + for _, attribute := range attributes { + enums = append(enums, docvalues.CreateEnumString(attribute)) + enums = append(enums, docvalues.CreateEnumString("no"+attribute)) + enums = append(enums, docvalues.CreateEnumString("no-"+attribute)) + } + + return enums +} diff --git a/server/utils/slices.go b/server/utils/slices.go index 0b74dab..d83e22e 100644 --- a/server/utils/slices.go +++ b/server/utils/slices.go @@ -141,3 +141,13 @@ func MergeMaps[T comparable, O any](maps ...map[T]O) map[T]O { return result } + +func MergeSlices[T any](slices ...[]T) []T { + result := make([]T, 0) + + for _, slice := range slices { + result = append(result, slice...) + } + + return result +}