diff --git a/src/encoding/encoding.go b/src/encoding/encoding.go index ae6a6fc..dd74b85 100644 --- a/src/encoding/encoding.go +++ b/src/encoding/encoding.go @@ -1,11 +1,9 @@ package encoding import ( - "errors" "strings" "unicode/utf8" - "github.com/mushroomsir/iconv" "github.com/saintfish/chardet" ) @@ -19,46 +17,56 @@ func DetectCharset(content []byte) (string, error) { return strings.ToUpper(result.Charset), nil } -func ToUTF8(content []byte, ignoreInvalidITF8Chars ...bool) (string, error) { - ignore := false - if len(ignoreInvalidITF8Chars) > 0 { - ignore = ignoreInvalidITF8Chars[0] +func ToUTF8(content string) []byte { + b := make([]byte, len(content)) + i := 0 + for _, r := range content { + i += utf8.EncodeRune(b[i:], r) } - cs, err := DetectCharset(content) - if err != nil { - if !ignore { - return "", err - } - cs = "UTF-8" - } - - bs := string(content) - if ignore { - if !utf8.ValidString(bs) { - v := make([]rune, 0, len(bs)) - for i, r := range bs { - if r == utf8.RuneError { - _, size := utf8.DecodeRuneInString(bs[i:]) - if size == 1 { - continue - } - } - v = append(v, r) - } - bs = string(v) - } - } - - if cs == "UTF-8" { - return bs, nil - } - - converter, err := iconv.NewConverter(cs, "UTF-8") - if err != nil { - err = errors.New("Failed to convert " + cs + " to UTF-8: " + err.Error()) - return bs, err - } - - return converter.ConvertString(bs) + return b[:i] } + +// func ToUTF8(content []byte, ignoreInvalidITF8Chars ...bool) (string, error) { +// ignore := false +// if len(ignoreInvalidITF8Chars) > 0 { +// ignore = ignoreInvalidITF8Chars[0] +// } + +// cs, err := DetectCharset(content) +// if err != nil { +// if !ignore { +// return "", err +// } +// cs = "UTF-8" +// } + +// bs := string(content) +// if ignore { +// if !utf8.ValidString(bs) { +// v := make([]rune, 0, len(bs)) +// for i, r := range bs { +// if r == utf8.RuneError { +// _, size := utf8.DecodeRuneInString(bs[i:]) +// if size == 1 { +// continue +// } +// } +// v = append(v, r) +// } +// bs = string(v) +// } +// } + +// if cs == "UTF-8" { +// return bs, nil +// } + +// converter, err := iconv.NewConverter(cs, "UTF-8") +// if err != nil { +// err = errors.New("Failed to convert " + cs + " to UTF-8: " + err.Error()) +// return bs, err +// } + +// return converter.ConvertString(bs) +// } diff --git a/src/go.mod b/src/go.mod index 890913a..9167401 100644 --- a/src/go.mod +++ b/src/go.mod @@ -8,14 +8,10 @@ require ( github.com/blang/semver v3.5.1+incompatible github.com/coreybutler/go-fsutil v1.2.0 github.com/coreybutler/go-where v1.0.1 - github.com/mushroomsir/iconv v0.0.0-20180525091039-6f95241e51c8 + github.com/djimenez/iconv-go v0.0.0-20160305225143-8960e66bd3da github.com/olekukonko/tablewriter v0.0.5 github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d golang.org/x/sys v0.3.0 ) -require ( - github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/stretchr/testify v1.8.1 // indirect - golang.org/x/text v0.3.2 // indirect -) +require github.com/mattn/go-runewidth v0.0.9 // indirect diff --git a/src/go.sum b/src/go.sum index 620fef8..cd71560 100644 --- a/src/go.sum +++ b/src/go.sum @@ -4,26 +4,14 @@ github.com/coreybutler/go-fsutil v1.2.0 h1:kbm62NSofawglUppEOhpHC3NDf/J7ZpguBirB github.com/coreybutler/go-fsutil v1.2.0/go.mod h1:B+6ufEkkRZgFwyR2sHEVG9dMzVBU3GbyGyYmCq7YkEk= github.com/coreybutler/go-where v1.0.1 h1:O88ndeqvrmuoq/2OfT+irLfzsjGrextvaNXE5pSEXUo= github.com/coreybutler/go-where v1.0.1/go.mod h1:IqV4saJiDXdNJURfTfVRywDHvY1IG5F+GXb2kmnmEe8= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/djimenez/iconv-go v0.0.0-20160305225143-8960e66bd3da h1:0qwwqQCLOOXPl58ljnq3sTJR7yRuMolM02vjxDh4ZVE= +github.com/djimenez/iconv-go v0.0.0-20160305225143-8960e66bd3da/go.mod h1:ns+zIWBBchgfRdxNgIJWn2x6U95LQchxeqiN5Cgdgts= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mushroomsir/iconv v0.0.0-20180525091039-6f95241e51c8 h1:qnum99kMXmcX8kwIvlHxMWeYCGx2h16gfIxyP1IhHjA= -github.com/mushroomsir/iconv v0.0.0-20180525091039-6f95241e51c8/go.mod h1:a1NpVA8oEJfkxTRw/RgKXnQbW/oIDxdkW5FTlQ1tFrQ= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA= github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/zmb3/gogetdoc v0.0.0-20190228002656-b37376c5da6a/go.mod h1:ofmGw6LrMypycsiWcyug6516EXpIxSbZ+uI9ppGypfY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -37,13 +25,8 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181207195948-8634b1ecd393/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190825031127-d72b05d2b1b6/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/src/nvm.go b/src/nvm.go index b25d68d..2559f72 100644 --- a/src/nvm.go +++ b/src/nvm.go @@ -16,6 +16,7 @@ import ( "strings" "syscall" "time" + "unsafe" "nvm/arch" "nvm/encoding" @@ -217,6 +218,7 @@ func getVersion(version string, cpuarch string, localInstallsOnly ...bool) (stri // If user specifies "latest" version, find out what version is if version == "latest" || version == "node" { version = getLatest() + fmt.Println(version) } if version == "lts" { @@ -599,7 +601,7 @@ func findLatestSubVersion(version string, localOnly ...bool) string { url := web.GetFullNodeUrl("latest-v" + version + ".x" + "/SHASUMS256.txt") content := web.GetRemoteTextFile(url) re := regexp.MustCompile("node-v(.+)+msi") - reg := regexp.MustCompile("node-v|-x.+") + reg := regexp.MustCompile("node-v|-[xa].+") latest := reg.ReplaceAllString(re.FindString(content), "") return latest } @@ -914,7 +916,7 @@ func checkLocalEnvironment() { username := strings.Split(user.Username, "\\") fmt.Printf("%v is not using admin or elevated rights", username[len(username)-1]) if devmode == "ON" { - fmt.Printf(", but windows developer mode is enabled.\nMost commands will still work unless %v lacks rights to modify %v.\n", username[len(username)-1], current) + fmt.Printf(", but windows developer mode is\nenabled. Most commands will still work unless %v lacks rights to\nmodify the %v symlink.\n", username[len(username)-1], current) } else { fmt.Println(".") } @@ -929,6 +931,36 @@ func checkLocalEnvironment() { fmt.Println(err) } + kernel32 := syscall.NewLazyDLL("kernel32.dll") + handle, _, err := kernel32.NewProc("GetStdHandle").Call(uintptr(0xfffffff5)) // get handle for console input + if err != nil && err.Error() != "The operation completed successfully." { + fmt.Printf("Error getting console handle: %v", err) + } else { + var mode uint32 + result, _, _ := kernel32.NewProc("GetConsoleMode").Call(handle, uintptr(unsafe.Pointer(&mode))) + if result != 0 { + var title [256]uint16 + _, _, err := kernel32.NewProc("GetConsoleTitleW").Call(uintptr(unsafe.Pointer(&title)), uintptr(len(title))) + if err != nil && err.Error() != "The operation completed successfully." { + fmt.Printf("Error getting console title: %v", err) + } else { + consoleTitle := syscall.UTF16ToString(title[:]) + + if !strings.Contains(strings.ToLower(consoleTitle), "command prompt") && !strings.Contains(strings.ToLower(consoleTitle), "powershell") { + problems = append(problems, fmt.Sprintf("\"%v\" is not an officially supported shell. Some features may not work as expected.\n", consoleTitle)) + } + + fmt.Printf("\n%v", consoleTitle) + } + } + } + + // SHELL in Linux + // TERM in Windows + // COMSPEC in Windows provides the terminal path + // shell := os.Getenv("ConEmuANSI") + // fmt.Printf("Shell: %v\n", shell) + // Display developer mode status if !admin { // if devmode == "ON" { @@ -948,12 +980,22 @@ func checkLocalEnvironment() { path = "UNKNOWN: " + err.Error() } - fmt.Printf("\nPath: %v\nVersion: %v\nNVM_HOME: %v\nNVM_SYMLINK: %v\n", path, NvmVersion, home, symlink) + out := "Unknown" + output, err := exec.Command(os.Getenv("NVM_SYMLINK")+"\\node.exe", "-v").Output() + if err == nil { + out = string(output) + } + + fmt.Printf("\nPath: %v\nNVM4W Version: %v\nNVM_HOME: %v\nNVM_SYMLINK: %v\n\nActive Node.js Version: %v", path, NvmVersion, home, symlink, out) if !nvmsymlinkfound { problems = append(problems, "The NVM4W symlink ("+env.symlink+") was not found in the PATH environment variable.") } + if home == symlink { + problems = append(problems, "NVM_HOME and NVM_SYMLINK cannot be the same value ("+symlink+"). Change NVM_SYMLINK.") + } + nodelist := web.Ping(web.GetFullNodeUrl("index.json")) if !nodelist { if len(env.node_mirror) > 0 && env.node_mirror != "none" { @@ -978,9 +1020,23 @@ func checkLocalEnvironment() { if len(problems) == 0 { fmt.Println("\n" + "No problems detected.") } else { - fmt.Println("\n" + "Problems Detected:") + // fmt.Println("") + // table := tablewriter.NewWriter(os.Stdout) + // table.SetHeader([]string{"#", "Problems Detected"}) + // table.SetColMinWidth(1, 40) + // table.SetAutoWrapText(false) + // // table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) + // // table.SetAlignment(tablewriter.ALIGN_LEFT) + // // table.SetCenterSeparator("|") + // data := make([][]string, 0) + // for i := 0; i < len(problems); i++ { + // data = append(data, []string{fmt.Sprintf(" %v ", i+1), problems[i]}) + // } + // table.AppendBulk(data) // Add Bulk Data + // table.Render() + fmt.Println("\nPROBLEMS DETECTED\n-----------------") for _, p := range problems { - fmt.Println(" - " + p) + fmt.Println(p + "\n") } } @@ -993,7 +1049,7 @@ func help() { fmt.Println(" ") fmt.Println(" nvm arch : Show if node is running in 32 or 64 bit mode.") fmt.Println(" nvm current : Display active version.") - fmt.Println(" nvm debug : Check the NVM4W process for known problems (experimental troubleshooter).") + fmt.Println(" nvm debug : Check the NVM4W process for known problems (troubleshooter).") fmt.Println(" nvm install [arch] : The version can be a specific version, \"latest\" for the latest current version, or \"lts\" for the") fmt.Println(" most recent LTS version. Optionally specify whether to install the 32 or 64 bit version (defaults") fmt.Println(" to system arch). Set [arch] to \"all\" to install 32 AND 64 bit versions.") @@ -1028,7 +1084,7 @@ func checkVersionExceedsLatest(version string) bool { url := web.GetFullNodeUrl("latest/SHASUMS256.txt") content := web.GetRemoteTextFile(url) re := regexp.MustCompile("node-v(.+)+msi") - reg := regexp.MustCompile("node-v|-x.+") + reg := regexp.MustCompile("node-v|-[xa].+") latest := reg.ReplaceAllString(re.FindString(content), "") var vArr = strings.Split(version, ".") var lArr = strings.Split(latest, ".") @@ -1073,7 +1129,7 @@ func getLatest() string { url := web.GetFullNodeUrl("latest/SHASUMS256.txt") content := web.GetRemoteTextFile(url) re := regexp.MustCompile("node-v(.+)+msi") - reg := regexp.MustCompile("node-v|-x.+") + reg := regexp.MustCompile("node-v|-[xa].+") return reg.ReplaceAllString(re.FindString(content), "") } @@ -1199,13 +1255,13 @@ func getProcessPermissions() (admin bool, elevated bool, err error) { } func encode(val string) string { - converted, err := encoding.ToUTF8([]byte(val)) - if err != nil { - fmt.Printf("WARNING: [encoding error] - %v\n", err.Error()) - return val - } + converted := encoding.ToUTF8(val) + // if err != nil { + // fmt.Printf("WARNING: [encoding error] - %v\n", err.Error()) + // return val + // } - return converted + return string(converted) } // ===============================================================