mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-04 02:37:50 +08:00
parent
d149955c1d
commit
7209b48bf8
|
@ -40,6 +40,7 @@ var defaultBindings = map[bufferMode]map[Key]string{
|
|||
Key{Up, 0}: "start-history",
|
||||
Key{'N', Ctrl}: "start-navigation",
|
||||
Key{'H', Ctrl}: "start-history-listing",
|
||||
Key{'L', Ctrl}: "start-location",
|
||||
},
|
||||
modeCommand: map[Key]string{
|
||||
Default: "default-command",
|
||||
|
@ -85,6 +86,14 @@ var defaultBindings = map[bufferMode]map[Key]string{
|
|||
modeHistoryListing: map[Key]string{
|
||||
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{}
|
||||
|
|
|
@ -74,6 +74,14 @@ var builtins = []Builtin{
|
|||
{"start-history-listing", startHistoryListing},
|
||||
{"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
|
||||
{"redraw", redraw},
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ type editorState struct {
|
|||
navigation *navigation
|
||||
history historyState
|
||||
historyListing *historyListing
|
||||
location location
|
||||
isExternal map[string]bool
|
||||
parseErrorAtEnd bool
|
||||
// Used for builtins.
|
||||
|
@ -65,6 +66,7 @@ const (
|
|||
modeNavigation
|
||||
modeHistory
|
||||
modeHistoryListing
|
||||
modeLocation
|
||||
)
|
||||
|
||||
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"
|
||||
styleForCompletedHistory = "2"
|
||||
styleForSelectedFile = ";7"
|
||||
styleForLocation = "4"
|
||||
styleForSelectedLocation = ";7"
|
||||
)
|
||||
|
||||
var styleForType = map[TokenKind]string{
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/elves/elvish/parse"
|
||||
"github.com/elves/elvish/sys"
|
||||
)
|
||||
|
||||
|
@ -483,9 +484,15 @@ tokens:
|
|||
case modeHistory:
|
||||
text = fmt.Sprintf("HISTORY #%d", es.history.current)
|
||||
case modeHistoryListing:
|
||||
text = fmt.Sprintf("HISTORY LISTING")
|
||||
text = "HISTORY LISTING"
|
||||
case modeLocation:
|
||||
text = "LOCATION"
|
||||
}
|
||||
b.writes(TrimWcWidth(" "+text+" ", width), styleForMode)
|
||||
if es.mode == modeLocation {
|
||||
b.writes(" ", "")
|
||||
b.writes(es.location.filter, styleForLocation)
|
||||
}
|
||||
}
|
||||
|
||||
// bufTips
|
||||
|
@ -528,10 +535,11 @@ tokens:
|
|||
// Render bufListing under the maximum height constraint
|
||||
nav := es.navigation
|
||||
hist := es.historyListing
|
||||
if hListing > 0 && (comp != nil || nav != nil || hist != nil) {
|
||||
if hListing > 0 {
|
||||
b := newBuffer(width)
|
||||
bufListing = b
|
||||
if comp != nil { // Completion listing
|
||||
switch es.mode {
|
||||
case modeCompletion:
|
||||
// Layout candidates in multiple columns
|
||||
cands := comp.candidates
|
||||
|
||||
|
@ -574,7 +582,7 @@ tokens:
|
|||
b.writes(ForceWcWidth(text, colWidth), style)
|
||||
}
|
||||
}
|
||||
} else if nav != nil { // Navigation listing
|
||||
case modeNavigation:
|
||||
margin := navigationListingColMargin
|
||||
var ratioParent, ratioCurrent, ratioPreview int
|
||||
if nav.dirPreview != nil {
|
||||
|
@ -603,7 +611,7 @@ tokens:
|
|||
bPreview := renderNavColumn(nav.dirPreview, wPreview, hListing)
|
||||
b.extendHorizontal(bPreview, wParent+wCurrent+margin, margin)
|
||||
}
|
||||
} else if hist != nil {
|
||||
case modeHistoryListing:
|
||||
n := len(hist.all)
|
||||
|
||||
i := 0
|
||||
|
@ -625,6 +633,26 @@ tokens:
|
|||
if len(b.cells) > 0 {
|
||||
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