github.com/jmigpin/editor@v1.6.0/core/lsproto/registration.go (about)

     1  package lsproto
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/jmigpin/editor/util/osutil"
     8  	"github.com/jmigpin/editor/util/parseutil"
     9  )
    10  
    11  //----------
    12  
    13  type Registration struct {
    14  	Language string
    15  	Exts     []string
    16  	Network  string // {stdio,tcpclient,tcp{templatevals:.Addr}}
    17  	Cmd      string
    18  	Optional []string // {stderr,nogotoimpl}
    19  }
    20  
    21  func NewRegistration(s string) (*Registration, error) {
    22  	reg, err := parseRegistration(s)
    23  	if err != nil {
    24  		return nil, err
    25  	}
    26  	return reg, nil
    27  }
    28  
    29  func (reg *Registration) HasOptional(s string) bool {
    30  	for _, v := range reg.Optional {
    31  		if v == s {
    32  			return true
    33  		}
    34  	}
    35  
    36  	// handle backwards compatibility (keep old defaults)
    37  	if s == "nogotoimpl" {
    38  		// - these won't use gotoimplementation, and there is no way to enable it (it would just be slower)
    39  		// - other languages (ex:c/c++) will use gotoimplementation
    40  		languagesToBypass := "go python javascript"
    41  		if strings.Contains(languagesToBypass, strings.ToLower(reg.Language)) {
    42  			return true
    43  		}
    44  	}
    45  
    46  	return false
    47  }
    48  
    49  func (reg *Registration) String() string {
    50  	return stringifyRegistration(reg)
    51  }
    52  
    53  //----------
    54  
    55  func parseRegistration(s string) (*Registration, error) {
    56  	fields, err := parseutil.ParseFields(s, ',')
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  
    61  	minFields := 4
    62  	if len(fields) < minFields {
    63  		return nil, fmt.Errorf("expecting at least %v fields: %v", minFields, len(fields))
    64  	}
    65  
    66  	reg := &Registration{}
    67  	reg.Language = fields[0]
    68  	if reg.Language == "" {
    69  		return nil, fmt.Errorf("empty language")
    70  	}
    71  	reg.Exts = strings.Split(fields[1], " ")
    72  	reg.Network = fields[2]
    73  	reg.Cmd = fields[3]
    74  	if len(fields) > 4 {
    75  		reg.Optional = strings.Split(fields[4], " ")
    76  	}
    77  
    78  	return reg, nil
    79  }
    80  
    81  func stringifyRegistration(reg *Registration) string {
    82  	exts := strings.Join(reg.Exts, " ")
    83  	if len(reg.Exts) >= 2 {
    84  		exts = fmt.Sprintf("%q", exts)
    85  	}
    86  
    87  	cmd := reg.Cmd
    88  	cmd2 := parseutil.AddEscapes(cmd, '\\', " ,")
    89  	if cmd != cmd2 {
    90  		cmd = fmt.Sprintf("%q", cmd)
    91  	}
    92  
    93  	u := []string{
    94  		reg.Language,
    95  		exts,
    96  		reg.Network,
    97  		cmd,
    98  	}
    99  	if len(reg.Optional) >= 1 {
   100  		h := strings.Join(reg.Optional, " ")
   101  		if len(reg.Optional) >= 2 {
   102  			h = fmt.Sprintf("%q", h)
   103  		}
   104  		u = append(u, h)
   105  	}
   106  	return strings.Join(u, ",")
   107  }
   108  
   109  //----------
   110  
   111  func RegistrationExamples() []string {
   112  	return []string{
   113  		GoplsRegistration(false, false, false),
   114  		GoplsRegistration(false, true, false),
   115  		cLangRegistration(false),
   116  		"python,.py,stdio,pylsp",
   117  		"python,.py,tcpclient,127.0.0.1:9000",
   118  		"python,.py,stdio,pylsp,\"stderr nogotoimpl\"",
   119  	}
   120  }
   121  
   122  //----------
   123  
   124  func GoplsRegistration(stderr bool, tcp bool, trace bool) string {
   125  	cmd := osutil.ExecName("gopls")
   126  	if trace {
   127  		cmd += " -v"
   128  	}
   129  	cmd += " serve"
   130  	if trace {
   131  		cmd += " -rpc.trace"
   132  	}
   133  	net := "stdio"
   134  	if tcp {
   135  		net = "tcp"
   136  		cmd += " -listen={{.Addr}}"
   137  	}
   138  
   139  	errOut := ""
   140  	if net == "stdio" {
   141  		if stderr {
   142  			//errOut = ",stderr"
   143  			// DEBUG
   144  			//errOut = ",stderrmanmsg"
   145  		}
   146  	}
   147  
   148  	return fmt.Sprintf("go,.go,%v,%q%s", net, cmd, errOut)
   149  }
   150  
   151  func cLangRegistration(stderr bool) string {
   152  	ext := ".c .h .cpp .hpp .cc"
   153  	cmd := osutil.ExecName("clangd")
   154  	errOut := ""
   155  	if stderr {
   156  		//errOut = ",stderr"
   157  	}
   158  	return fmt.Sprintf("cpp,%q,stdio,%q%s", ext, cmd, errOut)
   159  }
   160  
   161  func pylspRegistration(stderr bool, tcp bool) string {
   162  	cmd := osutil.ExecName("pylsp")
   163  	net := "stdio"
   164  	if tcp {
   165  		net = "tcp"
   166  		cmd += " --tcp"
   167  		cmd += " --host={{.Host}}"
   168  		cmd += " --port={{.Port}}"
   169  	}
   170  	errOut := ""
   171  	if stderr {
   172  		errOut = ",stderr"
   173  	}
   174  	return fmt.Sprintf("python,.py,%s,%q%s", net, cmd, errOut)
   175  }