runShell is used to run a shell command. Modes are as follows: Prefix Wait Async Stdin Stdout Stderr UI action $ No No Yes Yes Yes Pause and then resume % No No Yes Yes Yes Statline for input/output ! Yes No Yes Yes Yes
(s string, args []string, prefix string)
| 568 | // ! Yes No Yes Yes Yes Pause and then resume |
| 569 | // & No Yes No No No Do nothing |
| 570 | func (app *app) runShell(s string, args []string, prefix string) { |
| 571 | app.nav.exportFiles() |
| 572 | app.ui.exportSizes() |
| 573 | app.exportMode() |
| 574 | exportLfPath() |
| 575 | exportOpts() |
| 576 | |
| 577 | gState.mutex.Lock() |
| 578 | gState.data["maps"] = listBinds(map[string]map[string]expr{ |
| 579 | "n": gOpts.nkeys, |
| 580 | "v": gOpts.vkeys, |
| 581 | }) |
| 582 | gState.data["nmaps"] = listBinds(map[string]map[string]expr{ |
| 583 | "n": gOpts.nkeys, |
| 584 | }) |
| 585 | gState.data["vmaps"] = listBinds(map[string]map[string]expr{ |
| 586 | "v": gOpts.vkeys, |
| 587 | }) |
| 588 | gState.data["cmaps"] = listBinds(map[string]map[string]expr{ |
| 589 | "c": gOpts.cmdkeys, |
| 590 | }) |
| 591 | gState.data["cmds"] = listCmds(gOpts.cmds) |
| 592 | gState.data["jumps"] = listJumps(app.nav.jumpList, app.nav.jumpListInd) |
| 593 | gState.data["history"] = listHistory(app.cmdHistory) |
| 594 | gState.data["files"] = listFilesInCurrDir(app.nav) |
| 595 | gState.mutex.Unlock() |
| 596 | |
| 597 | cmd := shellCommand(s, args) |
| 598 | |
| 599 | switch prefix { |
| 600 | case "$", "!": |
| 601 | cmd.Stdin = os.Stdin |
| 602 | cmd.Stdout = os.Stderr |
| 603 | cmd.Stderr = os.Stderr |
| 604 | |
| 605 | app.runCmdSync(cmd, prefix == "!") |
| 606 | return |
| 607 | } |
| 608 | |
| 609 | // We are running the command asynchronously |
| 610 | var inReader, inWriter, outReader, outWriter *os.File |
| 611 | if prefix == "%" { |
| 612 | if app.ui.cmdPrefix == ">" { |
| 613 | return |
| 614 | } |
| 615 | |
| 616 | // [exec.Cmd.StdoutPipe] cannot be used as it requires the output to be fully |
| 617 | // read before calling [exec.Cmd.Wait], however in this case Cmd.Wait should |
| 618 | // only wait for the command to finish executing regardless of whether the |
| 619 | // output has been fully read or not. |
| 620 | var err error |
| 621 | inReader, inWriter, err = os.Pipe() |
| 622 | if err != nil { |
| 623 | log.Printf("creating input pipe: %s", err) |
| 624 | return |
| 625 | } |
| 626 | cmd.Stdin = inReader |
| 627 | app.cmdIn = inWriter |
no test coverage detected