2016-02-19 05:52:05 +08:00
|
|
|
package eval
|
|
|
|
|
2016-10-10 02:42:32 +08:00
|
|
|
import (
|
|
|
|
"unicode/utf8"
|
|
|
|
|
|
|
|
"github.com/elves/elvish/parse"
|
|
|
|
)
|
2016-02-19 05:52:05 +08:00
|
|
|
|
|
|
|
// String is just a string.
|
|
|
|
type String string
|
|
|
|
|
2016-10-10 02:42:32 +08:00
|
|
|
var (
|
|
|
|
_ Value = String("")
|
|
|
|
_ ListLike = String("")
|
|
|
|
)
|
|
|
|
|
2016-02-19 05:52:05 +08:00
|
|
|
func (String) Kind() string {
|
|
|
|
return "string"
|
|
|
|
}
|
|
|
|
|
2016-02-20 03:11:31 +08:00
|
|
|
func (s String) Repr(int) string {
|
2016-02-19 05:52:05 +08:00
|
|
|
return quote(string(s))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s String) String() string {
|
|
|
|
return string(s)
|
|
|
|
}
|
|
|
|
|
2016-02-19 18:49:19 +08:00
|
|
|
func (s String) Len() int {
|
|
|
|
return len(string(s))
|
|
|
|
}
|
|
|
|
|
2016-10-10 02:42:32 +08:00
|
|
|
func (s String) IndexOne(idx Value) Value {
|
|
|
|
slice, i, j := ParseAndFixListIndex(ToString(idx), len(s))
|
|
|
|
var r rune
|
|
|
|
if r, _ = utf8.DecodeRuneInString(string(s[i:])); r == utf8.RuneError {
|
|
|
|
throw(ErrBadIndex)
|
|
|
|
}
|
|
|
|
if slice {
|
|
|
|
if r, _ := utf8.DecodeLastRuneInString(string(s[:j])); r == utf8.RuneError {
|
|
|
|
throw(ErrBadIndex)
|
|
|
|
}
|
|
|
|
return String(s[i:j])
|
|
|
|
}
|
|
|
|
return String(r)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s String) Iterate(f func(v Value) bool) {
|
|
|
|
for _, r := range s {
|
|
|
|
b := f(String(string(r)))
|
|
|
|
if !b {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-02 08:35:13 +08:00
|
|
|
// Call resolves a command name to either a Fn variable or external command and
|
|
|
|
// calls it.
|
2016-09-15 05:34:10 +08:00
|
|
|
func (s String) Call(ec *EvalCtx, args []Value, opts map[string]Value) {
|
|
|
|
resolve(string(s), ec).Call(ec, args, opts)
|
2016-02-19 05:52:05 +08:00
|
|
|
}
|
|
|
|
|
2017-02-18 12:45:40 +08:00
|
|
|
func resolve(s string, ec *EvalCtx) CallableValue {
|
2016-02-19 05:52:05 +08:00
|
|
|
// Try variable
|
2016-10-13 14:10:10 +08:00
|
|
|
explode, ns, name := ParseAndFixVariable(string(s))
|
|
|
|
if !explode {
|
2016-02-19 05:52:05 +08:00
|
|
|
if v := ec.ResolveVar(ns, FnPrefix+name); v != nil {
|
2017-02-18 12:45:40 +08:00
|
|
|
if caller, ok := v.Get().(CallableValue); ok {
|
2016-02-19 05:52:05 +08:00
|
|
|
return caller
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// External command
|
|
|
|
return ExternalCmd{string(s)}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ToString converts a Value to String. When the Value type implements
|
2016-02-20 03:31:54 +08:00
|
|
|
// String(), it is used. Otherwise Repr(NoPretty) is used.
|
2016-02-19 05:52:05 +08:00
|
|
|
func ToString(v Value) string {
|
|
|
|
if s, ok := v.(Stringer); ok {
|
|
|
|
return s.String()
|
|
|
|
}
|
2016-02-20 03:31:54 +08:00
|
|
|
return v.Repr(NoPretty)
|
2016-02-19 05:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func quote(s string) string {
|
|
|
|
return parse.Quote(s)
|
|
|
|
}
|