Giter Site home page Giter Site logo

procmux's Introduction

procmux

a TUI utility for running multiple commands in parallel in easily switchable terminals

this app is heavily influenced by this TUI app: https://github.com/pvolok/mprocs

The goals/use-cases:

procmux allows the user to run multiple commands in parallel and makes it easy to view the output from each terminal session. Procmux configuration files can be included in projects that have a series of commonly used scripts / long-running processes. is intended to make it easy for newcomers to a project to browse and run necessary commands, while also reducing the need to manually spin up multiple terminal sessions for potentially long-running processes. Alternatively, personal or system-wide procmux config files can be defined for browsing/running snippets or commonly used shell scripts.

Alt Text

Installation

# if you use pipx
pipx install procmux

# if you use pip
pip install procmux

# if you use brew
brew tap napisani/procmux
brew install procmux

Usage

# standard usage
procmux --config /path/to/config.yaml

# with overriding config values
procmux --config /path/to/config.yaml --config-override /path/to/override-file.yaml

Configuration

Here is a procmux configuration example with ALL available configuration points. Only the procs section is required, the rest of the properties have defaults predefined:

procmux.yaml

layout:
  # hide or show the help window that show all keybindings and actions at the bottom of the screen
  hide_help: false
  # hide or show the window second from the bottom that shows the full command name and the description
  hide_process_description_panel: false
  # the prompt_toolkit width of the sidebar (containing all the process names)
  processes_list_width: 31
  # whether to sort the process list alphabetically
  sort_process_list_alpha: True
  # used as the prefix for category filters of the process list
  category_search_prefix: 'cat:'
  # the prompt template to be rendered everytime a field replacement input box is rendered
  # __FIELD_NAME__ will be replaced by the field name defined in the replacement definition 
  # IE: `echo "<something>"`  # field name is 'something'
  field_replacement_prompt: '__FIELD_NAME__ ⮕  '
style:
  #foreground color of the process in the process list when it is selected
  selected_process_color: 'ansiblack'
  #background color of the process in the process list when it is selected
  selected_process_bg_color: 'ansimagenta'
  #foregroud color of the process in the process list when it is not selected
  unselected_process_color: 'ansiblue'
  #foregroud color of the process list status when the status is RUNNING
  status_running_color: 'ansigreen'
  #foregroud color of the process list status when the status is STOPPED
  status_stopped_color: 'ansired'
  #the color of the right panel (terminal panel) when no terminal is created/selected yet
  placeholder_terminal_bg_color: '#1a1b26'
  # show or hide the border around the terminal panel and side bar
  show_borders: true 
  # whether to show the scrollbar on the right side of the sidebar 
  show_scrollbar: true 
  #character used to indicate the current selection
  pointer_char: ''
  #override default style classes
  #https://github.com/prompt-toolkit/python-prompt-toolkit/blob/master/src/prompt_toolkit/styles/defaults.py
  style_classes:
    cursor-line: 'underline'
  #one of: monochrome | ansicolors | 256colors | truecolors
  color_level: 'truecolors'
keybinding:
  # a map of app actions to their respective key bindings.
  # each key combo in an action list is an alias for the same action.
  # IE up is fired when 'j' or the 'up arrow' is pressed
  # All modifiers for a keybinding should be included in the same list element IE: switch focus - 'c-w' (Control-W)
  quit:
    - q
  filter:
    - /
  submit_filter:
    - enter
  start:
    - s
  stop:
    - x
  up:
    - up
    - k
  down:
    - down
    - j
  docs:
    - ?
  switch_focus:
    - 'c-w'
  zoom:
    - 'c-z'
  # using a keybinding of 'disabled' will remove any keybinding entirely
  #zoom:
  #  - 'disabled'
  toggle_scroll:
    - 'c-s'
shell_cmd:
  # this is the command used for all 'procs' that are defined with a 'shell' property.
  # by default the configured "$SHELL" environment variable will be used.
  - '/bin/bash'
  - '-c'

