mirror of
https://github.com/onyx-and-iris/q3rcon-tui.git
synced 2026-04-09 05:33:31 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 225685de63 | |||
| 5178b0066b | |||
| 68926fa67b | |||
| d273ca57ca | |||
| ce660fb6c8 | |||
| 514dda463a |
2
.github/workflows/publish.yml
vendored
2
.github/workflows/publish.yml
vendored
@@ -30,7 +30,7 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install "virtualenv<21" hatch
|
pip install hatch
|
||||||
|
|
||||||
- name: Build package
|
- name: Build package
|
||||||
run: hatch build
|
run: hatch build
|
||||||
|
|||||||
7
.pre-commit-config.yaml
Normal file
7
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v2.3.0
|
||||||
|
hooks:
|
||||||
|
- id: check-yaml
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: trailing-whitespace
|
||||||
@@ -66,6 +66,12 @@ Q3RCON_TUI_RAW=false
|
|||||||
Q3RCON_TUI_APPEND=false
|
Q3RCON_TUI_APPEND=false
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Use
|
||||||
|
|
||||||
|
Type in your Rcon command and press ENTER.
|
||||||
|
|
||||||
|
Press `Ctrl+q` to exit from the application.
|
||||||
|
|
||||||
## Special Thanks
|
## Special Thanks
|
||||||
|
|
||||||
- [lapetus-11](https://github.com/Iapetus-11) for writing the [aio-q3-rcon](https://github.com/Iapetus-11/aio-q3-rcon) package.
|
- [lapetus-11](https://github.com/Iapetus-11) for writing the [aio-q3-rcon](https://github.com/Iapetus-11/aio-q3-rcon) package.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# SPDX-FileCopyrightText: 2026-present onyx-and-iris <code@onyxandiris.online>
|
# SPDX-FileCopyrightText: 2026-present onyx-and-iris <code@onyxandiris.online>
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
__version__ = '0.7.1'
|
__version__ = '0.8.0'
|
||||||
|
|||||||
23
src/q3rcon_tui/history.py
Normal file
23
src/q3rcon_tui/history.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
from collections import UserList
|
||||||
|
|
||||||
|
|
||||||
|
class CommandHistory(UserList):
|
||||||
|
"""A simple list to store command history."""
|
||||||
|
|
||||||
|
def add(self, command: str):
|
||||||
|
"""Add a command to the history if it's not empty and not a duplicate of the last."""
|
||||||
|
command = command.strip()
|
||||||
|
if command and (not self.data or command != self.data[-1]):
|
||||||
|
self.data.append(command)
|
||||||
|
|
||||||
|
def get_previous(self, index: int) -> str:
|
||||||
|
"""Get the previous command based on the current index."""
|
||||||
|
if 0 <= index < len(self.data):
|
||||||
|
return self.data[index]
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def get_next(self, index: int) -> str:
|
||||||
|
"""Get the next command based on the current index."""
|
||||||
|
if 0 <= index < len(self.data):
|
||||||
|
return self.data[index]
|
||||||
|
return ''
|
||||||
@@ -4,17 +4,29 @@ from textual.containers import Grid
|
|||||||
from textual.widgets import Button, Input, RichLog
|
from textual.widgets import Button, Input, RichLog
|
||||||
|
|
||||||
from .configscreen import ConfigScreen
|
from .configscreen import ConfigScreen
|
||||||
|
from .history import CommandHistory
|
||||||
from .settings import Settings
|
from .settings import Settings
|
||||||
from .writable import Writable
|
from .writable import Writable
|
||||||
|
|
||||||
|
|
||||||
class Q3RconTUI(App):
|
class Q3RconTUI(App):
|
||||||
CSS_PATH = 'q3rcon_tui.tcss'
|
CSS_PATH = 'q3rcon_tui.tcss'
|
||||||
|
CMD_CONFIG = {
|
||||||
|
'status': (2, 0.25, False),
|
||||||
|
'fast_restart': (3, 1, True),
|
||||||
|
'map_restart': (3, 1, True),
|
||||||
|
'map': (3, 1, True),
|
||||||
|
'map_rotate': (3, 1, True),
|
||||||
|
}
|
||||||
|
DEFAULT_TIMEOUT = 2
|
||||||
|
DEFAULT_FRAGMENT_READ_TIMEOUT = 0.25
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._settings = Settings()
|
self._settings = Settings()
|
||||||
self.writable = Writable(self)
|
self.writable = Writable(self)
|
||||||
|
self._command_history = CommandHistory()
|
||||||
|
self._history_index = None
|
||||||
|
|
||||||
def compose(self) -> ComposeResult:
|
def compose(self) -> ComposeResult:
|
||||||
yield Grid(
|
yield Grid(
|
||||||
@@ -31,9 +43,33 @@ class Q3RconTUI(App):
|
|||||||
if self.screen and isinstance(self.screen, ConfigScreen):
|
if self.screen and isinstance(self.screen, ConfigScreen):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
command_input = self.query_one('#command', Input)
|
||||||
match event.key:
|
match event.key:
|
||||||
case 'enter' if self.query_one('#command', Input).has_focus:
|
case 'enter' if command_input.has_focus:
|
||||||
|
value = command_input.value.strip()
|
||||||
|
if value:
|
||||||
|
self._command_history.add(value)
|
||||||
|
self._history_index = None
|
||||||
self.query_one('#send', Button).press()
|
self.query_one('#send', Button).press()
|
||||||
|
case 'up' if command_input.has_focus:
|
||||||
|
if self._command_history:
|
||||||
|
if self._history_index is None:
|
||||||
|
self._history_index = len(self._command_history) - 1
|
||||||
|
elif self._history_index > 0:
|
||||||
|
self._history_index -= 1
|
||||||
|
command_input.value = self._command_history.get_previous(
|
||||||
|
self._history_index
|
||||||
|
)
|
||||||
|
case 'down' if command_input.has_focus:
|
||||||
|
if self._command_history and self._history_index is not None:
|
||||||
|
if self._history_index < len(self._command_history) - 1:
|
||||||
|
self._history_index += 1
|
||||||
|
command_input.value = self._command_history.get_next(
|
||||||
|
self._history_index
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self._history_index = None
|
||||||
|
command_input.value = ''
|
||||||
case 'f2':
|
case 'f2':
|
||||||
self.query_one('#config', Button).press()
|
self.query_one('#config', Button).press()
|
||||||
|
|
||||||
@@ -65,11 +101,20 @@ class Q3RconTUI(App):
|
|||||||
self.app.bell()
|
self.app.bell()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
timeout, fragment_read_timeout, interpret = Q3RconTUI.CMD_CONFIG.get(
|
||||||
|
cmd.split()[0].lower(),
|
||||||
|
(Q3RconTUI.DEFAULT_TIMEOUT, Q3RconTUI.DEFAULT_FRAGMENT_READ_TIMEOUT, False),
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
async with Client(
|
async with Client(
|
||||||
self._settings.host, self._settings.port, self._settings.password
|
self._settings.host,
|
||||||
|
self._settings.port,
|
||||||
|
self._settings.password,
|
||||||
|
timeout=timeout,
|
||||||
|
fragment_read_timeout=fragment_read_timeout,
|
||||||
) as client:
|
) as client:
|
||||||
response = await client.send_command(cmd)
|
response = await client.send_command(cmd, interpret=interpret)
|
||||||
self.query_one('#response', RichLog).write(
|
self.query_one('#response', RichLog).write(
|
||||||
self.writable.parse(cmd, response)
|
self.writable.parse(cmd, response)
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user