1package main
2
3import (
4	"fmt"
5	"strings"
6	"time"
7)
8
9type actionSimple func(env Env, args []string) error
10
11func (fn actionSimple) Call(env Env, args []string, config *Config) error {
12	return fn(env, args)
13}
14
15type actionWithConfig func(env Env, args []string, config *Config) error
16
17func (fn actionWithConfig) Call(env Env, args []string, config *Config) error {
18	var err error
19	if config == nil {
20		config, err = LoadConfig(env)
21		if err != nil {
22			return err
23		}
24	}
25
26	return fn(env, args, config)
27}
28
29type action interface {
30	Call(env Env, args []string, config *Config) error
31}
32
33// Cmd represents a direnv sub-command
34type Cmd struct {
35	Name    string
36	Desc    string
37	Args    []string
38	Aliases []string
39	Private bool
40	Action  action
41}
42
43// CmdList contains the list of all direnv sub-commands
44var CmdList []*Cmd
45
46func init() {
47	CmdList = []*Cmd{
48		CmdAllow,
49		CmdApplyDump,
50		CmdShowDump,
51		CmdDeny,
52		CmdDotEnv,
53		CmdDump,
54		CmdEdit,
55		CmdExec,
56		CmdExport,
57		CmdFetchURL,
58		CmdHelp,
59		CmdHook,
60		CmdPrune,
61		CmdReload,
62		CmdStatus,
63		CmdStdlib,
64		CmdVersion,
65		CmdWatch,
66		CmdWatchDir,
67		CmdWatchList,
68		CmdCurrent,
69	}
70}
71
72func cmdWithWarnTimeout(fn action) action {
73	return actionWithConfig(func(env Env, args []string, config *Config) (err error) {
74		done := make(chan bool, 1)
75		go func() {
76			select {
77			case <-done:
78				return
79			case <-time.After(config.WarnTimeout):
80				logError("(%v) is taking a while to execute. Use CTRL-C to give up.", args)
81			}
82		}()
83
84		err = fn.Call(env, args, config)
85		done <- true
86		return err
87	})
88}
89
90// CommandsDispatch is called by the main() function to dispatch to a sub-command
91func CommandsDispatch(env Env, args []string) error {
92	var command *Cmd
93	var commandName string
94	var commandPrefix string
95	var commandArgs []string
96
97	if len(args) < 2 {
98		commandName = "help"
99		commandPrefix = args[0]
100		commandArgs = []string{}
101	} else {
102		commandName = args[1]
103		commandPrefix = strings.Join(args[0:2], " ")
104		commandArgs = append([]string{commandPrefix}, args[2:]...)
105	}
106
107	for _, cmd := range CmdList {
108		if cmd.Name == commandName {
109			command = cmd
110			break
111		}
112		if cmd.Aliases != nil {
113			for _, alias := range cmd.Aliases {
114				if alias == commandName {
115					command = cmd
116				}
117			}
118		}
119	}
120
121	if command == nil {
122		return fmt.Errorf("command \"%s\" not found", commandPrefix)
123	}
124
125	return command.Action.Call(env, commandArgs, nil)
126}
127