# if this property is defined, the app will log all debug, info, error level logs to the designated file
log_file: /tmp/term.log
enable_mouse: true
procs:
  # each key will show up as its own process/script in the process list
  "tail log":
    # the shell command to run when this process is started
    shell: "tail -f /tmp/term.log"
    # whether to start this process when ProcMux starts
    autostart: true
    # a short description of what this process/command does - will be displayed at the bottom of the screen when selected
    description: 'tail the app log'
    # meta tags will be searched against for during process filtering
    # meta tags much match fully (unlike the process name itself, which is fuzzy matched)
    meta_tags:
      - "follow"
      - "-f"
  "print envs":
    shell: "echo $SOME_TEST"
    description: 'this command will print env vars that are configured in the child pid'
    #used for showing man page/documentation dialog when the docs keybinding is pressed
    docs: |
      <b>echo an env var set in the child pid</b>
      <style fg="ansigreen">first an env var is set in the child pid</style>
      <style fg="ansiblue">then the var is printed</style>
    # environment variables before the command/shell is invoked
    env:
      SOME_TEST: "AAAAAA"
  "vim":
    shell: "vim"
    autostart: false
    description: 'start vim'
    # categories can be used to view your process list by single groups using filters formatted
    # like this: `cat:<category name>` 
    # IE: `cat:edit` - this will show all processes that have a category 'edit'
    categories:
      - "edit"
    
      
  "long running print":
    shell: "echo 'some text here' && sleep 3 && echo 'still running'  && sleep 3 && echo 'final text'"
    autostart: false
    description: 'print a using sleeps in between'
  "print colors":
    shell: "./print_colors.sh"
    # used to change the directory that the command/process is started from
    cwd: "/Users/nick/code/procmux-tui"
    autostart: false
    description: 'test terminal colors'
  "just echo":
    # an example of using a specific CMD list instead of a shell string
    cmd:
      - '/bin/bash'
      - '-c'
      - 'echo "DONE!"'
    autostart: false
    description: 'run using cmd property'
  "interpolation":
    # processes can be defined with replaceable values in this format <field_name:default> or <field_name>
    # when processes with interpolated values are started, the user will be prompted to enter values for each field.
    # processes with interpolated values cannot be configured with 'autostart: true' 
    shell: "echo '<first_echo:some default>' && echo '<second_echo>'"
    autostart: false 
    description: 'test interpolation'

# these settings are used to control a signal server that can be used to send signals to procmux managed processes
# using another terminal or script. when the signal server is enabled, it will listen on the configured host and port
# for incoming signals. the signal server can be used to send signals to procmux managed processes without having procmux
# in focus.
# the procmux app can be used to send signals. Use any of the available procmux subcommands to send signals to the signal # server. IE: `procmux signal-stop --name 'long running print' --config /path/to/procmux.yaml`
signal_server:
  enable: true 
  host: 'localhost'
  port: 9792

procmux's People

Contributors

napisani avatar erhickey avatar

Stargazers

Shaik Noorullah Shareef avatar  avatar Kirill avatar  avatar  avatar Pablo avatar Mario Rugiero avatar Nic Fontaine avatar Jefferson Phillips avatar Sean Lee avatar joh6nn avatar  avatar  avatar Fulvio Scapin avatar Raza avatar Thomas Soteros avatar  avatar Thorhallur O avatar Andy McFarland avatar  avatar Cori Eisele avatar NSR avatar Yuki Nagato avatar  avatar Vladislav Sorokin avatar  avatar  avatar Hank Faust avatar  avatar Phani Rithvij avatar Felipe Delgado avatar  avatar  avatar William Allen avatar Ajam avatar Osirys avatar  avatar Altynbek Isabekov avatar cocoonk1d avatar  avatar Rahul Kalkani avatar Tim Rosulnik avatar Liam Don avatar Wes McNamee avatar Nikolaus Schlemm avatar David M. Golembiowski avatar  avatar  avatar Andrea Bonomi avatar  avatar Damien Pretet avatar Eugene Klimov avatar Marcus Weinberger avatar Eigengrau avatar  avatar Diego Rapoport avatar Blake Watters avatar  avatar  avatar

Watchers

 avatar  avatar  avatar David M. Golembiowski avatar

procmux's Issues

