mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-01 00:33:05 +08:00
parent
cb8628bcb6
commit
49115dba1d
|
@ -1,10 +1,13 @@
|
|||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"src.elv.sh/pkg/daemon/daemondefs"
|
||||
"src.elv.sh/pkg/env"
|
||||
"src.elv.sh/pkg/fsutil"
|
||||
"src.elv.sh/pkg/prog"
|
||||
)
|
||||
|
@ -12,16 +15,46 @@ import (
|
|||
func rcPath() (string, error) {
|
||||
if legacyRC, exists := legacyDataPath("rc.elv", false); exists {
|
||||
return legacyRC, nil
|
||||
} else if configHome := os.Getenv(env.XDG_CONFIG_HOME); configHome != "" {
|
||||
return filepath.Join(configHome, "elvish", "rc.elv"), nil
|
||||
} else if configHome, err := defaultConfigHome(); err == nil {
|
||||
return filepath.Join(configHome, "elvish", "rc.elv"), nil
|
||||
} else {
|
||||
return "", fmt.Errorf("find rc.elv: %w", err)
|
||||
}
|
||||
return newRCPath()
|
||||
}
|
||||
|
||||
func libPaths() ([]string, error) {
|
||||
paths, err := newLibPaths()
|
||||
var paths []string
|
||||
|
||||
if configHome := os.Getenv(env.XDG_CONFIG_HOME); configHome != "" {
|
||||
paths = append(paths, filepath.Join(configHome, "elvish", "lib"))
|
||||
} else if configHome, err := defaultConfigHome(); err == nil {
|
||||
paths = append(paths, filepath.Join(configHome, "elvish", "lib"))
|
||||
} else {
|
||||
return nil, fmt.Errorf("find roaming lib directory: %w", err)
|
||||
}
|
||||
|
||||
if dataHome := os.Getenv(env.XDG_DATA_HOME); dataHome != "" {
|
||||
paths = append(paths, filepath.Join(dataHome, "elvish", "lib"))
|
||||
} else if dataHome, err := defaultDataHome(); err == nil {
|
||||
paths = append(paths, filepath.Join(dataHome, "elvish", "lib"))
|
||||
} else {
|
||||
return nil, fmt.Errorf("find local lib directory: %w", err)
|
||||
}
|
||||
|
||||
if dataDirs := os.Getenv(env.XDG_DATA_DIRS); dataDirs != "" {
|
||||
// We intentionally do not use filepath.SplitList and always follow the
|
||||
// semantics of XDG, even on Windows.
|
||||
paths = append(paths, strings.Split(dataDirs, ":")...)
|
||||
} else {
|
||||
paths = append(paths, defaultDataDirs...)
|
||||
}
|
||||
|
||||
if legacyLib, exists := legacyDataPath("lib", true); exists {
|
||||
paths = append(paths, legacyLib)
|
||||
}
|
||||
return paths, err
|
||||
return paths, nil
|
||||
}
|
||||
|
||||
// Returns a SpawnConfig containing all the paths needed by the daemon. It
|
||||
|
@ -54,8 +87,13 @@ func daemonPaths(p *prog.DaemonPaths) (*daemondefs.SpawnConfig, error) {
|
|||
func dbPath() (string, error) {
|
||||
if legacyDB, exists := legacyDataPath("db", false); exists {
|
||||
return legacyDB, nil
|
||||
} else if stateHome := os.Getenv(env.XDG_STATE_HOME); stateHome != "" {
|
||||
return filepath.Join(stateHome, "elvish", "db.bolt"), nil
|
||||
} else if stateHome, err := defaultStateHome(); err == nil {
|
||||
return filepath.Join(stateHome, "elvish", "db.bolt"), nil
|
||||
} else {
|
||||
return "", fmt.Errorf("find db: %w", err)
|
||||
}
|
||||
return newDBPath()
|
||||
}
|
||||
|
||||
// Returns a path in the legacy data directory path, and whether it exists and
|
||||
|
|
|
@ -8,53 +8,27 @@ import (
|
|||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
"src.elv.sh/pkg/diag"
|
||||
"src.elv.sh/pkg/env"
|
||||
"src.elv.sh/pkg/fsutil"
|
||||
)
|
||||
|
||||
func newRCPath() (string, error) {
|
||||
return xdgHomePath(env.XDG_CONFIG_HOME, ".config", "elvish/rc.elv")
|
||||
func defaultConfigHome() (string, error) { return homePath(".config") }
|
||||
|
||||
func defaultDataHome() (string, error) { return homePath(".local/share") }
|
||||
|
||||
var defaultDataDirs = []string{
|
||||
"/usr/local/share/elvish/lib",
|
||||
"/usr/share/elvish/lib",
|
||||
}
|
||||
|
||||
const elvishLib = "elvish/lib"
|
||||
func defaultStateHome() (string, error) { return homePath(".local/state") }
|
||||
|
||||
func newLibPaths() ([]string, error) {
|
||||
var paths []string
|
||||
libConfig, errConfig := xdgHomePath(env.XDG_CONFIG_HOME, ".config", elvishLib)
|
||||
if errConfig == nil {
|
||||
paths = append(paths, libConfig)
|
||||
func homePath(suffix string) (string, error) {
|
||||
home, err := fsutil.GetHome("")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("resolve ~/%s: %w", suffix, err)
|
||||
}
|
||||
libData, errData := xdgHomePath(env.XDG_DATA_HOME, ".local/share", elvishLib)
|
||||
if errData == nil {
|
||||
paths = append(paths, libData)
|
||||
}
|
||||
|
||||
libSystem := os.Getenv(env.XDG_DATA_DIRS)
|
||||
if libSystem == "" {
|
||||
libSystem = "/usr/local/share:/usr/share"
|
||||
}
|
||||
for _, p := range filepath.SplitList(libSystem) {
|
||||
paths = append(paths, filepath.Join(p, elvishLib))
|
||||
}
|
||||
|
||||
return paths, diag.Errors(errConfig, errData)
|
||||
}
|
||||
|
||||
func newDBPath() (string, error) {
|
||||
return xdgHomePath(env.XDG_STATE_HOME, ".local/state", "elvish/db.bolt")
|
||||
}
|
||||
|
||||
func xdgHomePath(envName, fallback, suffix string) (string, error) {
|
||||
dir := os.Getenv(envName)
|
||||
if dir == "" {
|
||||
home, err := fsutil.GetHome("")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("resolve ~/%s/%s: %w", fallback, suffix, err)
|
||||
}
|
||||
dir = filepath.Join(home, fallback)
|
||||
}
|
||||
return filepath.Join(dir, suffix), nil
|
||||
return filepath.Join(home, suffix), nil
|
||||
}
|
||||
|
||||
// Returns a "run directory" for storing ephemeral files, which is guaranteed
|
||||
|
|
|
@ -9,37 +9,12 @@ import (
|
|||
"src.elv.sh/pkg/env"
|
||||
)
|
||||
|
||||
func newRCPath() (string, error) {
|
||||
d, err := roamingAppData()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(d, "elvish", "rc.elv"), nil
|
||||
}
|
||||
|
||||
func newLibPaths() ([]string, error) {
|
||||
local, err := localAppData()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
localLib := filepath.Join(local, "elvish", "lib")
|
||||
|
||||
roaming, err := roamingAppData()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
roamingLib := filepath.Join(roaming, "elvish", "lib")
|
||||
|
||||
return []string{roamingLib, localLib}, nil
|
||||
}
|
||||
|
||||
func newDBPath() (string, error) {
|
||||
d, err := localAppData()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(d, "elvish", "db.bolt"), nil
|
||||
}
|
||||
var (
|
||||
defaultConfigHome = roamingAppData
|
||||
defaultDataHome = localAppData
|
||||
defaultDataDirs = []string{}
|
||||
defaultStateHome = localAppData
|
||||
)
|
||||
|
||||
func localAppData() (string, error) {
|
||||
return windows.KnownFolderPath(windows.FOLDERID_LocalAppData, windows.KF_FLAG_CREATE)
|
||||
|
|
|
@ -119,9 +119,10 @@ func MakeEvaler(stderr io.Writer) *eval.Evaler {
|
|||
ev := eval.NewEvaler()
|
||||
libs, err := libPaths()
|
||||
if err != nil {
|
||||
fmt.Fprintln(stderr, "Warning:", err)
|
||||
fmt.Fprintln(stderr, "Warning: resolving lib paths:", err)
|
||||
} else {
|
||||
ev.LibDirs = libs
|
||||
}
|
||||
ev.LibDirs = libs
|
||||
mods.AddTo(ev)
|
||||
return ev
|
||||
}
|
||||
|
|
|
@ -23,16 +23,14 @@ Each unit of code read is executed as a [code chunk](language.html#code-chunk).
|
|||
Before the REPL starts, Elvish will execute the **RC file**. Its path is
|
||||
determined as follows:
|
||||
|
||||
- If the legacy `~/.elvish/rc.elv` exists, it is used (this will be ignored in
|
||||
a future version).
|
||||
1. If the legacy `~/.elvish/rc.elv` exists, it is used (this will be ignored
|
||||
starting from 0.20.0).
|
||||
|
||||
- Otherwise:
|
||||
2. If the `XDG_CONFIG_HOME` environment variable is defined and non-empty,
|
||||
`$XDG_CONFIG_HOME/elvish/rc.elv` is used.
|
||||
|
||||
- On UNIX (including macOS), `$XDG_CONFIG_HOME/elvish/rc.elv` is used,
|
||||
defaulting to `~/.config/elvish/rc.elv` if `$XDG_CONFIG_HOME` is unset
|
||||
or empty.
|
||||
|
||||
- On Windows, `%AppData%\elvish\rc.elv` is used.
|
||||
3. Otherwise, `~/.config/elvish/rc.elv` (non-Windows OSes) or
|
||||
`%AppData%\elvish\rc.elv` (Windows) is used.
|
||||
|
||||
If the RC file doesn't exist, Elvish does not execute any RC file.
|
||||
|
||||
|
@ -41,16 +39,14 @@ If the RC file doesn't exist, Elvish does not execute any RC file.
|
|||
Elvish in interactive mode uses a database file to keep command and directory
|
||||
history. Its path is determined as follows:
|
||||
|
||||
- If the legacy `~/.elvish/db` exists, it is used (this will be ignored in a
|
||||
future version).
|
||||
1. If the legacy `~/.elvish/db` exists, it is used (this will be ignored
|
||||
starting from 0.20.0).
|
||||
|
||||
- Otherwise:
|
||||
2. If the `XDG_STATE_HOME` environment variable is defined and non-empty,
|
||||
`$XDG_STATE_HOME/elvish/db.bolt` is used.
|
||||
|
||||
- On UNIX (including macOS), `$XDG_STATE_HOME/elvish/db.bolt` is used,
|
||||
defaulting to `~/.local/state/elvish/db.bolt` if `$XDG_STATE_HOME` is
|
||||
unset or empty.
|
||||
|
||||
- On Windows, `%LocalAppData%\elvish\db.bolt` is used.
|
||||
3. Othersie, `~/.local/state/elvish/db.bolt` (non-Windows OSes) or
|
||||
`%LocalAppData%\elvish\db.bolt` is used.
|
||||
|
||||
# Running a script
|
||||
|
||||
|
@ -72,21 +68,26 @@ When running a script, Elvish does not evaluate the [RC file](#rc-file).
|
|||
When importing [modules](language.html#modules), Elvish searches the following
|
||||
directories:
|
||||
|
||||
- On UNIX:
|
||||
1. If the `XDG_CONFIG_HOME` environment variable is defined and non-empty,
|
||||
`$XDG_CONFIG_HOME/elvish/lib` is searched.
|
||||
|
||||
1. `$XDG_CONFIG_HOME/elvish/lib`, defaulting to `~/.config/elvish/lib` if
|
||||
`$XDG_CONFIG_HOME` is unset or empty;
|
||||
Otherwise, `~/.config/elvish/lib` (non-Window OSes) or
|
||||
`%RoamingAppData%\elvish\lib` (Windows) is searched.
|
||||
|
||||
2. `$XDG_DATA_HOME/elvish/lib`, defaulting to `~/.local/share/elvish/lib` if
|
||||
`$XDG_DATA_HOME` is unset or empty;
|
||||
2. If the `XDG_DATA_HOME` environment variable is defined and non-empty,
|
||||
`$XDG_DATA_HOME/elvish/lib` is searched.
|
||||
|
||||
3. Paths specified in the colon-delimited `$XDG_DATA_DIRS`, followed by
|
||||
`elvish/lib`, defaulting to `/usr/local/share/elvish/lib` and
|
||||
`/usr/share/elvish/lib` if `$XDG_DATA_DIRS` is unset or empty.
|
||||
Otherwise, `~/.local/share/elvish/lib` (non-Windows OSes) or
|
||||
`%LocalAppData%\elvish\lib` (Windows) is searched.
|
||||
|
||||
- On Windows: `%AppData%\elvish\lib`, followed by `%LocalAppData%\elvish\lib`.
|
||||
3. If the `XDG_DATA_DIRS` environment variable is defined and non-empty, it is
|
||||
treated as a colon-delimited list of paths, which are all searched.
|
||||
|
||||
If the legacy `~/.elvish/lib` directory exists, it is also searched.
|
||||
Otherwise, `/usr/local/share/elvish/lib` and `/usr/share/elvish/lib` are
|
||||
searched on non-Windows OSes. On Windows, no directories are searched.
|
||||
|
||||
4. If the legacy `~/.elvish/lib` directory exists, it is also searched (this
|
||||
will be ignored starting from 0.20.0).
|
||||
|
||||
# Command-line flags
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user