Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add more shell types support #14

Merged
merged 1 commit into from
Feb 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ For instance, it will execute those commands which in Markdown block via `mde RE
ifconfig
```

Run in different shells:
```zsh
#!title: Run in zsh
readlink /proc/$$/exe
```

```dash
#!title: Run in dash
readlink /proc/$$/exe
```

### Variable input support
In some use cases, we need to change the variables or command line flags. Try the following demo:

Expand Down
38 changes: 38 additions & 0 deletions cli/golang_runner_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package cli

import (
"github.com/linuxsuren/http-downloader/pkg/exec"
"github.com/stretchr/testify/assert"
"testing"
)

func TestGolangRunner(t *testing.T) {
tests := []struct {
name string
title string
shellType string
cmd string
hasErr bool
}{{
name: "normal bash",
title: "title",
shellType: "bash",
cmd: `#!title: title
echo 1`,
hasErr: false,
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
shell := &GolangScript{
Script: Script{
Title: tt.title,
Content: tt.cmd,
Execer: exec.FakeExecer{},
},
}
assert.Equal(t, tt.title, shell.GetTitle())
err := shell.Run()
assert.Equal(t, tt.hasErr, err != nil)
})
}
}
38 changes: 38 additions & 0 deletions cli/python_runner_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package cli

import (
"github.com/linuxsuren/http-downloader/pkg/exec"
"github.com/stretchr/testify/assert"
"testing"
)

func TestPythonRunner(t *testing.T) {
tests := []struct {
name string
title string
shellType string
cmd string
hasErr bool
}{{
name: "normal bash",
title: "title",
shellType: "bash",
cmd: `#!title: title
echo 1`,
hasErr: false,
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
shell := &PythonScript{
Script: Script{
Title: tt.title,
Content: tt.cmd,
Execer: exec.FakeExecer{},
},
}
assert.Equal(t, tt.title, shell.GetTitle())
err := shell.Run()
assert.Equal(t, tt.hasErr, err != nil)
})
}
}
10 changes: 7 additions & 3 deletions cli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ func (o *option) runE(cmd *cobra.Command, args []string) (err error) {
}

