github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/utils/spellcheck/spellcheck.go (about)

     1  package spellcheck
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"regexp"
     8  
     9  	"github.com/lmorg/murex/lang"
    10  	"github.com/lmorg/murex/lang/types"
    11  	"github.com/lmorg/murex/shell/autocomplete"
    12  	"github.com/lmorg/murex/utils"
    13  	"github.com/lmorg/murex/utils/spellcheck/userdictionary"
    14  )
    15  
    16  var rxRemoveEsc = regexp.MustCompile(`\\[a-zA-Z]`)
    17  
    18  // String spellchecks a line of type string and returns an underlined (ANSI escaped) string
    19  func String(line string) (string, error) {
    20  	enabled, err := lang.ShellProcess.Config.Get("shell", "spellcheck-enabled", types.Boolean)
    21  	if err != nil || !enabled.(bool) {
    22  		return line, err
    23  	}
    24  
    25  	block, err := lang.ShellProcess.Config.Get("shell", "spellcheck-func", types.CodeBlock)
    26  	if err != nil || len(block.(string)) == 0 {
    27  		return line, err
    28  	}
    29  
    30  	check := rxRemoveEsc.ReplaceAll([]byte(line), []byte{' '})
    31  
    32  	fork := lang.ShellProcess.Fork(lang.F_FUNCTION | lang.F_BACKGROUND | lang.F_CREATE_STDIN | lang.F_CREATE_STDOUT | lang.F_CREATE_STDERR)
    33  	fork.Name.Set("(spellcheck)")
    34  	fork.Stdin.SetDataType(types.Generic)
    35  	_, err = fork.Stdin.Writeln(check)
    36  	if err != nil {
    37  		return line, err
    38  	}
    39  
    40  	_, err = fork.Execute([]rune(block.(string)))
    41  	if err != nil {
    42  		return line, err
    43  	}
    44  
    45  	b, err := fork.Stderr.ReadAll()
    46  	if err != nil {
    47  		return line, err
    48  	}
    49  	if len(b) != 0 {
    50  		return line, fmt.Errorf("`config get shell spellcheck-func` STDERR: %s", string(utils.CrLfTrim(b)))
    51  	}
    52  
    53  	err = fork.Stdout.ReadArray(context.Background(), func(bWord []byte) {
    54  		if len(bWord) == 0 {
    55  			return
    56  		}
    57  
    58  		sWord := string(bytes.TrimSpace(bWord))
    59  
    60  		if (*autocomplete.GlobalExes.Get())[sWord] || lang.MxFunctions.Exists(sWord) || lang.GoFunctions[sWord] != nil || lang.GlobalAliases.Exists(sWord) {
    61  			return
    62  		}
    63  
    64  		v, _ := lang.ShellProcess.Variables.GetValue(sWord)
    65  		if v != nil {
    66  			return
    67  		}
    68  
    69  		if userdictionary.IsInDictionary(sWord) {
    70  			return
    71  		}
    72  
    73  		highlighter(&line, []rune(sWord), highlight)
    74  	})
    75  
    76  	return line, err
    77  }