Repository: zyedidia/micro
File: internal/util/util.go (Go)

Code before:
// Special cases like Windows Absolute path (C:\myfile.txt:10:5) are handled correctly.
func GetPathAndCursorPosition(path string) (string, []string) {
	re := regexp.MustCompile(`([\s\S]+?)(?::(\d+))(?::(\d+))?$`)
	match := re.FindStringSubmatch(path)
	// no lines/columns were specified in the path, return just the path with no cursor location
	if len(match) == 0 {
		return path, nil
	} else if match[len(match)-1] != "" {
		// if the last capture group match isn't empty then both line and column were provided
		return match[1], match[2:]
	}
	// if it was empty, then only a line was provided, so default to column 0
	return match[1], []string{match[2], "0"}
}

// GetModTime returns the last modification time for a given file
func GetModTime(path string) (time.Time, error) {
	info, err := os.Stat(path)
	if err != nil {
		return time.Now(), err
	}
	return info.ModTime(), nil
}

func AppendBackupSuffix(path string) string {
	return path + ".micro-backup"
}

func HashStringMd5(str string) string {
	return fmt.Sprintf("%x", md5.Sum([]byte(str)))
}

// EscapePathUrl encodes the path in URL query form
func EscapePathUrl(path string) string {
	return url.QueryEscape(filepath.ToSlash(path))
}

// EscapePathLegacy replaces every path separator in a given path with a %
func EscapePathLegacy(path string) string {
	path = filepath.ToSlash(path)
	if runtime.GOOS == "windows" {
		// ':' is not valid in a path name on Windows but is ok on Unix
		path = strings.ReplaceAll(path, ":", "%")
	}
	return strings.ReplaceAll(path, "/", "%")
}

// DetermineEscapePath escapes a path, determining whether it should be escaped
// using URL encoding (preferred, since it encodes unambiguously) or
// legacy encoding with '%' (for backward compatibility, if the legacy-escaped
// path exists in the given directory).

Review comment (suggestion):
We could probably use https://pkg.go.dev/encoding/hex#EncodeToString instead (although `fmt.Sprintf` is probably fine too).

Code after:
// Special cases like Windows Absolute path (C:\myfile.txt:10:5) are handled correctly.
func GetPathAndCursorPosition(path string) (string, []string) {
	re := regexp.MustCompile(`([\s\S]+?)(?::(\d+))(?::(\d+))?$`)
	match := re.FindStringSubmatch(path)
	// no lines/columns were specified in the path, return just the path with no cursor location
	if len(match) == 0 {
		return path, nil
	} else if match[len(match)-1] != "" {
		// if the last capture group match isn't empty then both line and column were provided
		return match[1], match[2:]
	}
	// if it was empty, then only a line was provided, so default to column 0
	return match[1], []string{match[2], "0"}
}

// GetModTime returns the last modification time for a given file
func GetModTime(path string) (time.Time, error) {
	info, err := os.Stat(path)
	if err != nil {
		return time.Now(), err
	}
	return info.ModTime(), nil
}

func HashStringMd5(str string) string {
	return fmt.Sprintf("%x", md5.Sum([]byte(str)))
}

// EscapePathUrl encodes the path in URL query form
func EscapePathUrl(path string) string {
	return url.QueryEscape(filepath.ToSlash(path))
}

// EscapePathLegacy replaces every path separator in a given path with a %
func EscapePathLegacy(path string) string {
	path = filepath.ToSlash(path)
	if runtime.GOOS == "windows" {
		// ':' is not valid in a path name on Windows but is ok on Unix
		path = strings.ReplaceAll(path, ":", "%")
	}
	return strings.ReplaceAll(path, "/", "%")
}

// DetermineEscapePath escapes a path, determining whether it should be escaped
// using URL encoding (preferred, since it encodes unambiguously) or
// legacy encoding with '%' (for backward compatibility, if the legacy-escaped
// path exists in the given directory).
// In case the length of the escaped path (plus the backup extension) exceeds
// the filename length limit, a hash of the path is returned instead. In such
// case the second return value is the name of a file the original path should
// be saved to (since the original path cannot be derived from its hash).