Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion internal/buffer/autocomplete.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"io/fs"
"os"
"path/filepath"
"sort"
"strings"

Expand Down Expand Up @@ -106,8 +107,16 @@ func FileComplete(b *Buffer) ([]string, []string) {
c := b.GetActiveCursor()
input, argstart := b.GetArg()

// Windows accepts both separators, so keep completing with the one that is
// already in use instead of mixing them
sep := string(os.PathSeparator)
dirs := strings.Split(input, sep)
if i := strings.LastIndexAny(input, "/"+sep); i >= 0 {
sep = input[i : i+1]
}

// and normalize the input before splitting it, otherwise a forward slash
// separated path is treated as a single name
dirs := strings.Split(filepath.ToSlash(input), "/")

var files []fs.DirEntry
var err error
Expand Down
38 changes: 38 additions & 0 deletions internal/buffer/autocomplete_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package buffer

import (
"os"
"path/filepath"
"testing"

"github.com/micro-editor/micro/v2/internal/util"
"github.com/stretchr/testify/assert"
)

func TestFileComplete(t *testing.T) {
dir := t.TempDir()
f, err := os.Create(filepath.Join(dir, "foo.txt"))
if err != nil {
t.Fatal(err)
}
f.Close()
if err := os.Mkdir(filepath.Join(dir, "bar"), 0700); err != nil {
t.Fatal(err)
}

complete := func(input string) []string {
b := NewBufferFromString(input, "", BTDefault)
b.GetActiveCursor().X = util.CharacterCountInString(input)
_, suggestions := FileComplete(b)
return suggestions
}

// Both separators are valid on Windows, so completion has to work with
// either one of them and has to stay with the one already in use.
for _, sep := range []string{"/", string(os.PathSeparator)} {
prefix := "open " + filepath.ToSlash(dir) + sep

assert.Equal(t, []string{"foo.txt"}, complete(prefix+"fo"))
assert.Equal(t, []string{"bar" + sep}, complete(prefix+"ba"))
}
}
2 changes: 1 addition & 1 deletion internal/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ func ReplaceHome(path string) (string, error) {
var userData *user.User
var err error

homeString := strings.Split(path, "/")[0]
homeString := strings.Split(filepath.ToSlash(path), "/")[0]
if homeString == "~" {
userData, err = user.Current()
if err != nil {
Expand Down
26 changes: 26 additions & 0 deletions internal/util/util_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package util

import (
"os"
"os/user"
"testing"

"github.com/stretchr/testify/assert"
Expand All @@ -13,6 +15,30 @@ func TestStringWidth(t *testing.T) {
assert.Equal(t, 26, n)
}

func TestReplaceHome(t *testing.T) {
usr, err := user.Current()
if err != nil {
t.Fatal(err)
}
home := usr.HomeDir

path, err := ReplaceHome("~")
assert.NoError(t, err)
assert.Equal(t, home, path)

// Both separators are valid on Windows, so `~` has to be recognized
// regardless of which one follows it.
for _, sep := range []string{"/", string(os.PathSeparator)} {
path, err = ReplaceHome("~" + sep + "foo.txt")
assert.NoError(t, err)
assert.Equal(t, home+sep+"foo.txt", path)
}

path, err = ReplaceHome("foo~bar")
assert.NoError(t, err)
assert.Equal(t, "foo~bar", path)
}

func TestSliceVisualEnd(t *testing.T) {
s := []byte("\thello")
slc, n, _ := SliceVisualEnd(s, 2, 4)
Expand Down