mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-05 03:17:50 +08:00
pkg/eval: Simplify API of "src".
Remove the Type and Root fields, and add a new IsFile field.
This commit is contained in:
parent
905447eda5
commit
c112223611
|
@ -15,49 +15,34 @@ import (
|
|||
// Output a map-like value describing the current source being evaluated. The value
|
||||
// contains the following fields:
|
||||
//
|
||||
// - `type`, which can be one of `interactive`, `script` or `module`;
|
||||
// - `name`, a unique name of the current source. If the source originates from a
|
||||
// file, it is the full path of the file.
|
||||
//
|
||||
// - `name`, which is set to the name under which a script is executed or a
|
||||
// module is imported. It is an empty string when `type` = `interactive`;
|
||||
// - `code`, the full body of the current source.
|
||||
//
|
||||
// - `path`, which is the path to the current source. It is an empty string when
|
||||
// `type` = `interactive`;
|
||||
//
|
||||
// - `code`, which is the full body of the current source.
|
||||
// - `is-file`, whether the source originates from a file.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// ```elvish-transcript
|
||||
// ~> put (src)[type name path code]
|
||||
// ▶ interactive
|
||||
// ▶ ''
|
||||
// ▶ ''
|
||||
// ▶ 'put (src)[type name path code]'
|
||||
// ~> echo 'put (src)[type name path code]' > foo.elv
|
||||
// ~> elvish foo.elv
|
||||
// ▶ script
|
||||
// ▶ foo.elv
|
||||
// ▶ /home/xiaq/foo.elv
|
||||
// ▶ "put (src)[type name path code]\n"
|
||||
// ~> echo 'put (src)[type name path code]' > ~/.elvish/lib/m.elv
|
||||
// ~> use m
|
||||
// ▶ module
|
||||
// ▶ m
|
||||
// ▶ /home/xiaq/.elvish/lib/m.elv
|
||||
// ▶ "put (src)[type name path code]\n"
|
||||
// ```
|
||||
// ~> put (src)[name code is-file]
|
||||
// ▶ '[tty]'
|
||||
// ▶ 'put (src)[name code is-file]'
|
||||
// ▶ $false
|
||||
// ~> echo 'put (src)[name code is-file]' > show-src.elv
|
||||
// ~> elvish show-src.elv
|
||||
// ▶ /home/elf/show-src.elv
|
||||
// ▶ "put (src)[name code is-file]\n"
|
||||
// ▶ $true
|
||||
//
|
||||
// Note: this builtin always returns information of the source of the **calling
|
||||
// function**. Example:
|
||||
// Note: this builtin always returns information of the source of the function
|
||||
// calling `src`. Consider the following example:
|
||||
//
|
||||
// ```elvish-transcript
|
||||
// ~> echo 'fn f { put (src)[type name path code] }' > ~/.elvish/lib/n.elv
|
||||
// ~> use n
|
||||
// ~> n:f
|
||||
// ▶ module
|
||||
// ▶ n
|
||||
// ▶ /home/xiaq/.elvish/lib/n.elv
|
||||
// ▶ "fn f { put (src)[type name path code] }\n"
|
||||
// ~> echo 'fn show { put (src)[name] }' > ~/.elvish/lib/src-util.elv
|
||||
// ~> use src-util
|
||||
// ~> src-util:show
|
||||
// ▶ /home/elf/.elvish/lib/src-util.elv
|
||||
// ```
|
||||
|
||||
//elvdoc:fn -gc
|
||||
|
|
|
@ -259,7 +259,7 @@ func (op useOp) invoke(fm *Frame) error {
|
|||
func loadModule(fm *Frame, r diag.Ranger, spec string) (Ns, error) {
|
||||
if strings.HasPrefix(spec, "./") || strings.HasPrefix(spec, "../") {
|
||||
var dir string
|
||||
if fm.srcMeta.Type == FileSource {
|
||||
if fm.srcMeta.IsFile {
|
||||
dir = filepath.Dir(fm.srcMeta.Name)
|
||||
} else {
|
||||
var err error
|
||||
|
|
|
@ -2,7 +2,6 @@ package eval
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/elves/elvish/pkg/parse"
|
||||
"github.com/elves/elvish/pkg/util"
|
||||
|
@ -11,36 +10,36 @@ import (
|
|||
|
||||
// Source describes a piece of source code.
|
||||
type Source struct {
|
||||
Type SourceType
|
||||
Name string
|
||||
Root bool
|
||||
Code string
|
||||
|
||||
IsFile bool
|
||||
}
|
||||
|
||||
// NewInteractiveSource returns a Source for a piece of code entered
|
||||
// interactively.
|
||||
func NewInteractiveSource(name, code string) *Source {
|
||||
return &Source{InteractiveSource, "[tty]", true, code}
|
||||
return &Source{Name: "[tty]", Code: code}
|
||||
}
|
||||
|
||||
// NewScriptSource returns a Source for a piece of code used as a script.
|
||||
func NewScriptSource(path, code string) *Source {
|
||||
return &Source{FileSource, path, true, code}
|
||||
return &Source{Name: path, Code: code, IsFile: true}
|
||||
}
|
||||
|
||||
// NewModuleSource returns a Source for a piece of code used as a module.
|
||||
func NewModuleSource(path, code string) *Source {
|
||||
return &Source{FileSource, path, false, code}
|
||||
return &Source{Name: path, Code: code, IsFile: true}
|
||||
}
|
||||
|
||||
// NewInternalGoSource returns a Source for use as a placeholder when calling Elvish
|
||||
// functions from Go code. It has no associated code.
|
||||
func NewInternalGoSource(name string) *Source {
|
||||
return &Source{InternalGoSource, name, true, ""}
|
||||
return &Source{Name: name}
|
||||
}
|
||||
|
||||
func NewInternalElvishSource(root bool, name, code string) *Source {
|
||||
return &Source{InternalElvishSource, name, root, code}
|
||||
return &Source{Name: name, Code: code}
|
||||
}
|
||||
|
||||
func (src *Source) Kind() string {
|
||||
|
@ -48,12 +47,15 @@ func (src *Source) Kind() string {
|
|||
}
|
||||
|
||||
func (src *Source) Hash() uint32 {
|
||||
var root uint32
|
||||
if src.Root {
|
||||
root = 1
|
||||
return hash.DJB(
|
||||
hash.String(src.Name), hash.String(src.Code), hashBool(src.IsFile))
|
||||
}
|
||||
|
||||
func hashBool(b bool) uint32 {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return hash.DJB(uint32(src.Type),
|
||||
hash.String(src.Name), root, hash.String(src.Code))
|
||||
return 0
|
||||
}
|
||||
|
||||
func (src *Source) Equal(other interface{}) bool {
|
||||
|
@ -65,56 +67,22 @@ func (src *Source) Equal(other interface{}) bool {
|
|||
|
||||
func (src *Source) Repr(int) string {
|
||||
return fmt.Sprintf(
|
||||
"<src type:%s name:%s root:$%v code:...>",
|
||||
src.Type, parse.Quote(src.Name), src.Root)
|
||||
"<src name:%s code:... is-file:$%v>", parse.Quote(src.Name), src.IsFile)
|
||||
}
|
||||
|
||||
func (src *Source) Index(k interface{}) (interface{}, bool) {
|
||||
switch k {
|
||||
case "type":
|
||||
return src.Type.String(), true
|
||||
case "name":
|
||||
return src.Name, true
|
||||
case "root":
|
||||
return src.Root, true
|
||||
case "code":
|
||||
return src.Code, true
|
||||
case "is-file":
|
||||
return src.IsFile, true
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
func (src *Source) IterateKeys(f func(interface{}) bool) {
|
||||
util.Feed(f, "type", "name", "root", "code")
|
||||
}
|
||||
|
||||
// SourceType records the type of a piece of source code.
|
||||
type SourceType int
|
||||
|
||||
const (
|
||||
InvalidSource SourceType = iota
|
||||
// A special value used for the Frame when calling Elvish functions from Go.
|
||||
// This is the only sourceType without associated code.
|
||||
InternalGoSource
|
||||
// Code from an internal buffer.
|
||||
InternalElvishSource
|
||||
// Code entered interactively.
|
||||
InteractiveSource
|
||||
// Code from a file.
|
||||
FileSource
|
||||
)
|
||||
|
||||
func (t SourceType) String() string {
|
||||
switch t {
|
||||
case InternalGoSource:
|
||||
return "internal-go"
|
||||
case InternalElvishSource:
|
||||
return "internal-elvish"
|
||||
case InteractiveSource:
|
||||
return "interactive"
|
||||
case FileSource:
|
||||
return "file"
|
||||
default:
|
||||
return "bad type " + strconv.Itoa(int(t))
|
||||
}
|
||||
util.Feed(f, "name", "code", "is-file")
|
||||
}
|
||||
|
|
|
@ -10,23 +10,21 @@ import (
|
|||
func TestSourceAsValue(t *testing.T) {
|
||||
vals.TestValue(t, NewInteractiveSource("[tty]", "echo")).
|
||||
Kind("map").
|
||||
Hash(hash.DJB(uint32(InteractiveSource),
|
||||
hash.String("[tty]"), 1, hash.String("echo"))).
|
||||
Hash(hash.DJB(hash.String("[tty]"), hash.String("echo"), 0)).
|
||||
Equal(NewInteractiveSource("[tty]", "echo")).
|
||||
NotEqual(NewInteractiveSource("[tty]", "put")).
|
||||
Repr("<src type:interactive name:'[tty]' root:$true code:...>").
|
||||
AllKeys("type", "name", "root", "code").
|
||||
Index("type", "interactive").
|
||||
Repr("<src name:'[tty]' code:... is-file:$false>").
|
||||
AllKeys("name", "code", "is-file").
|
||||
Index("name", "[tty]").
|
||||
Index("root", true).
|
||||
Index("code", "echo")
|
||||
Index("code", "echo").
|
||||
Index("is-file", false)
|
||||
|
||||
vals.TestValue(t, NewInternalGoSource("[test]")).
|
||||
Index("type", "internal-go")
|
||||
Index("is-file", false)
|
||||
|
||||
vals.TestValue(t, NewInternalElvishSource(true, "[test]", "echo")).
|
||||
Index("type", "internal-elvish")
|
||||
Index("is-file", false)
|
||||
|
||||
vals.TestValue(t, NewScriptSource("/fake/path", "echo")).
|
||||
Index("type", "file")
|
||||
vals.TestValue(t, &Source{Type: -1}).
|
||||
Index("type", "bad type -1")
|
||||
Index("is-file", true)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user