Merge branch 'main' into ollama

This commit is contained in:
Chris Titus 2024-09-16 16:48:28 -05:00 committed by GitHub
commit 4e3db9e758
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 427 additions and 106 deletions

4
.github/mkdocs.yml vendored
View File

@ -5,7 +5,9 @@ docs_dir: '../docs'
nav:
- Introduction: 'index.md'
- User Guide: 'userguide.md'
- Contributing Guide: 'contribute.md'
- Contributing:
- Contributing Guide: 'contribute.md'
- Roadmap: 'roadmap.md'
- Documentation:
- Known Issues: 'KnownIssues.md'
- FAQ: 'faq.md'

View File

@ -1,5 +1,3 @@
name-template: '$RESOLVED_VERSION'
tag-template: '$RESOLVED_VERSION'
tag-prefix: ""
categories:
- title: '🚀 Features'
@ -21,10 +19,6 @@ template: |
$CHANGES
## Contributors
$CONTRIBUTORS
change-title-escapes: '\<*_&"'''
autolabeler:
- label: 'documentation'
@ -57,4 +51,6 @@ replacers:
- search: /`/g
replace: ''
exclude-labels:
- 'skip-changelog'
- 'skip-changelog'
filter-by-commitish: true

View File

@ -1,25 +0,0 @@
name: Remove Cargo.lock changes
on:
pull_request:
types: [opened, synchronize]
paths:
- 'Cargo.lock'
jobs:
remove-cargo-lock:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Remove Cargo.lock changes
run: |
git config user.name github-actions
git config user.email github-actions@github.com
git checkout ${{ github.head_ref }}
git reset origin/${{ github.base_ref }} -- Cargo.lock
git commit -m "Remove changes to Cargo.lock" || echo "No changes to commit"
git push origin ${{ github.head_ref }} --force

View File

@ -3,10 +3,11 @@ name: GitHub Pages Deploy
on:
push:
paths:
- 'mkdocs.yml'
- '.github/mkdocs.yml'
- '.github/requirements.txt'
- 'docs/**'
- 'overrides/**'
- 'CONTRIBUTING.md'
- '.github/CONTRIBUTING.md'
workflow_dispatch:
jobs:
@ -29,4 +30,6 @@ jobs:
run: pip install -r .github/requirements.txt
- name: Build & Deploy using mkdocs
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: mkdocs gh-deploy --force -f .github/mkdocs.yml

View File

@ -3,6 +3,7 @@ name: LinUtil Release
on:
push:
branches: ["main"]
workflow_dispatch:
permissions:
contents: write
@ -59,3 +60,39 @@ jobs:
file_pattern: "build/linutil"
add_options: '--force'
if: success()
- name: Extract Version
id: extract_version
run: |
version=$(date +"%Y.%m.%d")
echo "version=$version" >> $GITHUB_ENV
shell: bash
- name: Generate Release Notes
id: generate_notes
uses: release-drafter/release-drafter@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
config-name: release-drafter.yml
version: ${{ env.version }}
- name: Create and Upload Release
id: create_release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ env.version }}
name: Pre-Release ${{ env.version }}
body: |
${{ steps.generate_notes.outputs.body }}
![GitHub Downloads (specific asset, specific tag)](https://img.shields.io/github/downloads/ChrisTitusTech/linutil/${{ env.version }}/linutil)
append_body: false
files: |
./build/linutil
./start.sh
./startdev.sh
prerelease: true
env:
version: ${{ env.version }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

50
.github/workflows/pr-labels.yaml vendored Normal file
View File

@ -0,0 +1,50 @@
name: Manage labels based on PR body
on:
pull_request:
types: [opened, edited, reopened, synchronize]
jobs:
manage-labels:
runs-on: ubuntu-latest
steps:
- name: Analyze PR Body and manage labels
run: |
body="${{ github.event.pull_request.body }}"
labels_to_add=()
labels_to_remove=()
declare -A label_checks=(
["New feature"]="enhancement"
["Bug fix|Hotfix|Security patch"]="bug"
["Documentation update"]="documentation"
["Refactoring"]="refactor"
["UI/UX improvement"]="UI/UX"
)
for key in "${!label_checks[@]}"; do
if echo "$body" | grep -q "\- \[x\] $key"; then
labels_to_add+=("${label_checks[$key]}")
else
labels_to_remove+=("${label_checks[$key]}")
fi
done
echo "LABELS_TO_ADD=${labels_to_add[*]}" >> $GITHUB_ENV
echo "LABELS_TO_REMOVE=${labels_to_remove[*]}" >> $GITHUB_ENV
- name: Add labels if necessary
if: env.LABELS_TO_ADD != ''
run: |
for label in ${{ env.LABELS_TO_ADD }}; do
curl -s -X POST \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
-d "{\"labels\": [\"$label\"]}" \
https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels
done
- name: Remove labels if necessary
if: env.LABELS_TO_REMOVE != ''
run: |
for label in ${{ env.LABELS_TO_REMOVE }}; do
curl -s -X DELETE \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels/$label
done

View File

@ -1,55 +0,0 @@
name: Pre-Release LinUtil
permissions:
contents: write # Grant write permissions to contents
packages: write # Grant write permissions to packages
on:
workflow_dispatch: # Manual trigger added
workflow_run:
workflows: ["LinUtil Release"]
types:
- completed
jobs:
build-runspace:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Extract Version
id: extract_version
run: |
version=$(date +"%Y.%m.%d")
echo "version=$version" >> $GITHUB_ENV
shell: bash
- name: Generate Release Notes
id: generate_notes
uses: release-drafter/release-drafter@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
config-name: release-drafter.yml
version: ${{ env.version }}
- name: Create and Upload Release
id: create_release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ env.version }}
name: Pre-Release ${{ env.version }}
body: |
${{ steps.generate_notes.outputs.body }}
![GitHub Downloads (specific asset, specific tag)](https://img.shields.io/github/downloads/ChrisTitusTech/linutil/${{ env.version }}/linutil)
append_body: false
files: |
./build/linutil
./start.sh
./startdev.sh
prerelease: true
env:
version: ${{ env.version }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
/build
rust/target
rust/build
/build/linutil

View File

@ -31,7 +31,9 @@ For comprehensive information on how to use Linutil, visit the [Linutil Official
## 🛠 Contributing
We welcome contributions from the community! Before you start, please review our [Contributing Guidelines](CONTRIBUTING.md) to understand how to make the most effective and efficient contributions.
We welcome contributions from the community! Before you start, please review our [Contributing Guidelines](.github/CONTRIBUTING.md) to understand how to make the most effective and efficient contributions.
[Official LinUtil Roadmap](https://christitustech.github.io/linutil/roadmap)
## 🏅 Thanks to All Contributors

Binary file not shown.

View File

@ -15,8 +15,8 @@ setupDWM() {
pacman)
$ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm base-devel libx11 libxinerama libxft imlib2 libxcb
;;
apt)
$ESCALATION_TOOL "$PACKAGER" install -y build-essential libx11-dev libxinerama-dev libxft-dev libimlib2-dev libxcb1-dev libx11-xcb1
apt-get|nala)
$ESCALATION_TOOL "$PACKAGER" install -y build-essential libx11-dev libxinerama-dev libxft-dev libimlib2-dev libx11-xcb-dev libfontconfig1 libx11-6 libxft2 libxinerama1 libxcb-res0-dev
;;
dnf)
$ESCALATION_TOOL "$PACKAGER" groupinstall -y "Development Tools"
@ -178,7 +178,7 @@ setupDisplayManager() {
pacman)
$ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm xorg-xinit xorg-server
;;
apt)
apt-get|nala)
$ESCALATION_TOOL "$PACKAGER" install -y xorg xinit
;;
dnf)
@ -206,7 +206,7 @@ setupDisplayManager() {
pacman)
$ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm "$DM"
;;
apt)
apt-get|nala)
$ESCALATION_TOOL "$PACKAGER" install -y "$DM"
;;
dnf)
@ -292,4 +292,4 @@ makeDWM
install_slstatus
install_nerd_font
clone_config_folders
configure_backgrounds
configure_backgrounds

View File

@ -1,7 +1,7 @@
name = "Gaming"
[[data]]
name = "Diablo II Ressurected"
name = "Diablo II Resurrected"
[[data.entries]]
name = "Loot Filter Install"

View File

@ -0,0 +1,278 @@
#!/bin/sh -e
# Load common script functions
. ../common-script.sh
#external services directory
SCRIPT_DIR="./services"
# Function to show the main menu
show_menu() {
clear
echo "============================"
echo " Service Management Menu"
echo "============================"
echo "1. View all services"
echo "2. View enabled services"
echo "3. View disabled services"
echo "4. Add a new service"
echo "5. Remove a service"
echo "6. Start a service"
echo "7. Stop a service"
echo "8. Enable a service"
echo "9. Disable a service"
echo "10. Create a service from external scripts"
echo "11. Exit"
echo "============================"
}
# Function to view all services
view_all_services() {
echo "Listing all services..."
$ESCALATION_TOOL systemctl list-units --type=service --all --no-legend | awk '{print $1}' | sed 's/\.service//' | more
}
# Function to view enabled services
view_enabled_services() {
echo "Listing enabled services..."
$ESCALATION_TOOL systemctl list-unit-files --type=service --state=enabled --no-legend | awk '{print $1}' | sed 's/\.service//' | more
}
# Function to view disabled services
view_disabled_services() {
echo "Listing disabled services..."
$ESCALATION_TOOL systemctl list-unit-files --type=service --state=disabled --no-legend | awk '{print $1}' | sed 's/\.service//' | more
}
# Function to view started services
view_started_services() {
echo "Listing started services:"
$ESCALATION_TOOL systemctl list-units --type=service --state=running --no-pager | head -n -6 | awk 'NR>1 {print $1}' | more
}
# Function to add a new service
add_service() {
while [ -z "$SERVICE_NAME" ]; do
echo "Enter the name of the new service (e.g., my_service):"
read -r SERVICE_NAME
if $ESCALATION_TOOL systemctl list-units --type=service --all --no-legend | grep -q "$SERVICE_NAME.service"; then
echo "Service already exists!"
SERVICE_NAME=""
fi
done
echo "Enter the description of the service:"
read -r SERVICE_DESCRIPTION
echo "Enter the command to execute the service (e.g., /usr/local/bin/my_service.sh):"
read -r EXEC_START
echo "Enter the user to run the service as (leave empty for default):"
read -r SERVICE_USER
echo "Enter the working directory for the service (leave empty for default):"
read -r WORKING_DIRECTORY
echo "Enter the restart policy (e.g., always, on-failure; leave empty for no restart):"
read -r RESTART_POLICY
# Create the service unit file
SERVICE_FILE="/etc/systemd/system/$SERVICE_NAME.service"
# Create the service file with conditionals for optional fields
{
echo "[Unit]"
echo "Description=$SERVICE_DESCRIPTION"
echo ""
echo "[Service]"
echo "ExecStart=$EXEC_START"
[ -n "$SERVICE_USER" ] && echo "User=$SERVICE_USER"
[ -n "$WORKING_DIRECTORY" ] && echo "WorkingDirectory=$WORKING_DIRECTORY"
[ -n "$RESTART_POLICY" ] && echo "Restart=$RESTART_POLICY"
echo ""
echo "[Install]"
echo "WantedBy=multi-user.target"
} | $ESCALATION_TOOL tee "$SERVICE_FILE" > /dev/null
# Set permissions and reload systemd
$ESCALATION_TOOL chmod 644 "$SERVICE_FILE"
$ESCALATION_TOOL systemctl daemon-reload
echo "Service $SERVICE_NAME has been created and is ready to be started."
# Optionally, enable and start the service
echo "Do you want to start and enable the service now? (y/n)"
read -r START_ENABLE
if [ "$START_ENABLE" = "y" ]; then
$ESCALATION_TOOL systemctl start "$SERVICE_NAME"
$ESCALATION_TOOL systemctl enable "$SERVICE_NAME"
echo "Service $SERVICE_NAME has been started and enabled."
else
echo "Service $SERVICE_NAME has been created but not started."
fi
}
# Function to remove a service
remove_service() {
echo "Enter the name of the service to remove (e.g., my_service):"
read -r SERVICE_NAME
SERVICE_FILE="/etc/systemd/system/$SERVICE_NAME.service"
if [ -f "$SERVICE_FILE" ]; then
echo "Stopping and disabling the service..."
$ESCALATION_TOOL systemctl stop "$SERVICE_NAME"
$ESCALATION_TOOL systemctl disable "$SERVICE_NAME"
echo "Removing the service file..."
$ESCALATION_TOOL rm -f "$SERVICE_FILE"
$ESCALATION_TOOL systemctl daemon-reload
echo "Service $SERVICE_NAME has been removed."
else
echo "Service $SERVICE_NAME does not exist."
fi
}
# Function to start a service
start_service() {
view_disabled_services
echo "Enter the name of the service to start (e.g., my_service):"
read -r SERVICE_NAME
if $ESCALATION_TOOL systemctl start "$SERVICE_NAME"; then
echo "Service $SERVICE_NAME has been started."
else
echo "Failed to start service: $SERVICE_NAME."
fi
}
# Function to stop a service
stop_service() {
view_started_services
echo "Enter the name of the service to stop (e.g., my_service):"
read -r SERVICE_NAME
if $ESCALATION_TOOL systemctl stop "$SERVICE_NAME"; then
echo "Service $SERVICE_NAME has been stopped."
else
echo "Failed to stop service: $SERVICE_NAME."
fi
}
# Function to enable a service
enable_service() {
view_disabled_services
echo "Enter the name of the service to enable (e.g., my_service):"
read -r SERVICE_NAME
if $ESCALATION_TOOL systemctl enable "$SERVICE_NAME"; then
echo "Service $SERVICE_NAME has been enabled."
else
echo "Failed to enable service: $SERVICE_NAME."
fi
}
# Function to enable a service
disable_service() {
view_enabled_services
echo "Enter the name of the service to disable (e.g., my_service):"
read -r SERVICE_NAME
if $ESCALATION_TOOL systemctl disable "$SERVICE_NAME"; then
echo "Service $SERVICE_NAME has been enabled."
else
echo "Failed to enable service: $SERVICE_NAME."
fi
}
# Function to create, start, and enable a service from an external service file
create_service_from_external() {
# List all .service files in the SCRIPT_DIR
echo "============================"
echo "Listing available service files"
echo "============================"
for FILE in "$SCRIPT_DIR"/*.service; do
echo "$(basename "$FILE")"
done
echo "Enter the filename (without the .service extension) of the service to create:"
read -r SERVICE_NAME
SERVICE_FILE="$SCRIPT_DIR/$SERVICE_NAME.service"
if [ ! -f "$SERVICE_FILE" ]; then
echo "Service file $SERVICE_FILE does not exist."
return
fi
echo "Enter the username to run the service as (leave empty for no specific user):"
read -r SERVICE_USER
# Create the systemd service file path
SYSTEMD_SERVICE_FILE="/etc/systemd/system/$SERVICE_NAME.service"
# Add or update the User= line in the service file
if [ -n "$SERVICE_USER" ]; then
# Check if User= exists and append username if needed
if grep -q '^User=' "$SERVICE_FILE"; then
# Update the existing User= line with the new username
sed -i "s/^User=.*/User=$SERVICE_USER/" "$SERVICE_FILE"
else
# Add the User= line if it doesn't exist
sed -i '/^\[Service\]/a User='"$SERVICE_USER" "$SERVICE_FILE"
fi
fi
# Copy the modified service file to /etc/systemd/system/
$ESCALATION_TOOL cp "$SERVICE_FILE" "$SYSTEMD_SERVICE_FILE"
# Set permissions and reload systemd
$ESCALATION_TOOL chmod 644 "$SYSTEMD_SERVICE_FILE"
$ESCALATION_TOOL systemctl daemon-reload
echo "Service $SERVICE_NAME has been created and is ready to be started."
# Optionally, enable and start the service
echo "Do you want to start and enable the service now? (y/n)"
read -r START_ENABLE
if [ "$START_ENABLE" = "y" ]; then
$ESCALATION_TOOL systemctl start "$SERVICE_NAME"
$ESCALATION_TOOL systemctl enable "$SERVICE_NAME"
echo "Service $SERVICE_NAME has been started and enabled."
else
echo "Service $SERVICE_NAME has been created but not started."
fi
}
main() {
while true; do
show_menu
echo "Enter your choice:"
read -r CHOICE
case $CHOICE in
1) view_all_services ;;
2) view_enabled_services ;;
3) view_disabled_services ;;
4) add_service ;;
5) remove_service ;;
6) start_service ;;
7) stop_service ;;
8) enable_service ;;
9) disable_service ;;
10) create_service_from_external ;;
11) echo "Exiting..."; exit 0 ;;
*) echo "Invalid choice. Please try again." ;;
esac
echo "Press [Enter] to continue..."
read -r dummy
done
}
checkEnv
checkEscalationTool
main

View File

@ -0,0 +1,14 @@
/etc/systemd/system/
[Unit]
Description=i3lock on Lid Close
Before=sleep.target
[Service]
User=
Type=forking
Environment=DISPLAY=:0
ExecStart=/usr/bin/i3lock
[Install]
WantedBy=sleep.target

View File

@ -16,6 +16,10 @@ script = "numlock.sh"
name = "Ollama"
script = "ollama.sh"
[[data]]
name = "Service Manager"
script = "service-control.sh"
[[data]]
name = "Monitor Control"

View File

@ -64,9 +64,7 @@ impl Float {
// Returns true if the floating window is finished.
pub fn handle_key_event(&mut self, key: &KeyEvent) -> bool {
match key.code {
KeyCode::Enter | KeyCode::Char('p') | KeyCode::Esc | KeyCode::Char('q')
if self.content.is_finished() =>
{
KeyCode::Enter | KeyCode::Char('p') | KeyCode::Esc if self.content.is_finished() => {
true
}
_ => self.content.handle_key_event(key),

View File

@ -14,7 +14,6 @@ use std::{
use crate::theme::Theme;
use clap::Parser;
use crossterm::{
cursor::RestorePosition,
event::{self, DisableMouseCapture, Event, KeyEventKind},
style::ResetColor,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
@ -38,7 +37,7 @@ struct Args {
override_validation: bool,
}
fn main() -> std::io::Result<()> {
fn main() -> io::Result<()> {
let args = Args::parse();
let mut state = AppState::new(args.theme, args.override_validation);
@ -55,8 +54,8 @@ fn main() -> std::io::Result<()> {
terminal.backend_mut().execute(LeaveAlternateScreen)?;
terminal.backend_mut().execute(DisableMouseCapture)?;
terminal.backend_mut().execute(ResetColor)?;
terminal.backend_mut().execute(RestorePosition)?;
terminal.show_cursor()?;
Ok(())
}

View File

@ -6,7 +6,7 @@ use crate::{
running_command::RunningCommand,
theme::Theme,
};
use crossterm::event::{KeyCode, KeyEvent, KeyEventKind};
use crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
use ego_tree::NodeId;
use linutil_core::{Command, ListNode, Tab};
use ratatui::{
@ -185,6 +185,7 @@ impl AppState {
draw_shortcuts(self, frame, vertical[1]);
}
pub fn handle_key(&mut self, key: &KeyEvent) -> bool {
match &mut self.focus {
Focus::FloatingWindow(command) => {
@ -192,31 +193,43 @@ impl AppState {
self.focus = Focus::List;
}
}
Focus::Search => match self.filter.handle_key(key) {
SearchAction::Exit => self.exit_search(),
SearchAction::Update => self.update_items(),
_ => {}
},
_ if key.code == KeyCode::Char('q') => return false,
_ if key.code == KeyCode::Char('q')
|| key.code == KeyCode::Char('c')
&& key.modifiers.contains(KeyModifiers::CONTROL) =>
{
return false;
}
Focus::TabList => match key.code {
KeyCode::Enter | KeyCode::Char('l') | KeyCode::Right | KeyCode::Tab => {
self.focus = Focus::List
}
KeyCode::Char('j') | KeyCode::Down
if self.current_tab.selected().unwrap() + 1 < self.tabs.len() =>
{
self.current_tab.select_next();
self.refresh_tab();
}
KeyCode::Char('k') | KeyCode::Up => {
self.current_tab.select_previous();
self.refresh_tab();
}
KeyCode::Char('/') => self.enter_search(),
KeyCode::Char('t') => self.theme.next(),
KeyCode::Char('T') => self.theme.prev(),
_ => {}
},
Focus::List if key.kind != KeyEventKind::Release => match key.code {
KeyCode::Char('j') | KeyCode::Down => self.selection.select_next(),
KeyCode::Char('k') | KeyCode::Up => self.selection.select_previous(),
@ -235,10 +248,12 @@ impl AppState {
KeyCode::Char('T') => self.theme.prev(),
_ => {}
},
_ => {}
_ => (),
};
true
}
fn update_items(&mut self) {
self.filter.update_items(
&self.tabs,
@ -246,12 +261,14 @@ impl AppState {
*self.visit_stack.last().unwrap(),
);
}
/// Checks ehther the current tree node is the root node (can we go up the tree or no)
/// Returns `true` if we can't go up the tree (we are at the tree root)
/// else returns `false`
pub fn at_root(&self) -> bool {
self.visit_stack.len() == 1
}
fn enter_parent_directory(&mut self) {
self.visit_stack.pop();
self.selection.select(Some(0));