mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-05 03:17:50 +08:00
parent
d149955c1d
commit
7209b48bf8
|
@ -40,6 +40,7 @@ var defaultBindings = map[bufferMode]map[Key]string{
|
||||||
Key{Up, 0}: "start-history",
|
Key{Up, 0}: "start-history",
|
||||||
Key{'N', Ctrl}: "start-navigation",
|
Key{'N', Ctrl}: "start-navigation",
|
||||||
Key{'H', Ctrl}: "start-history-listing",
|
Key{'H', Ctrl}: "start-history-listing",
|
||||||
|
Key{'L', Ctrl}: "start-location",
|
||||||
},
|
},
|
||||||
modeCommand: map[Key]string{
|
modeCommand: map[Key]string{
|
||||||
Default: "default-command",
|
Default: "default-command",
|
||||||
|
@ -85,6 +86,14 @@ var defaultBindings = map[bufferMode]map[Key]string{
|
||||||
modeHistoryListing: map[Key]string{
|
modeHistoryListing: map[Key]string{
|
||||||
Default: "default-history-listing",
|
Default: "default-history-listing",
|
||||||
},
|
},
|
||||||
|
modeLocation: map[Key]string{
|
||||||
|
Key{Up, 0}: "location-prev",
|
||||||
|
Key{Down, 0}: "location-next",
|
||||||
|
Key{Tab, 0}: "location-next",
|
||||||
|
Key{Enter, 0}: "accept-location",
|
||||||
|
Key{'[', Ctrl}: "cancel-location",
|
||||||
|
Default: "location-default",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var keyBindings = map[bufferMode]map[Key]Caller{}
|
var keyBindings = map[bufferMode]map[Key]Caller{}
|
||||||
|
|
|
@ -74,6 +74,14 @@ var builtins = []Builtin{
|
||||||
{"start-history-listing", startHistoryListing},
|
{"start-history-listing", startHistoryListing},
|
||||||
{"default-history-listing", defaultHistoryListing},
|
{"default-history-listing", defaultHistoryListing},
|
||||||
|
|
||||||
|
// Location mode
|
||||||
|
{"start-location", startLocation},
|
||||||
|
{"location-prev", locationPrev},
|
||||||
|
{"location-next", locationNext},
|
||||||
|
{"accept-location", acceptLocation},
|
||||||
|
{"cancel-location", cancelLocation},
|
||||||
|
{"location-default", locationDefault},
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
{"redraw", redraw},
|
{"redraw", redraw},
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ type editorState struct {
|
||||||
navigation *navigation
|
navigation *navigation
|
||||||
history historyState
|
history historyState
|
||||||
historyListing *historyListing
|
historyListing *historyListing
|
||||||
|
location location
|
||||||
isExternal map[string]bool
|
isExternal map[string]bool
|
||||||
parseErrorAtEnd bool
|
parseErrorAtEnd bool
|
||||||
// Used for builtins.
|
// Used for builtins.
|
||||||
|
@ -65,6 +66,7 @@ const (
|
||||||
modeNavigation
|
modeNavigation
|
||||||
modeHistory
|
modeHistory
|
||||||
modeHistoryListing
|
modeHistoryListing
|
||||||
|
modeLocation
|
||||||
)
|
)
|
||||||
|
|
||||||
type actionType int
|
type actionType int
|
||||||
|
|
74
edit/location.go
Normal file
74
edit/location.go
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
package edit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
|
"github.com/elves/elvish/store"
|
||||||
|
)
|
||||||
|
|
||||||
|
type location struct {
|
||||||
|
filter string
|
||||||
|
candidates []store.Dir
|
||||||
|
current int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *location) updateCandidates(store *store.Store) error {
|
||||||
|
dirs, err := store.FindDirs(l.filter)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
l.candidates = dirs
|
||||||
|
|
||||||
|
if len(l.candidates) > 0 {
|
||||||
|
l.current = 0
|
||||||
|
} else {
|
||||||
|
l.current = -1
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func startLocation(ed *Editor) {
|
||||||
|
ed.location = location{}
|
||||||
|
ed.location.updateCandidates(ed.store)
|
||||||
|
ed.mode = modeLocation
|
||||||
|
}
|
||||||
|
|
||||||
|
func locationPrev(ed *Editor) {
|
||||||
|
if len(ed.location.candidates) > 0 && ed.location.current > 0 {
|
||||||
|
ed.location.current--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func locationNext(ed *Editor) {
|
||||||
|
if len(ed.location.candidates) > 0 && ed.location.current < len(ed.location.candidates)-1 {
|
||||||
|
ed.location.current++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func acceptLocation(ed *Editor) {
|
||||||
|
// XXX Maybe we want to use eval.cdInner and increase the score?
|
||||||
|
loc := &ed.location
|
||||||
|
if len(loc.candidates) > 0 {
|
||||||
|
err := os.Chdir(loc.candidates[loc.current].Path)
|
||||||
|
if err != nil {
|
||||||
|
ed.notify("%v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ed.mode = modeInsert
|
||||||
|
}
|
||||||
|
|
||||||
|
func cancelLocation(ed *Editor) {
|
||||||
|
ed.mode = modeInsert
|
||||||
|
}
|
||||||
|
|
||||||
|
func locationDefault(ed *Editor) {
|
||||||
|
k := ed.lastKey
|
||||||
|
if k.Mod == 0 && k.Rune > 0 && unicode.IsGraphic(k.Rune) {
|
||||||
|
ed.location.filter += string(k.Rune)
|
||||||
|
ed.location.updateCandidates(ed.store)
|
||||||
|
} else {
|
||||||
|
cancelLocation(ed)
|
||||||
|
ed.nextAction = action{actionType: reprocessKey}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,8 @@ var (
|
||||||
styleForCurrentCompletion = ";7"
|
styleForCurrentCompletion = ";7"
|
||||||
styleForCompletedHistory = "2"
|
styleForCompletedHistory = "2"
|
||||||
styleForSelectedFile = ";7"
|
styleForSelectedFile = ";7"
|
||||||
|
styleForLocation = "4"
|
||||||
|
styleForSelectedLocation = ";7"
|
||||||
)
|
)
|
||||||
|
|
||||||
var styleForType = map[TokenKind]string{
|
var styleForType = map[TokenKind]string{
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/elves/elvish/parse"
|
||||||
"github.com/elves/elvish/sys"
|
"github.com/elves/elvish/sys"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -483,9 +484,15 @@ tokens:
|
||||||
case modeHistory:
|
case modeHistory:
|
||||||
text = fmt.Sprintf("HISTORY #%d", es.history.current)
|
text = fmt.Sprintf("HISTORY #%d", es.history.current)
|
||||||
case modeHistoryListing:
|
case modeHistoryListing:
|
||||||
text = fmt.Sprintf("HISTORY LISTING")
|
text = "HISTORY LISTING"
|
||||||
|
case modeLocation:
|
||||||
|
text = "LOCATION"
|
||||||
}
|
}
|
||||||
b.writes(TrimWcWidth(" "+text+" ", width), styleForMode)
|
b.writes(TrimWcWidth(" "+text+" ", width), styleForMode)
|
||||||
|
if es.mode == modeLocation {
|
||||||
|
b.writes(" ", "")
|
||||||
|
b.writes(es.location.filter, styleForLocation)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// bufTips
|
// bufTips
|
||||||
|
@ -528,10 +535,11 @@ tokens:
|
||||||
// Render bufListing under the maximum height constraint
|
// Render bufListing under the maximum height constraint
|
||||||
nav := es.navigation
|
nav := es.navigation
|
||||||
hist := es.historyListing
|
hist := es.historyListing
|
||||||
if hListing > 0 && (comp != nil || nav != nil || hist != nil) {
|
if hListing > 0 {
|
||||||
b := newBuffer(width)
|
b := newBuffer(width)
|
||||||
bufListing = b
|
bufListing = b
|
||||||
if comp != nil { // Completion listing
|
switch es.mode {
|
||||||
|
case modeCompletion:
|
||||||
// Layout candidates in multiple columns
|
// Layout candidates in multiple columns
|
||||||
cands := comp.candidates
|
cands := comp.candidates
|
||||||
|
|
||||||
|
@ -574,7 +582,7 @@ tokens:
|
||||||
b.writes(ForceWcWidth(text, colWidth), style)
|
b.writes(ForceWcWidth(text, colWidth), style)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if nav != nil { // Navigation listing
|
case modeNavigation:
|
||||||
margin := navigationListingColMargin
|
margin := navigationListingColMargin
|
||||||
var ratioParent, ratioCurrent, ratioPreview int
|
var ratioParent, ratioCurrent, ratioPreview int
|
||||||
if nav.dirPreview != nil {
|
if nav.dirPreview != nil {
|
||||||
|
@ -603,7 +611,7 @@ tokens:
|
||||||
bPreview := renderNavColumn(nav.dirPreview, wPreview, hListing)
|
bPreview := renderNavColumn(nav.dirPreview, wPreview, hListing)
|
||||||
b.extendHorizontal(bPreview, wParent+wCurrent+margin, margin)
|
b.extendHorizontal(bPreview, wParent+wCurrent+margin, margin)
|
||||||
}
|
}
|
||||||
} else if hist != nil {
|
case modeHistoryListing:
|
||||||
n := len(hist.all)
|
n := len(hist.all)
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
|
@ -625,6 +633,26 @@ tokens:
|
||||||
if len(b.cells) > 0 {
|
if len(b.cells) > 0 {
|
||||||
b.trimToLines(startIndex, n)
|
b.trimToLines(startIndex, n)
|
||||||
}
|
}
|
||||||
|
case modeLocation:
|
||||||
|
loc := &es.location
|
||||||
|
if len(loc.candidates) == 0 {
|
||||||
|
b.writes("(no match)", "")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
low, high := findWindow(len(loc.candidates), loc.current, hListing)
|
||||||
|
for i := low; i < high; i++ {
|
||||||
|
if i > low {
|
||||||
|
b.newline()
|
||||||
|
}
|
||||||
|
text := fmt.Sprintf("%4.0f %s", loc.candidates[i].Score, parse.Quote(loc.candidates[i].Path))
|
||||||
|
style := ""
|
||||||
|
if i == loc.current {
|
||||||
|
style = styleForSelectedLocation
|
||||||
|
}
|
||||||
|
b.writes(TrimWcWidth(text, width), style)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
bufListing = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user