コード例 #1
0
ファイル: mapstringstring.go プロジェクト: yonglehou/elvish
func (m MapStringString) Repr(indent int) string {
	var builder MapReprBuilder
	builder.Indent = indent
	for k, v := range m {
		builder.WritePair(parse.Quote(k), parse.Quote(v))
	}
	return builder.String()
}
コード例 #2
0
ファイル: search.go プロジェクト: rathinaganesh/elvish
// Search tries to resolve an external command and return the full (possibly
// relative) path.
func (ev *Evaler) Search(exe string) (string, error) {
	if DontSearch(exe) {
		if IsExecutable(exe) {
			return exe, nil
		}
		return "", fmt.Errorf("external command %s not executable", parse.Quote(exe))
	}
	for _, p := range ev.searchPaths {
		full := p + "/" + exe
		if IsExecutable(full) {
			return full, nil
		}
	}
	return "", fmt.Errorf("external command %s not found", parse.Quote(exe))
}
コード例 #3
0
ファイル: search.go プロジェクト: zhsj/elvish
// Search tries to resolve an external command and return the full (possibly
// relative) path.
func (ev *Evaler) Search(exe string) (string, error) {
	path, err := util.Search(ev.searchPaths(), exe)
	if err != nil {
		return "", fmt.Errorf("search %s: %s", parse.Quote(exe), err.Error())
	}
	return path, nil
}
コード例 #4
0
ファイル: binding.go プロジェクト: zhsj/elvish
func (bt BindingTable) Repr(indent int) string {
	var builder eval.MapReprBuilder
	builder.Indent = indent
	for k, v := range bt.inner {
		builder.WritePair(parse.Quote(k.String()), v.Repr(eval.IncIndent(indent, 1)))
	}
	return builder.String()
}
コード例 #5
0
ファイル: struct.go プロジェクト: yonglehou/elvish
func (s *Struct) Repr(indent int) string {
	var builder MapReprBuilder
	builder.Indent = indent
	for i, name := range s.FieldNames {
		builder.WritePair(parse.Quote(name), s.Fields[i].Get().Repr(indent+1))
	}
	return builder.String()
}
コード例 #6
0
ファイル: error.go プロジェクト: zhsj/elvish
func (e Error) Repr(indent int) string {
	if e.Inner == nil {
		return "$ok"
	}
	if r, ok := e.Inner.(Reprer); ok {
		return r.Repr(indent)
	}
	return "?(error " + parse.Quote(e.Inner.Error()) + ")"
}
コード例 #7
0
ファイル: opt.go プロジェクト: zhsj/elvish
func (os *OptSet) Pick(opts map[string]Value) ([]Value, error) {
	vs := make([]Value, len(os.optSpecs))
	for k, v := range opts {
		if i, ok := os.indices[k]; ok {
			vs[i] = v
		} else {
			return nil, errors.New("unknown option " + parse.Quote(k))
		}
	}
	for i, optSpec := range os.optSpecs {
		if vs[i] == nil {
			vs[i] = optSpec.Default
		}
	}
	return vs, nil
}
コード例 #8
0
ファイル: error.go プロジェクト: zhsj/elvish
func (exit ExternalCmdExit) Error() string {
	ws := exit.WaitStatus
	quotedName := parse.Quote(exit.CmdName)
	switch {
	case ws.Exited():
		return quotedName + " exited with " + strconv.Itoa(ws.ExitStatus())
	case ws.Signaled():
		msg := quotedName + " killed by signal " + ws.Signal().String()
		if ws.CoreDump() {
			msg += " (core dumped)"
		}
		return msg
	case ws.Stopped():
		msg := quotedName + " stopped by signal " + fmt.Sprintf("%s (pid=%d)", ws.StopSignal(), exit.Pid)
		trap := ws.TrapCause()
		if trap != -1 {
			msg += fmt.Sprintf(" (trapped %v)", trap)
		}
		return msg
	default:
		return fmt.Sprint(quotedName, " has unknown WaitStatus ", ws)
	}
}
コード例 #9
0
ファイル: string.go プロジェクト: zhsj/elvish
func quote(s string) string {
	return parse.Quote(s)
}
コード例 #10
0
ファイル: completers.go プロジェクト: yonglehou/elvish
func complGetopt(ec *eval.EvalCtx, elemsv eval.IteratorValue, optsv eval.IteratorValue, argsv eval.IteratorValue) {
	var (
		elems    []string
		opts     []*getopt.Option
		args     []eval.FnValue
		variadic bool
	)
	// Convert arguments.
	elemsv.Iterate(func(v eval.Value) bool {
		elem, ok := v.(eval.String)
		if !ok {
			throwf("arg should be string, got %s", v.Kind())
		}
		elems = append(elems, string(elem))
		return true
	})
	optsv.Iterate(func(v eval.Value) bool {
		m, ok := v.(eval.MapLike)
		if !ok {
			throwf("opt should be map-like, got %s", v.Kind())
		}
		opt := &getopt.Option{}
		vshort := maybeIndex(m, eval.String("short"))
		if vshort != nil {
			sv, ok := vshort.(eval.String)
			if !ok {
				throwf("short option should be string, got %s", vshort.Kind())
			}
			s := string(sv)
			r, size := utf8.DecodeRuneInString(s)
			if r == utf8.RuneError || size != len(s) {
				throwf("short option should be exactly one rune, got %v", parse.Quote(s))
			}
			opt.Short = r
		}
		vlong := maybeIndex(m, eval.String("long"))
		if vlong != nil {
			s, ok := vlong.(eval.String)
			if !ok {
				throwf("long option should be string, got %s", vlong.Kind())
			}
			opt.Long = string(s)
		}
		if vshort == nil && vlong == nil {
			throwf("opt should have at least one of short and long as keys")
		}
		// TODO support &desc
		opts = append(opts, opt)
		return true
	})
	argsv.Iterate(func(v eval.Value) bool {
		sv, ok := v.(eval.String)
		if ok {
			if string(sv) == "..." {
				variadic = true
				return true
			}
			throwf("string except for ... not allowed as argument handler, got %s", parse.Quote(string(sv)))
		}
		arg, ok := v.(eval.FnValue)
		if !ok {
			throwf("argument handler should be fn, got %s", v.Kind())
		}
		args = append(args, arg)
		return true
	})
	// TODO Configurable config
	g := getopt.Getopt{opts, getopt.GNUGetoptLong}
	_, _, ctx := g.Parse(elems)
	out := ec.OutputChan()
	_ = variadic // XXX
	switch ctx.Type {
	case getopt.NewOptionOrArgument, getopt.Argument:
	case getopt.NewOption:
		for _, opt := range opts {
			if opt.Short != 0 {
				out <- eval.String("-" + string(opt.Short))
			}
			if opt.Long != "" {
				out <- eval.String("--" + opt.Long)
			}
		}
	case getopt.NewLongOption:
		for _, opt := range opts {
			if opt.Long != "" {
				out <- eval.String("--" + opt.Long)
			}
		}
	case getopt.LongOption:
		for _, opt := range opts {
			if strings.HasPrefix(opt.Long, ctx.Text) {
				out <- eval.String("--" + opt.Long)
			}
		}
	case getopt.ChainShortOption:
		for _, opt := range opts {
			if opt.Short != 0 {
				// XXX loses chained options
				out <- eval.String("-" + string(opt.Short))
			}
		}
	case getopt.OptionArgument:
	}
}
コード例 #11
0
ファイル: compl-getopt.go プロジェクト: zhsj/elvish
func complGetopt(ec *eval.EvalCtx, elemsv eval.IteratorValue, optsv eval.IteratorValue, argsv eval.IteratorValue) {
	var (
		elems    []string
		opts     []*getopt.Option
		args     []eval.FnValue
		variadic bool
	)
	desc := make(map[*getopt.Option]string)
	// Convert arguments.
	elemsv.Iterate(func(v eval.Value) bool {
		elem, ok := v.(eval.String)
		if !ok {
			throwf("arg should be string, got %s", v.Kind())
		}
		elems = append(elems, string(elem))
		return true
	})
	optsv.Iterate(func(v eval.Value) bool {
		m, ok := v.(eval.MapLike)
		if !ok {
			throwf("opt should be map-like, got %s", v.Kind())
		}
		get := func(ks string) (string, bool) {
			kv := eval.String(ks)
			if !m.HasKey(kv) {
				return "", false
			}
			vv := m.IndexOne(kv)
			if vs, ok := vv.(eval.String); ok {
				return string(vs), true
			} else {
				throwf("%s should be string, got %s", ks, vs.Kind())
				panic("unreachable")
			}
		}

		opt := &getopt.Option{}
		if s, ok := get("short"); ok {
			r, size := utf8.DecodeRuneInString(s)
			if r == utf8.RuneError || size != len(s) {
				throwf("short option should be exactly one rune, got %v", parse.Quote(s))
			}
			opt.Short = r
		}
		if s, ok := get("long"); ok {
			opt.Long = s
		}
		if opt.Short == 0 && opt.Long == "" {
			throwf("opt should have at least one of short and long forms")
		}
		if s, ok := get("desc"); ok {
			desc[opt] = s
		}
		opts = append(opts, opt)
		return true
	})
	argsv.Iterate(func(v eval.Value) bool {
		sv, ok := v.(eval.String)
		if ok {
			if string(sv) == "..." {
				variadic = true
				return true
			}
			throwf("string except for ... not allowed as argument handler, got %s", parse.Quote(string(sv)))
		}
		arg, ok := v.(eval.FnValue)
		if !ok {
			throwf("argument handler should be fn, got %s", v.Kind())
		}
		args = append(args, arg)
		return true
	})
	// TODO Configurable config
	g := getopt.Getopt{opts, getopt.GNUGetoptLong}
	_, parsedArgs, ctx := g.Parse(elems)
	out := ec.OutputChan()

	putShortOpt := func(opt *getopt.Option) {
		c := &candidate{text: "-" + string(opt.Short)}
		if d, ok := desc[opt]; ok {
			c.display.text = c.text + " (" + d + ")"
		}
		out <- c
	}
	putLongOpt := func(opt *getopt.Option) {
		c := &candidate{text: "--" + string(opt.Long)}
		if d, ok := desc[opt]; ok {
			c.display.text = c.text + " (" + d + ")"
		}
		out <- c
	}

	switch ctx.Type {
	case getopt.NewOptionOrArgument, getopt.Argument:
		// Find argument completer
		var argCompl eval.FnValue
		if len(parsedArgs) < len(args) {
			argCompl = args[len(parsedArgs)]
		} else if variadic {
			argCompl = args[len(args)-1]
		}
		if argCompl != nil {
			cands, err := callFnForCandidates(argCompl, ec.Evaler, []string{ctx.Text})
			maybeThrow(err)
			for _, cand := range cands {
				out <- cand
			}
		}
		// TODO Notify that there is no suitable argument completer
	case getopt.NewOption:
		for _, opt := range opts {
			if opt.Short != 0 {
				putShortOpt(opt)
			}
			if opt.Long != "" {
				putLongOpt(opt)
			}
		}
	case getopt.NewLongOption:
		for _, opt := range opts {
			if opt.Long != "" {
				putLongOpt(opt)
			}
		}
	case getopt.LongOption:
		for _, opt := range opts {
			if strings.HasPrefix(opt.Long, ctx.Text) {
				putLongOpt(opt)
			}
		}
	case getopt.ChainShortOption:
		for _, opt := range opts {
			if opt.Short != 0 {
				// XXX loses chained options
				putShortOpt(opt)
			}
		}
	case getopt.OptionArgument:
	}
}
コード例 #12
0
ファイル: location.go プロジェクト: yonglehou/elvish
func (loc *location) Show(i, width int) styled {
	cand := loc.candidates[i]
	return unstyled(TrimWcWidth(fmt.Sprintf("%4.0f %s", cand.Score, parse.Quote(cand.Path)), width))
}
コード例 #13
0
ファイル: navigation.go プロジェクト: zhsj/elvish
func navInsertSelectedAndQuit(ed *Editor) {
	ed.insertAtDot(parse.Quote(ed.navigation.current.selectedName()) + " ")
	ed.mode = &ed.insert
}
コード例 #14
0
ファイル: value.go プロジェクト: wanlanjian/elvish
func (s String) Repr() string {
	return parse.Quote(string(s))
}
コード例 #15
0
ファイル: navigation.go プロジェクト: zhsj/elvish
func navInsertSelected(ed *Editor) {
	ed.insertAtDot(parse.Quote(ed.navigation.current.selectedName()) + " ")
}
コード例 #16
0
ファイル: location.go プロジェクト: zhsj/elvish
func (loc *location) Show(i, width int) styled {
	cand := loc.filtered[i]
	return unstyled(util.TrimWcwidth(fmt.Sprintf("%4.0f %s", cand.Score, parse.Quote(cand.Path)), width))
}
コード例 #17
0
ファイル: editor.go プロジェクト: elves/elvish
// ReadLine reads a line interactively.
func (ed *Editor) ReadLine() (line string, err error) {
	e := ed.startReadLine()
	if e != nil {
		return "", e
	}
	defer ed.finishReadLine(func(e error) {
		if e != nil {
			err = util.CatError(err, e)
		}
	})

	ed.mode = &ed.insert

	isExternalCh := make(chan map[string]bool, 1)
	go getIsExternal(ed.evaler, isExternalCh)

	ed.writer.resetOldBuf()
	go ed.reader.Run()

	fullRefresh := false

	beforeReadLines := ed.beforeReadLine.Get().(eval.ListLike)
	beforeReadLines.Iterate(func(f eval.Value) bool {
		ed.CallFn(f.(eval.FnValue))
		return true
	})

MainLoop:
	for {
		ed.prompt = callFnForPrompt(ed, ed.ps1.Get().(eval.Fn))
		ed.rprompt = callFnForPrompt(ed, ed.rps1.Get().(eval.Fn))

		err := ed.refresh(fullRefresh, true)
		fullRefresh = false
		if err != nil {
			return "", err
		}

		ed.tips = nil

		select {
		case m := <-isExternalCh:
			ed.isExternal = m
		case sig := <-ed.sigs:
			// TODO(xiaq): Maybe support customizable handling of signals
			switch sig {
			case syscall.SIGINT:
				// Start over
				ed.editorState = editorState{
					savedTermios: ed.savedTermios,
					isExternal:   ed.isExternal,
				}
				ed.mode = &ed.insert
				goto MainLoop
			case syscall.SIGWINCH:
				fullRefresh = true
				continue MainLoop
			case syscall.SIGCHLD:
				// ignore
			default:
				ed.addTip("ignored signal %s", sig)
			}
		case err := <-ed.reader.ErrorChan():
			ed.Notify("reader error: %s", err.Error())
		case mouse := <-ed.reader.MouseChan():
			ed.addTip("mouse: %+v", mouse)
		case <-ed.reader.CPRChan():
			// Ignore CPR
		case b := <-ed.reader.PasteChan():
			if !b {
				continue
			}
			var buf bytes.Buffer
			timer := time.NewTimer(EscSequenceTimeout)
		paste:
			for {
				// XXX Should also select on other chans. However those chans
				// will be unified (agina) into one later so we don't do
				// busywork here.
				select {
				case k := <-ed.reader.KeyChan():
					if k.Mod != 0 {
						ed.Notify("function key within paste")
						break paste
					}
					buf.WriteRune(k.Rune)
					timer.Reset(EscSequenceTimeout)
				case b := <-ed.reader.PasteChan():
					if !b {
						break paste
					}
				case <-timer.C:
					ed.Notify("bracketed paste timeout")
					break paste
				}
			}
			topaste := buf.String()
			if ed.insert.quotePaste {
				topaste = parse.Quote(topaste)
			}
			ed.insertAtDot(topaste)
		case k := <-ed.reader.KeyChan():
		lookupKey:
			keyBinding, ok := keyBindings[ed.mode.Mode()]
			if !ok {
				ed.addTip("No binding for current mode")
				continue
			}

			fn, bound := keyBinding[k]
			if !bound {
				fn = keyBinding[Default]
			}

			ed.insert.insertedLiteral = false
			ed.lastKey = k
			ed.CallFn(fn)
			if ed.insert.insertedLiteral {
				ed.insert.literalInserts++
			} else {
				ed.insert.literalInserts = 0
			}
			act := ed.nextAction
			ed.nextAction = action{}

			switch act.typ {
			case noAction:
				continue
			case reprocessKey:
				err = ed.refresh(false, true)
				if err != nil {
					return "", err
				}
				goto lookupKey
			case exitReadLine:
				if act.returnErr == nil && act.returnLine != "" {
					ed.appendHistory(act.returnLine)
				}
				return act.returnLine, act.returnErr
			}
		}
	}
}
コード例 #18
0
ファイル: builtin-fn.go プロジェクト: zhsj/elvish
// WrapFn wraps an inner function into one suitable as a builtin function. It
// generates argument checking and conversion code according to the signature of
// the inner function and option specifications. The inner function must accept
// EvalCtx* as the first argument, followed by options, followed by arguments.
func WrapFn(inner interface{}, optSpecs ...OptSpec) func(*EvalCtx, []Value, map[string]Value) {
	funcType := reflect.TypeOf(inner)
	if funcType.In(0) != evalCtxType {
		panic("bad func to wrap, first argument not *EvalCtx")
	}

	nopts := len(optSpecs)
	optsTo := nopts + 1
	optSet := NewOptSet(optSpecs...)
	// Range occupied by fixed arguments in the argument list to inner.
	fixedArgsFrom, fixedArgsTo := optsTo, funcType.NumIn()
	isVariadic := funcType.IsVariadic()
	hasOptionalIterate := false
	var variadicType reflect.Type
	if isVariadic {
		fixedArgsTo--
		variadicType = funcType.In(funcType.NumIn() - 1).Elem()
		if !supportedArgType(variadicType) {
			panic(fmt.Sprintf("bad func to wrap, variadic argument type %s unsupported", variadicType))
		}
	} else if funcType.In(funcType.NumIn()-1) == iterateType {
		fixedArgsTo--
		hasOptionalIterate = true
	}

	for i := 1; i < fixedArgsTo; i++ {
		if !supportedArgType(funcType.In(i)) {
			panic(fmt.Sprintf("bad func to wrap, argument type %s unsupported", funcType.In(i)))
		}
	}

	nFixedArgs := fixedArgsTo - fixedArgsFrom

	return func(ec *EvalCtx, args []Value, opts map[string]Value) {
		// Check arity of arguments.
		if isVariadic {
			if len(args) < nFixedArgs {
				throw(fmt.Errorf("arity mismatch: want %d or more arguments, got %d", nFixedArgs, len(args)))
			}
		} else if hasOptionalIterate {
			if len(args) < nFixedArgs || len(args) > nFixedArgs+1 {
				throw(fmt.Errorf("arity mismatch: want %d or %d arguments, got %d", nFixedArgs, nFixedArgs+1, len(args)))
			}
		} else if len(args) != nFixedArgs {
			throw(fmt.Errorf("arity mismatch: want %d arguments, got %d", nFixedArgs, len(args)))
		}
		convertedArgs := make([]reflect.Value, 1+nopts+len(args))
		convertedArgs[0] = reflect.ValueOf(ec)

		// Convert and fill options.
		var err error
		optValues := optSet.MustPick(opts)
		for i, v := range optValues {
			convertedArgs[1+i], err = convertArg(v, funcType.In(1+i))
			if err != nil {
				throw(errors.New("bad option " + parse.Quote(optSet.optSpecs[i].Name) + ": " + err.Error()))
			}
		}

		// Convert and fill fixed arguments.
		for i, arg := range args[:nFixedArgs] {
			convertedArgs[fixedArgsFrom+i], err = convertArg(arg, funcType.In(fixedArgsFrom+i))
			if err != nil {
				throw(errors.New("bad argument: " + err.Error()))
			}
		}

		if isVariadic {
			for i, arg := range args[nFixedArgs:] {
				convertedArgs[fixedArgsTo+i], err = convertArg(arg, variadicType)
				if err != nil {
					throw(errors.New("bad argument: " + err.Error()))
				}
			}
		} else if hasOptionalIterate {
			var iterate func(func(Value))
			if len(args) == nFixedArgs {
				// No Iterator specified in arguments. Use input.
				// Since convertedArgs was created according to the size of the
				// actual argument list, we now an empty element to make room
				// for this additional iterator argument.
				convertedArgs = append(convertedArgs, reflect.Value{})
				iterate = ec.IterateInputs
			} else {
				iterator, ok := args[nFixedArgs].(Iterator)
				if !ok {
					throw(errors.New("bad argument: need iterator, got " + args[nFixedArgs].Kind()))
				}
				iterate = func(f func(Value)) {
					iterator.Iterate(func(v Value) bool {
						f(v)
						return true
					})
				}
			}
			convertedArgs[fixedArgsTo] = reflect.ValueOf(iterate)
		}
		reflect.ValueOf(inner).Call(convertedArgs)
	}
}
コード例 #19
0
ファイル: styled.go プロジェクト: elves/elvish
func (s *styled) Repr(indent int) string {
	return "(le:styled " + parse.Quote(s.text) + " " + parse.Quote(s.styles.String()) + ")"
}
コード例 #20
0
ファイル: external_cmd.go プロジェクト: elves/elvish
func (e ExternalCmd) Repr(int) string {
	return "<external " + parse.Quote(e.Name) + ">"
}
コード例 #21
0
ファイル: candidate.go プロジェクト: zhsj/elvish
func (c *candidate) Repr(int) string {
	return fmt.Sprintf("(le:candidate %s %s %s)", parse.Quote(c.text), c.display.Repr(eval.NoPretty), parse.Quote(c.suffix))
}