example config file bug with ?

Ran the project to test it out, and immediately got a stack trace when using the example config (https://github.com/napisani/procmux#configuration)

❯ procmux --config mux.op.yml 
Traceback (most recent call last):
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/cache.py", line 35, in get
    return self._data[key]
KeyError: 1

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/bin/procmux", line 8, in <module>
    sys.exit(start_cli())
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/procmux.py", line 8, in start_cli
    run_app(config)
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/app/__main__.py", line 14, in run_app
    start_tui(cfg)
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/app/tui/app.py", line 66, in start_tui
    application.run()
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/application/application.py", line 736, in run
    return run()
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/application/application.py", line 710, in run
    return f.result()
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/eventloop/future.py", line 151, in result
    raise self._exception
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/eventloop/coroutine.py", line 92, in step_next
    new_f = coroutine.throw(exc)
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/application/application.py", line 685, in _run_async2
    result = yield f
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/eventloop/coroutine.py", line 88, in step_next
    new_f = coroutine.send(None)
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/application/application.py", line 628, in _run_async
    self._redraw()
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/application/application.py", line 471, in _redraw
    self.renderer.render(self, self.layout)
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/renderer.py", line 582, in render
    layout.container.write_to_screen(screen, mouse_handlers, WritePosition(
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/layout/containers.py", line 656, in write_to_screen
    self.content.write_to_screen(
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/layout/containers.py", line 2234, in write_to_screen
    self._get_container().write_to_screen(*a, **kw)
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/layout/containers.py", line 314, in write_to_screen
    c.write_to_screen(screen, mouse_handlers,
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/layout/containers.py", line 2196, in write_to_screen
    return self.content.write_to_screen(
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/layout/containers.py", line 1448, in write_to_screen
    draw_func()
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/layout/containers.py", line 1466, in _write_to_screen_at_index
    ui_content = self.content.create_content(
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/layout/controls.py", line 323, in create_content
    fragments_with_mouse_handlers = self._get_formatted_text_cached()
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/layout/controls.py", line 304, in _get_formatted_text_cached
    return self._fragment_cache.get(
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/cache.py", line 38, in get
    value = getter_func()
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/layout/controls.py", line 306, in <lambda>
    lambda: to_formatted_text(self.text, self.style))
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/formatted_text/base.py", line 45, in to_formatted_text
    return to_formatted_text(value(), style=style)
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/app/tui/view/help.py", line 32, in _get_formatted_text
    result = [self._get_key_combo_text(help_) for help_ in self._controller.get_app_keybindings().help_docs]
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/app/tui/controller/tui_controller.py", line 375, in get_app_keybindings
    self._add_side_bar_keybindings(kb)
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/app/tui/controller/tui_controller.py", line 428, in _add_side_bar_keybindings
    kb.register_configured_keybinding_sans_event(
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/app/tui/keybindings.py", line 22, in register_configured_keybinding_sans_event
    self.register_configured_keybinding(keys, lambda _: handler(), help_label=help_label)
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/app/tui/keybindings.py", line 33, in register_configured_keybinding
    @self.add(keybinding)
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/key_binding/key_bindings.py", line 189, in add
    keys = tuple(_check_and_expand_key(k) for k in keys)
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/key_binding/key_bindings.py", line 189, in <genexpr>
    keys = tuple(_check_and_expand_key(k) for k in keys)
  File "/home/matthieu/.cache/pypoetry/virtualenvs/server--_HPI2hw-py3.10/lib/python3.10/site-packages/prompt_toolkit/key_binding/key_bindings.py", line 329, in _check_and_expand_key
    key = KEY_ALIASES.get(key, key)
TypeError: unhashable type: 'collections.OrderedDict'

I debugged it to the "docs" key in the config file using the question mark:

keybinding:
  docs:
    - ?

it decodes to {'keybinding': {'docs': [{None: None}]}}, because ? is interpreted as a complex mapping key
-> a solution is to quote the ? to get a "?" string instead

[Feature Request] Default config file name

Searching for a file named procmux-config.yaml in the current directory instead of requiring the --config option every time that you run the program would be very convenient.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.