Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
b172d8f43d
|
|||
92133a6b2e
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@ dist
|
|||||||
.env
|
.env
|
||||||
.ledo-mode
|
.ledo-mode
|
||||||
main
|
main
|
||||||
|
ledo
|
||||||
|
125
app/cmd/autocomplete.go
Normal file
125
app/cmd/autocomplete.go
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
"github.com/adrg/xdg"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CmdAutocomplete manages autocompletion
|
||||||
|
var CmdAutocomplete = cli.Command{
|
||||||
|
Name: "shellcompletion",
|
||||||
|
Aliases: []string{"autocomplete"},
|
||||||
|
Category: catSetup,
|
||||||
|
Usage: "Install shell completion for ledo",
|
||||||
|
Description: "Install shell completion for ledo",
|
||||||
|
ArgsUsage: "<shell type> (bash, zsh, powershell, fish)",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "install",
|
||||||
|
Usage: "Persist in shell config instead of printing commands",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: runAutocompleteAdd,
|
||||||
|
}
|
||||||
|
|
||||||
|
func runAutocompleteAdd(ctx *cli.Context) error {
|
||||||
|
var remoteFile, localFile, cmds string
|
||||||
|
shell := ctx.Args().First()
|
||||||
|
|
||||||
|
switch shell {
|
||||||
|
case "zsh":
|
||||||
|
remoteFile = "contrib/autocomplete.zsh"
|
||||||
|
localFile = "autocomplete.zsh"
|
||||||
|
cmds = "echo 'PROG=ledo _CLI_ZSH_AUTOCOMPLETE_HACK=1 source \"%s\"' >> ~/.zshrc && source ~/.zshrc"
|
||||||
|
|
||||||
|
case "bash":
|
||||||
|
remoteFile = "contrib/autocomplete.sh"
|
||||||
|
localFile = "autocomplete.sh"
|
||||||
|
cmds = "echo 'PROG=ledo source \"%s\"' >> ~/.bashrc && source ~/.bashrc"
|
||||||
|
|
||||||
|
case "powershell":
|
||||||
|
remoteFile = "contrib/autocomplete.ps1"
|
||||||
|
localFile = "tea.ps1"
|
||||||
|
cmds = "\"& %s\" >> $profile"
|
||||||
|
|
||||||
|
case "fish":
|
||||||
|
return writeFishAutoCompleteFile(ctx)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Must specify valid %s", ctx.Command.ArgsUsage)
|
||||||
|
}
|
||||||
|
|
||||||
|
localPath, err := xdg.ConfigFile("ledo/" + localFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cmds = fmt.Sprintf(cmds, localPath)
|
||||||
|
if err = writeRemoteAutoCompleteFile(remoteFile, localPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.Bool("install") {
|
||||||
|
fmt.Println("Installing in your shellrc")
|
||||||
|
installer := exec.Command(shell, "-c", cmds)
|
||||||
|
if shell == "powershell" {
|
||||||
|
installer = exec.Command("powershell.exe", "-Command", cmds)
|
||||||
|
}
|
||||||
|
out, err := installer.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Couldn't run the commands: %s %s", err, out)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println("\n# Run the following commands to install autocompletion (or use --install)")
|
||||||
|
fmt.Println(cmds)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeRemoteAutoCompleteFile(file, destPath string) error {
|
||||||
|
url := fmt.Sprintf("https://git.cynarski.pl/LeDo/ledo/raw/branch/master/%s", file)
|
||||||
|
fmt.Println("Fetching " + url)
|
||||||
|
|
||||||
|
res, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
writer, err := os.Create(destPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer writer.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(writer, res.Body)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeFishAutoCompleteFile(ctx *cli.Context) error {
|
||||||
|
script, err := ctx.App.ToFishCompletion()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
localPath, err := xdg.ConfigFile("fish/conf.d/tea_completion.fish")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
writer, err := os.Create(localPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err = io.WriteString(writer, script); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("Installed tab completion to %s\n", localPath)
|
||||||
|
return nil
|
||||||
|
}
|
@ -7,7 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var CmdComposeBuild = cli.Command{
|
var CmdComposeBuild = cli.Command{
|
||||||
Name: "pull",
|
Name: "build",
|
||||||
|
Aliases: []string{"b"},
|
||||||
Usage: "build docker image",
|
Usage: "build docker image",
|
||||||
Description: `Build all docker images`,
|
Description: `Build all docker images`,
|
||||||
Action: RunComposeBuild,
|
Action: RunComposeBuild,
|
||||||
|
@ -8,14 +8,19 @@ import (
|
|||||||
|
|
||||||
var CmdComposeRun = cli.Command{
|
var CmdComposeRun = cli.Command{
|
||||||
Name: "run",
|
Name: "run",
|
||||||
|
Aliases: []string{"r"},
|
||||||
Usage: "run cmd in main container",
|
Usage: "run cmd in main container",
|
||||||
Description: `Run command in main container`,
|
Description: `Run command in main container`,
|
||||||
|
ArgsUsage: "[<cmd>]",
|
||||||
Action: RunComposeRun,
|
Action: RunComposeRun,
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunComposeRun(cmd *cli.Context) error {
|
func RunComposeRun(cmd *cli.Context) error {
|
||||||
ctx := context.InitCommand(cmd)
|
ctx := context.InitCommand(cmd)
|
||||||
compose.ExecComposerRun(ctx)
|
if cmd.Args().Len() >= 1 {
|
||||||
|
compose.ExecComposerRun(ctx, cmd.Args())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
var CmdComposeShell = cli.Command{
|
var CmdComposeShell = cli.Command{
|
||||||
Name: "shell",
|
Name: "shell",
|
||||||
|
Aliases: []string{"sh"},
|
||||||
Usage: "run shell from main service",
|
Usage: "run shell from main service",
|
||||||
Description: `Execute shell cmd in main service`,
|
Description: `Execute shell cmd in main service`,
|
||||||
Action: RunComposeShell,
|
Action: RunComposeShell,
|
||||||
|
@ -10,7 +10,7 @@ var CmdComposeStop = cli.Command{
|
|||||||
Name: "stop",
|
Name: "stop",
|
||||||
Usage: "stop containers",
|
Usage: "stop containers",
|
||||||
Description: `Stop all containers defined in docker-compose stack mode`,
|
Description: `Stop all containers defined in docker-compose stack mode`,
|
||||||
Action: RunComposePull,
|
Action: RunComposeStop,
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunComposeStop(cmd *cli.Context) error {
|
func RunComposeStop(cmd *cli.Context) error {
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/Masterminds/semver"
|
"github.com/Masterminds/semver"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"ledo/app/modules/context"
|
"ledo/app/modules/context"
|
||||||
@ -147,9 +148,13 @@ func ExecComposerDebug(ctx *context.LedoContext) {
|
|||||||
ctx.ExecCmd("docker-compose", args[0:])
|
ctx.ExecCmd("docker-compose", args[0:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExecComposerRun(ctx *context.LedoContext) {
|
func ExecComposerRun(ctx *context.LedoContext, command cli.Args) {
|
||||||
args := ctx.ComposeArgs
|
args := ctx.ComposeArgs
|
||||||
args = append(args, "run", strings.ToLower(ctx.Config.Docker.MainService), ctx.Config.Docker.Shell)
|
args = append(args, "run", strings.ToLower(ctx.Config.Docker.MainService))
|
||||||
|
if ctx.Config.Docker.Username != "" {
|
||||||
|
args = append(args, "sudo", "-E", "-u", ctx.Config.Docker.Username)
|
||||||
|
}
|
||||||
|
args = append(args, command.Slice()...)
|
||||||
ctx.ExecCmd("docker-compose", args[0:])
|
ctx.ExecCmd("docker-compose", args[0:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ type DockerMap struct {
|
|||||||
Name string `yaml:"name,omitempty"`
|
Name string `yaml:"name,omitempty"`
|
||||||
MainService string `yaml:"main_service,omitempty"`
|
MainService string `yaml:"main_service,omitempty"`
|
||||||
Shell string `yaml:"shell,omitempty"`
|
Shell string `yaml:"shell,omitempty"`
|
||||||
|
Username string `yaml:"username,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLedoFile(s string) (*LedoFile, error) {
|
func NewLedoFile(s string) (*LedoFile, error) {
|
||||||
|
9
contrib/autocomplete.ps1
Normal file
9
contrib/autocomplete.ps1
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
$fn = $($MyInvocation.MyCommand.Name)
|
||||||
|
$name = $fn -replace "(.*)\.ps1$", '$1'
|
||||||
|
Register-ArgumentCompleter -Native -CommandName $name -ScriptBlock {
|
||||||
|
param($commandName, $wordToComplete, $cursorPosition)
|
||||||
|
$other = "$wordToComplete --generate-bash-completion"
|
||||||
|
Invoke-Expression $other | ForEach-Object {
|
||||||
|
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
|
||||||
|
}
|
||||||
|
}
|
21
contrib/autocomplete.sh
Normal file
21
contrib/autocomplete.sh
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
: ${PROG:=$(basename ${BASH_SOURCE})}
|
||||||
|
|
||||||
|
_cli_bash_autocomplete() {
|
||||||
|
if [[ "${COMP_WORDS[0]}" != "source" ]]; then
|
||||||
|
local cur opts base
|
||||||
|
COMPREPLY=()
|
||||||
|
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||||
|
if [[ "$cur" == "-"* ]]; then
|
||||||
|
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} ${cur} --generate-bash-completion )
|
||||||
|
else
|
||||||
|
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion )
|
||||||
|
fi
|
||||||
|
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
complete -o bashdefault -o default -o nospace -F _cli_bash_autocomplete $PROG
|
||||||
|
unset PROG
|
23
contrib/autocomplete.zsh
Normal file
23
contrib/autocomplete.zsh
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#compdef $PROG
|
||||||
|
|
||||||
|
_cli_zsh_autocomplete() {
|
||||||
|
|
||||||
|
local -a opts
|
||||||
|
local cur
|
||||||
|
cur=${words[-1]}
|
||||||
|
if [[ "$cur" == "-"* ]]; then
|
||||||
|
opts=("${(@f)$(_CLI_ZSH_AUTOCOMPLETE_HACK=1 ${words[@]:0:#words[@]-1} ${cur} --generate-bash-completion)}")
|
||||||
|
else
|
||||||
|
opts=("${(@f)$(_CLI_ZSH_AUTOCOMPLETE_HACK=1 ${words[@]:0:#words[@]-1} --generate-bash-completion)}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${opts[1]}" != "" ]]; then
|
||||||
|
_describe 'values' opts
|
||||||
|
else
|
||||||
|
_files
|
||||||
|
fi
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
compdef _cli_zsh_autocomplete $PROG
|
1
go.mod
1
go.mod
@ -5,6 +5,7 @@ go 1.17
|
|||||||
require (
|
require (
|
||||||
github.com/AlecAivazis/survey/v2 v2.3.2
|
github.com/AlecAivazis/survey/v2 v2.3.2
|
||||||
github.com/Masterminds/semver v1.5.0
|
github.com/Masterminds/semver v1.5.0
|
||||||
|
github.com/adrg/xdg v0.3.4
|
||||||
github.com/spf13/viper v1.8.1
|
github.com/spf13/viper v1.8.1
|
||||||
github.com/thoas/go-funk v0.9.1
|
github.com/thoas/go-funk v0.9.1
|
||||||
github.com/urfave/cli/v2 v2.3.0
|
github.com/urfave/cli/v2 v2.3.0
|
||||||
|
2
go.sum
2
go.sum
@ -45,6 +45,8 @@ github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3Q
|
|||||||
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
|
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
|
||||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
|
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
|
||||||
|
github.com/adrg/xdg v0.3.4 h1:0BivHfQ0LSGQrFTaEZ0hyQLm/HAidci7m+1cT6wKKdA=
|
||||||
|
github.com/adrg/xdg v0.3.4/go.mod h1:61xAR2VZcggl2St4O9ohF5qCKe08+JDmE4VNzPFQvOQ=
|
||||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||||
|
1
main.go
1
main.go
@ -21,6 +21,7 @@ func main() {
|
|||||||
app.Commands = []*cli.Command{
|
app.Commands = []*cli.Command{
|
||||||
&cmd.CmdDocker,
|
&cmd.CmdDocker,
|
||||||
&cmd.CmdMode,
|
&cmd.CmdMode,
|
||||||
|
&cmd.CmdAutocomplete,
|
||||||
}
|
}
|
||||||
app.EnableBashCompletion = true
|
app.EnableBashCompletion = true
|
||||||
err := app.Run(os.Args)
|
err := app.Run(os.Args)
|
||||||
|
Reference in New Issue
Block a user