package edit
import (
"fmt"
"sync"
"src.elv.sh/pkg/cli"
"src.elv.sh/pkg/eval"
"src.elv.sh/pkg/eval/vals"
"src.elv.sh/pkg/eval/vars"
"src.elv.sh/pkg/parse"
"src.elv.sh/pkg/store"
)
type Editor struct {
app cli .App
ns *eval .Ns
excMutex sync .RWMutex
excList vals .List
AfterCommand []func (src parse .Source , duration float64 , err error )
}
type notifier interface {
notifyf (format string , args ...interface {})
notifyError (ctx string , e error )
}
func NewEditor (tty cli .TTY , ev *eval .Evaler , st store .Store ) *Editor {
ed := &Editor {excList : vals .EmptyList }
nb := eval .NsBuilder {}
appSpec := cli .AppSpec {TTY : tty }
hs , err := newHistStore (st )
if err != nil {
}
initHighlighter (&appSpec , ev )
initMaxHeight (&appSpec , nb )
initReadlineHooks (&appSpec , ev , nb )
initAddCmdFilters (&appSpec , ev , nb , hs )
initGlobalBindings (&appSpec , ed , ev , nb )
initInsertAPI (&appSpec , ed , ev , nb )
initPrompts (&appSpec , ed , ev , nb )
ed .app = cli .NewApp (appSpec )
initExceptionsAPI (ed , nb )
initVarsAPI (ed , nb )
initCommandAPI (ed , ev , nb )
initListings (ed , ev , st , hs , nb )
initNavigation (ed , ev , nb )
initCompletion (ed , ev , nb )
initHistWalk (ed , ev , hs , nb )
initInstant (ed , ev , nb )
initMinibuf (ed , ev , nb )
initRepl (ed , ev , nb )
initBufferBuiltins (ed .app , nb )
initTTYBuiltins (ed .app , tty , nb )
initMiscBuiltins (ed .app , nb )
initStateAPI (ed .app , nb )
initStoreAPI (ed .app , nb , hs )
ed .ns = nb .Ns ()
initElvishState (ev , ed .ns )
return ed
}
func initExceptionsAPI (ed *Editor , nb eval .NsBuilder ) {
nb .Add ("exceptions" , vars .FromPtrWithMutex (&ed .excList , &ed .excMutex ))
}
func initElvishState (ev *eval .Evaler , ns *eval .Ns ) {
src := parse .Source {Name : "[RC file]" , Code : elvInit }
err := ev .Eval (src , eval .EvalCfg {Global : ns })
if err != nil {
panic (err )
}
}
func (ed *Editor ) ReadCode () (string , error ) {
return ed .app .ReadCode ()
}
func (ed *Editor ) RunAfterCommandHooks (src parse .Source , duration float64 , err error ) {
for _ , f := range ed .AfterCommand {
f (src , duration , err )
}
}
func (ed *Editor ) Ns () *eval .Ns {
return ed .ns
}
func (ed *Editor ) notifyf (format string , args ...interface {}) {
ed .app .Notify (fmt .Sprintf (format , args ...))
}
func (ed *Editor ) notifyError (ctx string , e error ) {
if exc , ok := e .(eval .Exception ); ok {
ed .excMutex .Lock ()
defer ed .excMutex .Unlock ()
ed .excList = ed .excList .Cons (exc )
ed .notifyf ("[%v error] %v\n" +
`see stack trace with "show $edit:exceptions[%d]"` ,
ctx , e , ed .excList .Len ()-1 )
} else {
ed .notifyf ("[%v error] %v" , ctx , e )
}
}