deleted: AUTOCOMPLETE.md
modified: README.md modified: install.sh
This commit is contained in:
240
AUTOCOMPLETE.md
240
AUTOCOMPLETE.md
@ -1,240 +0,0 @@
|
|||||||
# Autocomplete Feature
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
QLPyCon includes intelligent autocomplete for console variables (cvars) and commands with fuzzy matching support.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- **Real-time Suggestions**: Fuzzy matches appear below the input line as you type
|
|
||||||
- **Tab Cycling**: Press Tab to cycle through suggestions
|
|
||||||
- **Smart Argument Highlighting**: Current argument position highlighted in reverse video
|
|
||||||
- **Argument Value Suggestions**: Intelligent suggestions for command arguments (bot names, maps, gametypes, etc.)
|
|
||||||
- **Command Signatures**: Automatic display when typing commands with arguments
|
|
||||||
- **Fuzzy Matching**: Finds matches even with partial or misspelled input
|
|
||||||
- **Smart Scoring**: Best matches appear first (exact > prefix > substring > fuzzy)
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Type a partial command (2+ characters) and fuzzy matches appear below the prompt:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ sv_m
|
|
||||||
sv_maxclients sv_minrate sv_maxrate sv_timeout sv_floodprotect
|
|
||||||
```
|
|
||||||
|
|
||||||
Press **Tab** to cycle through the suggestions:
|
|
||||||
```
|
|
||||||
$ sv_m [Tab] → sv_maxclients
|
|
||||||
$ sv_maxclients [Tab] → sv_minrate
|
|
||||||
$ sv_minrate [Tab] → sv_maxrate
|
|
||||||
$ sv_maxrate [Tab] → sv_timeout
|
|
||||||
$ sv_timeout [Tab] → sv_floodprotect
|
|
||||||
$ sv_floodprotect [Tab] → sv_maxclients (cycles back)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Command signatures with argument highlighting:**
|
|
||||||
|
|
||||||
When you type a command that has arguments, the signature appears automatically with the **current argument highlighted**:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ addbot
|
|
||||||
[<botname>] [skill 1-5] [team] [msec delay] [altname]
|
|
||||||
↑ highlighted (currently typing this)
|
|
||||||
|
|
||||||
$ addbot sarge
|
|
||||||
<botname> [[skill 1-5]] [team] [msec delay] [altname]
|
|
||||||
↑ highlighted (now typing skill level)
|
|
||||||
|
|
||||||
$ addbot sarge 5
|
|
||||||
<botname> [skill 1-5] [[team]] [msec delay] [altname]
|
|
||||||
↑ highlighted (now typing team)
|
|
||||||
|
|
||||||
$ kick
|
|
||||||
[<player>]
|
|
||||||
↑ highlighted
|
|
||||||
|
|
||||||
$ g_gametype
|
|
||||||
[<0=FFA 1=Duel 2=TDM 3=CA 4=CTF...>]
|
|
||||||
↑ highlighted
|
|
||||||
```
|
|
||||||
|
|
||||||
The highlighted argument (shown with `[[ ]]` above, displayed in reverse video) shows you **exactly what to type next**.
|
|
||||||
|
|
||||||
Matches update in real-time as you type or delete characters.
|
|
||||||
|
|
||||||
**Argument value suggestions:**
|
|
||||||
|
|
||||||
After typing a command with a space, the system suggests valid values for each argument with fuzzy matching:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ addbot
|
|
||||||
Anarki Angel Biker Bitterman Bones
|
|
||||||
↑ Shows bot names
|
|
||||||
|
|
||||||
$ addbot sar
|
|
||||||
Sarge
|
|
||||||
↑ Fuzzy matches 'sar' → 'Sarge'
|
|
||||||
|
|
||||||
$ addbot Sarge
|
|
||||||
1 2 3 4 5
|
|
||||||
↑ Shows skill levels (1-5)
|
|
||||||
|
|
||||||
$ addbot Sarge 4
|
|
||||||
red blue free spectator any
|
|
||||||
↑ Shows team values
|
|
||||||
|
|
||||||
$ map
|
|
||||||
aerowalk almostlost arenagate asylum battleforged
|
|
||||||
↑ Shows map names
|
|
||||||
|
|
||||||
$ map blood
|
|
||||||
bloodrun
|
|
||||||
↑ Fuzzy matches 'blood' → 'bloodrun'
|
|
||||||
|
|
||||||
$ g_gametype
|
|
||||||
0 1 2 3 4 FFA Duel TDM CA CTF
|
|
||||||
↑ Shows numeric and string gametype values
|
|
||||||
|
|
||||||
$ callvote
|
|
||||||
map kick shuffle teamsize
|
|
||||||
↑ Shows vote types
|
|
||||||
```
|
|
||||||
|
|
||||||
The system knows valid values for **25+ commands** including:
|
|
||||||
- **32 bot names**: Sarge, Ranger, Visor, Xaero, Anarki, etc.
|
|
||||||
- **40+ maps**: bloodrun, campgrounds, toxicity, aerowalk, etc.
|
|
||||||
- **12 game types**: FFA, Duel, TDM, CA, CTF, etc. (numeric and string forms)
|
|
||||||
- **Vote types**: map, kick, shuffle, teamsize, g_gametype, etc.
|
|
||||||
- **Team values**: red, blue, free, spectator, any
|
|
||||||
- **Skill levels**: 1-5 for bots
|
|
||||||
- **Boolean values**: 0, 1, true, false, enabled, disabled
|
|
||||||
- **Common settings**: timelimits, fraglimits, sv_fps values, etc.
|
|
||||||
|
|
||||||
Arguments with freetext (like player names or custom messages) fall back to showing the signature with highlighting.
|
|
||||||
|
|
||||||
## Supported Commands
|
|
||||||
|
|
||||||
**76 cvars and commands included:**
|
|
||||||
|
|
||||||
### Commands with Signatures
|
|
||||||
|
|
||||||
The following commands show usage help when selected:
|
|
||||||
|
|
||||||
**Bot commands:**
|
|
||||||
- `addbot` - <botname> [skill 1-5] [team] [msec delay] [altname]
|
|
||||||
- `removebot` - <botname>
|
|
||||||
|
|
||||||
**Player management:**
|
|
||||||
- `kick` - <player>
|
|
||||||
- `kickban` - <player>
|
|
||||||
- `ban` - <player>
|
|
||||||
- `tempban` - <player> <seconds>
|
|
||||||
- `tell` - <player> <message>
|
|
||||||
|
|
||||||
**Game settings:**
|
|
||||||
- `g_gametype` - <0=FFA 1=Duel 2=TDM 3=CA 4=CTF...>
|
|
||||||
- `timelimit` - <minutes>
|
|
||||||
- `fraglimit` - <frags>
|
|
||||||
- `capturelimit` - <captures>
|
|
||||||
|
|
||||||
**Map & voting:**
|
|
||||||
- `map` - <mapname>
|
|
||||||
- `callvote` - <vote type> [args...]
|
|
||||||
- `say` - <message>
|
|
||||||
|
|
||||||
### Additional Cvars
|
|
||||||
|
|
||||||
**Server Configuration:**
|
|
||||||
- sv_hostname, sv_maxclients, sv_fps, sv_pure, etc.
|
|
||||||
|
|
||||||
**Network & ZMQ:**
|
|
||||||
- net_port, zmq_rcon_enable, zmq_stats_enable, etc.
|
|
||||||
|
|
||||||
**QLX (minqlx):**
|
|
||||||
- qlx_serverBrandName, qlx_owner, qlx_redditAuth
|
|
||||||
|
|
||||||
## Technical Details
|
|
||||||
|
|
||||||
### Fuzzy Matching Algorithm
|
|
||||||
|
|
||||||
Scoring system (higher = better match):
|
|
||||||
- **1000**: Exact match
|
|
||||||
- **500+**: Prefix match (prioritizes shorter results)
|
|
||||||
- **100-**: Substring match (earlier = better)
|
|
||||||
- **50**: Contains all characters in order
|
|
||||||
|
|
||||||
### Examples:
|
|
||||||
|
|
||||||
```python
|
|
||||||
autocomplete('sv_')
|
|
||||||
→ ['sv_fps', 'sv_pure', 'sv_maxrate', 'sv_minrate', 'sv_timeout']
|
|
||||||
|
|
||||||
autocomplete('time')
|
|
||||||
→ ['timelimit', 'sv_timeout']
|
|
||||||
|
|
||||||
autocomplete('stat')
|
|
||||||
→ ['status', 'zmq_stats_enable', 'zmq_stats_ip', 'zmq_stats_password', 'zmq_stats_port']
|
|
||||||
```
|
|
||||||
|
|
||||||
## Customization
|
|
||||||
|
|
||||||
### Add Your Own Cvars
|
|
||||||
|
|
||||||
Edit `cvars.py` and add to the appropriate list:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Custom cvars
|
|
||||||
CUSTOM_CVARS = [
|
|
||||||
'my_custom_cvar',
|
|
||||||
'another_cvar',
|
|
||||||
]
|
|
||||||
|
|
||||||
# Add to ALL_CVARS
|
|
||||||
ALL_CVARS = (
|
|
||||||
SERVER_CVARS +
|
|
||||||
GAME_CVARS +
|
|
||||||
# ...
|
|
||||||
CUSTOM_CVARS
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Adjust Behavior
|
|
||||||
|
|
||||||
In `ui.py`, modify:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Minimum characters before showing suggestions
|
|
||||||
if len(current_word) >= 2: # Change to 1 or 3
|
|
||||||
|
|
||||||
# Maximum suggestions displayed
|
|
||||||
suggestions = autocomplete(current_word, max_results=5) # Change limit
|
|
||||||
```
|
|
||||||
|
|
||||||
## Keyboard Shortcuts
|
|
||||||
|
|
||||||
| Key | Action |
|
|
||||||
|-----|--------|
|
|
||||||
| **Tab** | Cycle through autocomplete suggestions |
|
|
||||||
| **↑** | Previous command in history |
|
|
||||||
| **↓** | Next command in history |
|
|
||||||
| **←/→** | Move cursor |
|
|
||||||
| **Backspace** | Delete (updates suggestions) |
|
|
||||||
| **Enter** | Send command |
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
- Autocomplete starts after typing 2+ characters
|
|
||||||
- Suggestions appear on the line below the prompt
|
|
||||||
- Up to 5 matches shown at once (best matches first)
|
|
||||||
- Suggestions update in real-time as you type
|
|
||||||
- History navigation (↑/↓) works normally
|
|
||||||
|
|
||||||
## Testing Autocomplete
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Run cvars module directly to test matching
|
|
||||||
python3 cvars.py
|
|
||||||
|
|
||||||
# Output shows test queries and results
|
|
||||||
```
|
|
||||||
246
README.md
246
README.md
@ -57,8 +57,6 @@ qlpycon --list # list configured servers
|
|||||||
- Argument suggestions for 25+ commands (bot names, maps, gametypes)
|
- Argument suggestions for 25+ commands (bot names, maps, gametypes)
|
||||||
- Command history (↑/↓)
|
- Command history (↑/↓)
|
||||||
|
|
||||||
See [AUTOCOMPLETE.md](AUTOCOMPLETE.md) for input details.
|
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -78,3 +76,247 @@ lib/
|
|||||||
## License
|
## License
|
||||||
|
|
||||||
WTFPL
|
WTFPL
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Autocomplete Feature
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
QLPyCon includes intelligent autocomplete for console variables (cvars) and commands with fuzzy matching support.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Real-time Suggestions**: Fuzzy matches appear below the input line as you type
|
||||||
|
- **Tab Cycling**: Press Tab to cycle through suggestions
|
||||||
|
- **Smart Argument Highlighting**: Current argument position highlighted in reverse video
|
||||||
|
- **Argument Value Suggestions**: Intelligent suggestions for command arguments (bot names, maps, gametypes, etc.)
|
||||||
|
- **Command Signatures**: Automatic display when typing commands with arguments
|
||||||
|
- **Fuzzy Matching**: Finds matches even with partial or misspelled input
|
||||||
|
- **Smart Scoring**: Best matches appear first (exact > prefix > substring > fuzzy)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Type a partial command (2+ characters) and fuzzy matches appear below the prompt:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sv_m
|
||||||
|
sv_maxclients sv_minrate sv_maxrate sv_timeout sv_floodprotect
|
||||||
|
```
|
||||||
|
|
||||||
|
Press **Tab** to cycle through the suggestions:
|
||||||
|
```
|
||||||
|
$ sv_m [Tab] → sv_maxclients
|
||||||
|
$ sv_maxclients [Tab] → sv_minrate
|
||||||
|
$ sv_minrate [Tab] → sv_maxrate
|
||||||
|
$ sv_maxrate [Tab] → sv_timeout
|
||||||
|
$ sv_timeout [Tab] → sv_floodprotect
|
||||||
|
$ sv_floodprotect [Tab] → sv_maxclients (cycles back)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Command signatures with argument highlighting:**
|
||||||
|
|
||||||
|
When you type a command that has arguments, the signature appears automatically with the **current argument highlighted**:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ addbot
|
||||||
|
[<botname>] [skill 1-5] [team] [msec delay] [altname]
|
||||||
|
↑ highlighted (currently typing this)
|
||||||
|
|
||||||
|
$ addbot sarge
|
||||||
|
<botname> [[skill 1-5]] [team] [msec delay] [altname]
|
||||||
|
↑ highlighted (now typing skill level)
|
||||||
|
|
||||||
|
$ addbot sarge 5
|
||||||
|
<botname> [skill 1-5] [[team]] [msec delay] [altname]
|
||||||
|
↑ highlighted (now typing team)
|
||||||
|
|
||||||
|
$ kick
|
||||||
|
[<player>]
|
||||||
|
↑ highlighted
|
||||||
|
|
||||||
|
$ g_gametype
|
||||||
|
[<0=FFA 1=Duel 2=TDM 3=CA 4=CTF...>]
|
||||||
|
↑ highlighted
|
||||||
|
```
|
||||||
|
|
||||||
|
The highlighted argument (shown with `[[ ]]` above, displayed in reverse video) shows you **exactly what to type next**.
|
||||||
|
|
||||||
|
Matches update in real-time as you type or delete characters.
|
||||||
|
|
||||||
|
**Argument value suggestions:**
|
||||||
|
|
||||||
|
After typing a command with a space, the system suggests valid values for each argument with fuzzy matching:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ addbot
|
||||||
|
Anarki Angel Biker Bitterman Bones
|
||||||
|
↑ Shows bot names
|
||||||
|
|
||||||
|
$ addbot sar
|
||||||
|
Sarge
|
||||||
|
↑ Fuzzy matches 'sar' → 'Sarge'
|
||||||
|
|
||||||
|
$ addbot Sarge
|
||||||
|
1 2 3 4 5
|
||||||
|
↑ Shows skill levels (1-5)
|
||||||
|
|
||||||
|
$ addbot Sarge 4
|
||||||
|
red blue free spectator any
|
||||||
|
↑ Shows team values
|
||||||
|
|
||||||
|
$ map
|
||||||
|
aerowalk almostlost arenagate asylum battleforged
|
||||||
|
↑ Shows map names
|
||||||
|
|
||||||
|
$ map blood
|
||||||
|
bloodrun
|
||||||
|
↑ Fuzzy matches 'blood' → 'bloodrun'
|
||||||
|
|
||||||
|
$ g_gametype
|
||||||
|
0 1 2 3 4 FFA Duel TDM CA CTF
|
||||||
|
↑ Shows numeric and string gametype values
|
||||||
|
|
||||||
|
$ callvote
|
||||||
|
map kick shuffle teamsize
|
||||||
|
↑ Shows vote types
|
||||||
|
```
|
||||||
|
|
||||||
|
The system knows valid values for **25+ commands** including:
|
||||||
|
- **32 bot names**: Sarge, Ranger, Visor, Xaero, Anarki, etc.
|
||||||
|
- **40+ maps**: bloodrun, campgrounds, toxicity, aerowalk, etc.
|
||||||
|
- **12 game types**: FFA, Duel, TDM, CA, CTF, etc. (numeric and string forms)
|
||||||
|
- **Vote types**: map, kick, shuffle, teamsize, g_gametype, etc.
|
||||||
|
- **Team values**: red, blue, free, spectator, any
|
||||||
|
- **Skill levels**: 1-5 for bots
|
||||||
|
- **Boolean values**: 0, 1, true, false, enabled, disabled
|
||||||
|
- **Common settings**: timelimits, fraglimits, sv_fps values, etc.
|
||||||
|
|
||||||
|
Arguments with freetext (like player names or custom messages) fall back to showing the signature with highlighting.
|
||||||
|
|
||||||
|
## Supported Commands
|
||||||
|
|
||||||
|
**76 cvars and commands included:**
|
||||||
|
|
||||||
|
### Commands with Signatures
|
||||||
|
|
||||||
|
The following commands show usage help when selected:
|
||||||
|
|
||||||
|
**Bot commands:**
|
||||||
|
- `addbot` - <botname> [skill 1-5] [team] [msec delay] [altname]
|
||||||
|
- `removebot` - <botname>
|
||||||
|
|
||||||
|
**Player management:**
|
||||||
|
- `kick` - <player>
|
||||||
|
- `kickban` - <player>
|
||||||
|
- `ban` - <player>
|
||||||
|
- `tempban` - <player> <seconds>
|
||||||
|
- `tell` - <player> <message>
|
||||||
|
|
||||||
|
**Game settings:**
|
||||||
|
- `g_gametype` - <0=FFA 1=Duel 2=TDM 3=CA 4=CTF...>
|
||||||
|
- `timelimit` - <minutes>
|
||||||
|
- `fraglimit` - <frags>
|
||||||
|
- `capturelimit` - <captures>
|
||||||
|
|
||||||
|
**Map & voting:**
|
||||||
|
- `map` - <mapname>
|
||||||
|
- `callvote` - <vote type> [args...]
|
||||||
|
- `say` - <message>
|
||||||
|
|
||||||
|
### Additional Cvars
|
||||||
|
|
||||||
|
**Server Configuration:**
|
||||||
|
- sv_hostname, sv_maxclients, sv_fps, sv_pure, etc.
|
||||||
|
|
||||||
|
**Network & ZMQ:**
|
||||||
|
- net_port, zmq_rcon_enable, zmq_stats_enable, etc.
|
||||||
|
|
||||||
|
**QLX (minqlx):**
|
||||||
|
- qlx_serverBrandName, qlx_owner, qlx_redditAuth
|
||||||
|
|
||||||
|
## Technical Details
|
||||||
|
|
||||||
|
### Fuzzy Matching Algorithm
|
||||||
|
|
||||||
|
Scoring system (higher = better match):
|
||||||
|
- **1000**: Exact match
|
||||||
|
- **500+**: Prefix match (prioritizes shorter results)
|
||||||
|
- **100-**: Substring match (earlier = better)
|
||||||
|
- **50**: Contains all characters in order
|
||||||
|
|
||||||
|
### Examples:
|
||||||
|
|
||||||
|
```python
|
||||||
|
autocomplete('sv_')
|
||||||
|
→ ['sv_fps', 'sv_pure', 'sv_maxrate', 'sv_minrate', 'sv_timeout']
|
||||||
|
|
||||||
|
autocomplete('time')
|
||||||
|
→ ['timelimit', 'sv_timeout']
|
||||||
|
|
||||||
|
autocomplete('stat')
|
||||||
|
→ ['status', 'zmq_stats_enable', 'zmq_stats_ip', 'zmq_stats_password', 'zmq_stats_port']
|
||||||
|
```
|
||||||
|
|
||||||
|
## Customization
|
||||||
|
|
||||||
|
### Add Your Own Cvars
|
||||||
|
|
||||||
|
Edit `cvars.py` and add to the appropriate list:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Custom cvars
|
||||||
|
CUSTOM_CVARS = [
|
||||||
|
'my_custom_cvar',
|
||||||
|
'another_cvar',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Add to ALL_CVARS
|
||||||
|
ALL_CVARS = (
|
||||||
|
SERVER_CVARS +
|
||||||
|
GAME_CVARS +
|
||||||
|
# ...
|
||||||
|
CUSTOM_CVARS
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adjust Behavior
|
||||||
|
|
||||||
|
In `ui.py`, modify:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Minimum characters before showing suggestions
|
||||||
|
if len(current_word) >= 2: # Change to 1 or 3
|
||||||
|
|
||||||
|
# Maximum suggestions displayed
|
||||||
|
suggestions = autocomplete(current_word, max_results=5) # Change limit
|
||||||
|
```
|
||||||
|
|
||||||
|
## Keyboard Shortcuts
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|-----|--------|
|
||||||
|
| **Tab** | Cycle through autocomplete suggestions |
|
||||||
|
| **↑** | Previous command in history |
|
||||||
|
| **↓** | Next command in history |
|
||||||
|
| **←/→** | Move cursor |
|
||||||
|
| **Backspace** | Delete (updates suggestions) |
|
||||||
|
| **Enter** | Send command |
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Autocomplete starts after typing 2+ characters
|
||||||
|
- Suggestions appear on the line below the prompt
|
||||||
|
- Up to 5 matches shown at once (best matches first)
|
||||||
|
- Suggestions update in real-time as you type
|
||||||
|
- History navigation (↑/↓) works normally
|
||||||
|
|
||||||
|
## Testing Autocomplete
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run cvars module directly to test matching
|
||||||
|
python3 cvars.py
|
||||||
|
|
||||||
|
# Output shows test queries and results
|
||||||
|
```
|
||||||
|
|||||||
@ -2,8 +2,15 @@
|
|||||||
#
|
#
|
||||||
# qlpycon installer
|
# qlpycon installer
|
||||||
# Usage:
|
# Usage:
|
||||||
|
# pipe2bash:
|
||||||
# curl -sSL https://6bit.ch/qlpycon/install.sh | bash
|
# curl -sSL https://6bit.ch/qlpycon/install.sh | bash
|
||||||
#
|
#
|
||||||
|
# local:
|
||||||
|
# mkdir qlpycon
|
||||||
|
# cd qlpycon
|
||||||
|
# chmod u+x install.sh
|
||||||
|
# ./install.sh
|
||||||
|
#
|
||||||
# or run directly from cloned repo:
|
# or run directly from cloned repo:
|
||||||
# git clone https://git.6bit.ch/xbl/qlpycon.git
|
# git clone https://git.6bit.ch/xbl/qlpycon.git
|
||||||
# cd qlpycon
|
# cd qlpycon
|
||||||
@ -111,6 +118,7 @@ write_launcher() {
|
|||||||
|
|
||||||
mkdir -p "$BIN_DIR"
|
mkdir -p "$BIN_DIR"
|
||||||
|
|
||||||
|
echo "BIN_PATH is: $BIN_PATH"
|
||||||
cat > "$BIN_PATH" << EOF
|
cat > "$BIN_PATH" << EOF
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# qlpycon launcher — generated by install.sh
|
# qlpycon launcher — generated by install.sh
|
||||||
|
|||||||
Reference in New Issue
Block a user