Add a cross-platform way to execute a shell command and string utilities

pull/6/head
Mickaël Menu 3 years ago
parent cd2040a74b
commit f1df4320ed
No known key found for this signature in database
GPG Key ID: 53D73664CD359895

@ -25,6 +25,14 @@ func (s *Styler) Style(text string, rules ...style.Rule) (string, error) {
return color.New(attrs...).Sprint(text), nil
}
func (s *Styler) MustStyle(text string, rules ...style.Rule) string {
text, err := s.Style(text, rules...)
if err != nil {
panic(err.Error())
}
return text
}
// FIXME: User config
var themeAliases = map[style.Rule][]style.Rule{
"title": {"bold", "yellow"},

@ -3,11 +3,11 @@ package note
import (
"fmt"
"os"
"os/exec"
"github.com/kballard/go-shellquote"
"github.com/mickael-menu/zk/core/zk"
"github.com/mickael-menu/zk/util/errors"
"github.com/mickael-menu/zk/util/exec"
"github.com/mickael-menu/zk/util/opt"
osutil "github.com/mickael-menu/zk/util/os"
)
@ -30,7 +30,7 @@ func Edit(zk *zk.Zk, path string) error {
}
args = append(args, path)
cmd := exec.Command(args[0], args[1:]...)
cmd := exec.CommandFromString(editor.String() + " '" + path + "'")
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout

@ -0,0 +1,3 @@
// +build !windows
package exec

@ -0,0 +1,17 @@
// +build !windows
package exec
import (
"os"
"os/exec"
)
// CommandFromString returns a Cmd running the given command with $SHELL.
func CommandFromString(command string) *exec.Cmd {
shell := os.Getenv("SHELL")
if len(shell) == 0 {
shell = "sh"
}
return exec.Command(shell, "-c", command)
}

@ -0,0 +1,18 @@
package exec
import (
"fmt"
"os/exec"
"syscall"
)
// CommandFromString returns a Cmd running the given command.
func CommandFromString(command string) *exec.Cmd {
cmd := exec.Command("cmd")
cmd.SysProcAttr = &syscall.SysProcAttr{
HideWindow: false,
CmdLine: fmt.Sprintf(` /v:on/s/c "%s"`, command),
CreationFlags: 0,
}
return cmd
}

@ -11,6 +11,7 @@ import (
"github.com/kballard/go-shellquote"
"github.com/mickael-menu/zk/util"
"github.com/mickael-menu/zk/util/errors"
executil "github.com/mickael-menu/zk/util/exec"
"github.com/mickael-menu/zk/util/opt"
osutil "github.com/mickael-menu/zk/util/os"
)
@ -39,11 +40,7 @@ func New(pagerCmd opt.String, logger util.Logger) (*Pager, error) {
return PassthroughPager, nil
}
args, err := shellquote.Split(pagerCmd.String())
if err != nil {
return nil, wrap(err)
}
cmd := exec.Command(args[0], args[1:]...)
cmd := executil.CommandFromString(pagerCmd.String())
r, w, err := os.Pipe()
if err != nil {

@ -1,6 +1,9 @@
package strings
import "strings"
import (
"bufio"
"strings"
)
// Prepend prefixes each lines of a string with the given prefix.
// It can be used to indent or quote (> ) a paragraph, for example.
@ -25,3 +28,20 @@ func Pluralize(word string, count int) string {
return word + "s"
}
}
// SplitLines splits a string by the newlines character in a portable way
// Using only `strings.Split(s, "\n")` doesn't work on Windows.
func SplitLines(s string) []string {
var lines []string
scanner := bufio.NewScanner(strings.NewReader(s))
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return lines
}
// JoinLines joins each lines of the given string by replacing the newlines by
// a single space.
func JoinLines(s string) string {
return strings.Join(SplitLines(s), " ")
}

@ -32,3 +32,26 @@ func TestPluralize(t *testing.T) {
test("word", 2, "words")
test("word", 1000, "words")
}
func TestSplitLines(t *testing.T) {
test := func(text string, expected ...string) {
assert.Equal(t, SplitLines(text), expected)
}
test("")
test("One line", "One line")
test("One line\nTwo lines", "One line", "Two lines")
test("One line\nTwo lines\n\nThree lines", "One line", "Two lines", "", "Three lines")
}
func TestJoinLines(t *testing.T) {
test := func(text string, expected string) {
assert.Equal(t, JoinLines(text), expected)
}
test("", "")
test("One line", "One line")
test("One line\nTwo lines", "One line Two lines")
test("One line\nTwo lines\n\nThree lines", "One line Two lines Three lines")
test("One line\nTwo lines\n Three lines", "One line Two lines Three lines")
}

Loading…
Cancel
Save