for _, file := range files {
if !strings.HasSuffix(file, ".md") {
continue
}
var runners ScriptRunners
if runners, err = o.parseMarkdownRunner(file); err != nil {
break
Expand Down Expand Up @@ -120,9 +123,10 @@ func (o *option) parseMarkdownRunner(mdFilePath string) (scriptList ScriptRunner
}

switch lang {
case "shell", "bash":
case "shell", "bash", "zsh", "csh", "tcsh", "dash", "fish", "ksh":
scriptList = append(scriptList, &ShellScript{
Script: script,
Script: script,
ShellType: lang,
})
case "python3":
scriptList = append(scriptList, &PythonScript{
Expand Down Expand Up @@ -150,7 +154,7 @@ func (o *option) executeScripts(scriptRunners ScriptRunners) (err error) {
Message: "Choose the code block to run",
Options: scriptRunners.GetTitles(),
}
titles := []string{}
var titles []string
if err = survey.AskOne(selector, &titles, survey.WithKeepFilter(o.keepFilter)); err != nil {
return
}
Expand Down
11 changes: 11 additions & 0 deletions cli/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@ package cli

import (
"bytes"
"os"
"testing"

"github.com/linuxsuren/http-downloader/pkg/exec"
"github.com/stretchr/testify/assert"
)

func TestNewRootCommand(t *testing.T) {
f, err := os.CreateTemp(os.TempDir(), "")
assert.Nil(t, err)
defer func() {
_ = f.Close()
}()

tests := []struct {
name string
args []string
Expand All @@ -17,6 +24,10 @@ func TestNewRootCommand(t *testing.T) {
name: "no argument",
args: nil,
hasErr: true,
}, {
name: "a single file which is not Markdown",
args: []string{f.Name()},
hasErr: false,
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
19 changes: 16 additions & 3 deletions cli/shell_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cli

import (
"fmt"
"github.com/linuxsuren/http-downloader/pkg/installer"
"io"
"os"
"path"
Expand All @@ -14,6 +15,7 @@ import (
// ShellScript represents the shell script
type ShellScript struct {
Script
ShellType string
}

// Run executes the script
Expand All @@ -40,7 +42,7 @@ func (s *ShellScript) Run() (err error) {
if pair, err = inputRequest(pair); err != nil {
break
}
os.Setenv(pair[0], pair[1])
_ = os.Setenv(pair[0], pair[1])
continue
} else {
err = s.runCmdLine(strings.Join(lines[i:], "\n"), s.Dir, s.KeepScripts)
Expand All @@ -51,7 +53,7 @@ func (s *ShellScript) Run() (err error) {
// reset the env
os.Clearenv()
for _, pair := range preDefinedEnv {
os.Setenv(strings.Split(pair, "=")[0], strings.Split(pair, "=")[1])
_ = os.Setenv(strings.Split(pair, "=")[0], strings.Split(pair, "=")[1])
}
return
}
Expand All @@ -68,7 +70,18 @@ func (s *ShellScript) runCmdLine(cmdLine, contextDir string, keepScripts bool) (
}()
}

err = s.Execer.RunCommandInDir("bash", contextDir, path.Base(shellFile))
if s.ShellType == "shell" || s.ShellType == "" {
s.ShellType = "bash"
}

is := installer.Installer{
Provider: "github",
}
if err = is.CheckDepAndInstall(map[string]string{
s.ShellType: s.ShellType,
}); err == nil {
err = s.Execer.RunCommandInDir(s.ShellType, contextDir, path.Base(shellFile))
}
return
}

Expand Down
55 changes: 55 additions & 0 deletions cli/shell_runner_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,52 @@
package cli

import (
"fmt"
"github.com/linuxsuren/http-downloader/pkg/exec"
"testing"

"github.com/stretchr/testify/assert"
)

func TestShell(t *testing.T) {
tests := []struct {
name string
title string
shellType string
cmd string
hasErr bool
}{{
name: "normal bash",
title: "title",
shellType: "bash",
cmd: `#!title: title
echo 1`,
hasErr: false,
}, {
name: "shell type is empty",
title: "title",
shellType: "",
cmd: `#!title: title
echo 1`,
hasErr: false,
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
shell := &ShellScript{
Script: Script{
Title: tt.title,
Content: tt.cmd,
Execer: exec.FakeExecer{},
},
ShellType: tt.shellType,
}
assert.Equal(t, tt.title, shell.GetTitle())
err := shell.Run()
assert.Equal(t, tt.hasErr, err != nil)
})
}
}

func TestIsInputRequest(t *testing.T) {
tests := []struct {
name string
Expand Down Expand Up @@ -41,3 +82,17 @@ func TestIsInputRequest(t *testing.T) {
})
}
}

func FuzzInputRequest(f *testing.F) {
f.Add("a", "b")
f.Fuzz(func(t *testing.T, key, value string) {
ok, pair, err := isInputRequest(fmt.Sprintf("%s=%s", key, value))
assert.True(t, ok)
assert.Equal(t, key, pair[0])
assert.Equal(t, value, pair[1])
assert.Nil(t, err)
if err != nil {
t.Fail()
}
})
}
24 changes: 22 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,39 @@ require (
)

require (
github.com/Microsoft/go-winio v0.4.16 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
github.com/acomagu/bufpipe v1.0.3 // indirect
github.com/antonmedv/expr v1.11.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emirpasic/gods v1.12.0 // indirect
github.com/go-git/gcfg v1.5.0 // indirect
github.com/go-git/go-billy/v5 v5.3.1 // indirect
github.com/go-git/go-git/v5 v5.4.2 // indirect
github.com/google/go-github/v29 v29.0.3 // indirect
github.com/google/go-querystring v1.0.0 // indirect
github.com/gosuri/uilive v0.0.3 // indirect
github.com/gosuri/uiprogress v0.0.1 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
github.com/mattn/go-colorable v0.1.6 // indirect
github.com/mattn/go-isatty v0.0.12 // indirect
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/xanzy/ssh-agent v0.3.0 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/text v0.3.8 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

Expand Down
Loading