mirror of
https://github.com/ChrisTitusTech/linutil.git
synced 2024-11-05 21:28:48 +00:00
Merge branch 'main' into root
This commit is contained in:
commit
7f3bfe79af
18
.github/workflows/github-pages.yml
vendored
18
.github/workflows/github-pages.yml
vendored
|
@ -13,6 +13,10 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
build-and-deploy:
|
build-and-deploy:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
environment: linutil_env
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Repository
|
- name: Checkout Repository
|
||||||
|
@ -24,11 +28,17 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
echo -e "<!-- THIS FILE IS GENERATED AUTOMATICALLY. EDIT .github/CONTRIBUTING.md -->\n\n$(cat .github/CONTRIBUTING.md)" > 'docs/contributing.md'
|
echo -e "<!-- THIS FILE IS GENERATED AUTOMATICALLY. EDIT .github/CONTRIBUTING.md -->\n\n$(cat .github/CONTRIBUTING.md)" > 'docs/contributing.md'
|
||||||
|
|
||||||
- uses: stefanzweifel/git-auto-commit-action@v5
|
- name: Create Pull Request
|
||||||
|
uses: peter-evans/create-pull-request@v6
|
||||||
with:
|
with:
|
||||||
commit_message: Commit Contributing Guidelines
|
commit-message: Update Contributing Guidelines
|
||||||
file_pattern: "docs/contributing.md"
|
title: 'docs: Update Contributing Guidelines'
|
||||||
add_options: '--force'
|
body: 'Automated update of Contributing Guidelines from .github/CONTRIBUTING.md'
|
||||||
|
branch: update-contributing-guidelines
|
||||||
|
delete-branch: true
|
||||||
|
base: main
|
||||||
|
labels: documentation
|
||||||
|
token: ${{ secrets.PAT_TOKEN }}
|
||||||
if: success()
|
if: success()
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
|
|
8
.github/workflows/linutil.yml
vendored
8
.github/workflows/linutil.yml
vendored
|
@ -78,11 +78,3 @@ jobs:
|
||||||
env:
|
env:
|
||||||
version: ${{ env.version }}
|
version: ${{ env.version }}
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Upload build artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: linutil-artifact
|
|
||||||
path: build/x86_64-unknown-linux-musl/release/linutil
|
|
||||||
compression-level: 0
|
|
||||||
overwrite: true
|
|
67
.github/workflows/preview.yml
vendored
67
.github/workflows/preview.yml
vendored
|
@ -3,8 +3,8 @@ name: LinUtil Preview
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
run_id:
|
tag_name:
|
||||||
description: 'Run ID of LinUtil Release'
|
description: 'Tag name'
|
||||||
required: true
|
required: true
|
||||||
workflow_run:
|
workflow_run:
|
||||||
workflows: ["LinUtil Release"]
|
workflows: ["LinUtil Release"]
|
||||||
|
@ -14,29 +14,47 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
generate_preview:
|
generate_preview:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
environment: linutil_env
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: Checkout source
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set Run ID
|
- name: Get tag name ( Workflow Run )
|
||||||
run: |
|
id: latest_tag
|
||||||
if [ "${{ github.event_name }}" == "workflow_run" ]; then
|
uses: actions/github-script@v7
|
||||||
echo "run_id=${{ github.event.workflow_run.id }}" >> $GITHUB_ENV
|
if: github.event_name == 'workflow_run'
|
||||||
else
|
|
||||||
echo "run_id=${{ github.event.inputs.run_id }}" >> $GITHUB_ENV
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Download build artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
with:
|
||||||
name: linutil-artifact
|
script: |
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
const releases = await github.rest.repos.listReleases({
|
||||||
run-id: ${{ env.run_id }}
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
per_page: 1
|
||||||
|
});
|
||||||
|
core.setOutput('result', releases.data[0].tag_name);
|
||||||
|
result-encoding: string
|
||||||
|
|
||||||
|
- name: Set tag name ( Workflow Run )
|
||||||
|
if: github.event_name == 'workflow_run'
|
||||||
|
run: echo "tag_name=${{ steps.latest_tag.outputs.result }}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Set tag name ( Workflow Dispatch )
|
||||||
|
if: ${{ github.event_name }} == 'workflow_dispatch'
|
||||||
|
run: echo "tag_name=${{ github.event.inputs.tag_name }}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Download binary
|
||||||
|
run: |
|
||||||
|
curl -LO "https://github.com/${{ github.repository }}/releases/download/${{ env.tag_name }}/linutil"
|
||||||
|
|
||||||
- name: Set env
|
- name: Set env
|
||||||
run: |
|
run: |
|
||||||
chmod +x linutil
|
chmod +x linutil
|
||||||
echo "${{ github.workspace }}" >> $GITHUB_PATH
|
mkdir -p build
|
||||||
|
mv linutil build/linutil
|
||||||
|
echo "${{ github.workspace }}/build" >> $GITHUB_PATH
|
||||||
|
|
||||||
- name: Generate preview
|
- name: Generate preview
|
||||||
uses: charmbracelet/vhs-action@v2.1.0
|
uses: charmbracelet/vhs-action@v2.1.0
|
||||||
|
@ -46,10 +64,15 @@ jobs:
|
||||||
- name: Move preview
|
- name: Move preview
|
||||||
run: mv preview.gif docs/assets/preview.gif
|
run: mv preview.gif docs/assets/preview.gif
|
||||||
|
|
||||||
- name: Upload preview
|
- name: Create PR
|
||||||
uses: stefanzweifel/git-auto-commit-action@v5
|
uses: peter-evans/create-pull-request@v7.0.5
|
||||||
with:
|
with:
|
||||||
commit_message: Preview for ${{ env.run_id }}
|
commit-message: Preview for ${{ env.tag_name }}
|
||||||
file_pattern: "docs/assets/preview.gif"
|
file-pattern: "docs/assets/preview.gif"
|
||||||
add_options: "--force"
|
add-options: "--force"
|
||||||
|
token: ${{ secrets.PAT_TOKEN }}
|
||||||
|
branch: feature/preview-${{ env.tag_name }}
|
||||||
|
title: "Update preview for ${{ env.tag_name }}"
|
||||||
|
body: |
|
||||||
|
Automated PR to update preview gif for version ${{ env.tag_name }}
|
||||||
if: success()
|
if: success()
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
. ../../common-script.sh
|
||||||
|
|
||||||
|
manualInstall() {
|
||||||
|
JETBRAINS_TOOLBOX_DIR="/opt/jetbrains-toolbox"
|
||||||
|
|
||||||
|
case "$ARCH" in
|
||||||
|
x86_64) ARCHIVE_URL=$(curl -s "https://data.services.jetbrains.com/products/releases?code=TBA&latest=true&type=release" | jq -r ".TBA[0].downloads.linux.link") ;;
|
||||||
|
aarch64) ARCHIVE_URL=$(curl -s "https://data.services.jetbrains.com/products/releases?code=TBA&latest=true&type=release" | jq -r ".TBA[0].downloads.linuxARM64.link") ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
curl -fSL "$ARCHIVE_URL" -o "jetbrains-toolbox.tar.gz"
|
||||||
|
|
||||||
|
if [ -d "$JETBRAINS_TOOLBOX_DIR" ]; then
|
||||||
|
"$ESCALATION_TOOL" rm -rf "$JETBRAINS_TOOLBOX_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$ESCALATION_TOOL" mkdir -p "$JETBRAINS_TOOLBOX_DIR"
|
||||||
|
"$ESCALATION_TOOL" tar -xzf "jetbrains-toolbox.tar.gz" -C "$JETBRAINS_TOOLBOX_DIR" --strip-components=1
|
||||||
|
"$ESCALATION_TOOL" ln -sf "$JETBRAINS_TOOLBOX_DIR/jetbrains-toolbox" "/usr/bin/jetbrains-toolbox"
|
||||||
|
}
|
||||||
|
|
||||||
|
installJetBrainsToolBox() {
|
||||||
|
if ! command_exists jetbrains-toolbox; then
|
||||||
|
printf "%b\n" "${YELLOW}Installing Jetbrains Toolbox...${RC}"
|
||||||
|
case "$PACKAGER" in
|
||||||
|
pacman)
|
||||||
|
"$AUR_HELPER" -S --needed --noconfirm jetbrains-toolbox
|
||||||
|
;;
|
||||||
|
dnf)
|
||||||
|
manualInstall
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
"$ESCALATION_TOOL" "$PACKAGER" install -y libfuse2
|
||||||
|
manualInstall
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
printf "%b\n" "${GREEN}Successfully installed Jetbrains Toolbox.${RC}"
|
||||||
|
else
|
||||||
|
printf "%b\n" "${GREEN}Jetbrains toolbox is already installed.${RC}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
checkEnv
|
||||||
|
checkEscalationTool
|
||||||
|
checkAURHelper
|
||||||
|
installJetBrainsToolBox
|
|
@ -54,6 +54,12 @@ description = "GitHub Desktop is a user-friendly application that simplifies the
|
||||||
script = "Developer-tools/githubdesktop-setup.sh"
|
script = "Developer-tools/githubdesktop-setup.sh"
|
||||||
task_list = "I"
|
task_list = "I"
|
||||||
|
|
||||||
|
[[data.entries]]
|
||||||
|
name = "JetBrains Toolbox"
|
||||||
|
description = "JetBrains Toolbox is a collection of tools and an app that help developers work with JetBrains products."
|
||||||
|
script = "Developer-tools/jetbrains-toolbox.sh"
|
||||||
|
task_list = "I"
|
||||||
|
|
||||||
[[data.entries]]
|
[[data.entries]]
|
||||||
name = "Meld"
|
name = "Meld"
|
||||||
description = "Meld is a visual diff and merge tool that helps compare files, directories, and version-controlled projects."
|
description = "Meld is a visual diff and merge tool that helps compare files, directories, and version-controlled projects."
|
||||||
|
|
|
@ -51,6 +51,16 @@ elevated_execution() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkArch() {
|
||||||
|
case "$(uname -m)" in
|
||||||
|
x86_64 | amd64) ARCH="x86_64" ;;
|
||||||
|
aarch64 | arm64) ARCH="aarch64" ;;
|
||||||
|
*) printf "%b\n" "${RED}Unsupported architecture: $(uname -m)${RC}" && exit 1 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
printf "%b\n" "${CYAN}System architecture: ${ARCH}${RC}"
|
||||||
|
}
|
||||||
|
|
||||||
checkAURHelper() {
|
checkAURHelper() {
|
||||||
## Check & Install AUR helper
|
## Check & Install AUR helper
|
||||||
if [ "$PACKAGER" = "pacman" ]; then
|
if [ "$PACKAGER" = "pacman" ]; then
|
||||||
|
@ -169,6 +179,7 @@ checkDistro() {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkEnv() {
|
checkEnv() {
|
||||||
|
checkArch
|
||||||
checkEscalationTool
|
checkEscalationTool
|
||||||
checkCommandRequirements "curl groups $ESCALATION_TOOL"
|
checkCommandRequirements "curl groups $ESCALATION_TOOL"
|
||||||
checkPackageManager 'nala apt-get dnf pacman zypper'
|
checkPackageManager 'nala apt-get dnf pacman zypper'
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
### Developer Tools
|
### Developer Tools
|
||||||
|
|
||||||
- **Github Desktop**: GitHub Desktop is a user-friendly application that simplifies the process of managing Git repositories and interacting with GitHub, providing a graphical interface for tasks like committing, branching, and syncing changes.
|
- **Github Desktop**: GitHub Desktop is a user-friendly application that simplifies the process of managing Git repositories and interacting with GitHub, providing a graphical interface for tasks like committing, branching, and syncing changes.
|
||||||
|
- **JetBrains Toolbox**: JetBrains Toolbox is a collection of tools and an app that help developers work with JetBrains products.
|
||||||
- **Meld**: Meld is a visual diff and merge tool that helps compare files, directories, and version-controlled projects.
|
- **Meld**: Meld is a visual diff and merge tool that helps compare files, directories, and version-controlled projects.
|
||||||
- **Neovim**: Neovim is a refactor, and sometimes redactor, in the tradition of Vim.
|
- **Neovim**: Neovim is a refactor, and sometimes redactor, in the tradition of Vim.
|
||||||
It is not a rewrite but a continuation and extension of Vim.
|
It is not a rewrite but a continuation and extension of Vim.
|
||||||
|
|
|
@ -4,7 +4,7 @@ use ego_tree::NodeId;
|
||||||
use linutil_core::Tab;
|
use linutil_core::Tab;
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
layout::{Position, Rect},
|
layout::{Position, Rect},
|
||||||
style::Style,
|
style::{Color, Style},
|
||||||
text::Span,
|
text::Span,
|
||||||
widgets::{Block, Borders, Paragraph},
|
widgets::{Block, Borders, Paragraph},
|
||||||
Frame,
|
Frame,
|
||||||
|
@ -22,6 +22,7 @@ pub struct Filter {
|
||||||
in_search_mode: bool,
|
in_search_mode: bool,
|
||||||
input_position: usize,
|
input_position: usize,
|
||||||
items: Vec<ListEntry>,
|
items: Vec<ListEntry>,
|
||||||
|
completion_preview: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Filter {
|
impl Filter {
|
||||||
|
@ -31,17 +32,23 @@ impl Filter {
|
||||||
in_search_mode: false,
|
in_search_mode: false,
|
||||||
input_position: 0,
|
input_position: 0,
|
||||||
items: vec![],
|
items: vec![],
|
||||||
|
completion_preview: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn item_list(&self) -> &[ListEntry] {
|
pub fn item_list(&self) -> &[ListEntry] {
|
||||||
&self.items
|
&self.items
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn activate_search(&mut self) {
|
pub fn activate_search(&mut self) {
|
||||||
self.in_search_mode = true;
|
self.in_search_mode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deactivate_search(&mut self) {
|
pub fn deactivate_search(&mut self) {
|
||||||
self.in_search_mode = false;
|
self.in_search_mode = false;
|
||||||
|
self.completion_preview = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_items(&mut self, tabs: &[Tab], current_tab: usize, node: NodeId) {
|
pub fn update_items(&mut self, tabs: &[Tab], current_tab: usize, node: NodeId) {
|
||||||
if self.search_input.is_empty() {
|
if self.search_input.is_empty() {
|
||||||
let curr = tabs[current_tab].tree.get(node).unwrap();
|
let curr = tabs[current_tab].tree.get(node).unwrap();
|
||||||
|
@ -78,13 +85,34 @@ impl Filter {
|
||||||
}
|
}
|
||||||
self.items.sort_by(|a, b| a.node.name.cmp(&b.node.name));
|
self.items.sort_by(|a, b| a.node.name.cmp(&b.node.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.update_completion_preview();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_completion_preview(&mut self) {
|
||||||
|
if self.search_input.is_empty() {
|
||||||
|
self.completion_preview = None;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let input = self.search_input.iter().collect::<String>().to_lowercase();
|
||||||
|
self.completion_preview = self.items.iter().find_map(|item| {
|
||||||
|
let item_name_lower = item.node.name.to_lowercase();
|
||||||
|
if item_name_lower.starts_with(&input) {
|
||||||
|
Some(item_name_lower[input.len()..].to_string())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
pub fn draw_searchbar(&self, frame: &mut Frame, area: Rect, theme: &Theme) {
|
pub fn draw_searchbar(&self, frame: &mut Frame, area: Rect, theme: &Theme) {
|
||||||
//Set the search bar text (If empty use the placeholder)
|
//Set the search bar text (If empty use the placeholder)
|
||||||
let display_text = if !self.in_search_mode && self.search_input.is_empty() {
|
let display_text = if !self.in_search_mode && self.search_input.is_empty() {
|
||||||
Span::raw("Press / to search")
|
Span::raw("Press / to search")
|
||||||
} else {
|
} else {
|
||||||
Span::raw(self.search_input.iter().collect::<String>())
|
let input_text = self.search_input.iter().collect::<String>();
|
||||||
|
Span::styled(input_text, Style::default().fg(theme.focused_color()))
|
||||||
};
|
};
|
||||||
|
|
||||||
let search_color = if self.in_search_mode {
|
let search_color = if self.in_search_mode {
|
||||||
|
@ -110,11 +138,22 @@ impl Filter {
|
||||||
let x = area.x + cursor_position as u16 + 1;
|
let x = area.x + cursor_position as u16 + 1;
|
||||||
let y = area.y + 1;
|
let y = area.y + 1;
|
||||||
frame.set_cursor_position(Position::new(x, y));
|
frame.set_cursor_position(Position::new(x, y));
|
||||||
|
|
||||||
|
if let Some(preview) = &self.completion_preview {
|
||||||
|
let preview_span = Span::styled(preview, Style::default().fg(Color::DarkGray));
|
||||||
|
let preview_paragraph = Paragraph::new(preview_span).style(Style::default());
|
||||||
|
let preview_area = Rect::new(
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
(preview.len() as u16).min(area.width - cursor_position as u16 - 1),
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
frame.render_widget(preview_paragraph, preview_area);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Handles key events. Returns true if search must be exited
|
// Handles key events. Returns true if search must be exited
|
||||||
pub fn handle_key(&mut self, event: &KeyEvent) -> SearchAction {
|
pub fn handle_key(&mut self, event: &KeyEvent) -> SearchAction {
|
||||||
//Insert user input into the search bar
|
|
||||||
match event.code {
|
match event.code {
|
||||||
KeyCode::Char('c') if event.modifiers.contains(KeyModifiers::CONTROL) => {
|
KeyCode::Char('c') if event.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||||
return self.exit_search()
|
return self.exit_search()
|
||||||
|
@ -124,10 +163,17 @@ impl Filter {
|
||||||
KeyCode::Delete => self.remove_next(),
|
KeyCode::Delete => self.remove_next(),
|
||||||
KeyCode::Left => return self.cursor_left(),
|
KeyCode::Left => return self.cursor_left(),
|
||||||
KeyCode::Right => return self.cursor_right(),
|
KeyCode::Right => return self.cursor_right(),
|
||||||
|
KeyCode::Tab => return self.complete_search(),
|
||||||
|
KeyCode::Esc => {
|
||||||
|
self.input_position = 0;
|
||||||
|
self.search_input.clear();
|
||||||
|
self.completion_preview = None;
|
||||||
|
return SearchAction::Exit;
|
||||||
|
}
|
||||||
KeyCode::Enter => return SearchAction::Exit,
|
KeyCode::Enter => return SearchAction::Exit,
|
||||||
KeyCode::Esc => return self.exit_search(),
|
|
||||||
_ => return SearchAction::None,
|
_ => return SearchAction::None,
|
||||||
};
|
};
|
||||||
|
self.update_completion_preview();
|
||||||
SearchAction::Update
|
SearchAction::Update
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,16 +187,19 @@ impl Filter {
|
||||||
self.input_position = self.input_position.saturating_sub(1);
|
self.input_position = self.input_position.saturating_sub(1);
|
||||||
SearchAction::None
|
SearchAction::None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cursor_right(&mut self) -> SearchAction {
|
fn cursor_right(&mut self) -> SearchAction {
|
||||||
if self.input_position < self.search_input.len() {
|
if self.input_position < self.search_input.len() {
|
||||||
self.input_position += 1;
|
self.input_position += 1;
|
||||||
}
|
}
|
||||||
SearchAction::None
|
SearchAction::None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_char(&mut self, input: char) {
|
fn insert_char(&mut self, input: char) {
|
||||||
self.search_input.insert(self.input_position, input);
|
self.search_input.insert(self.input_position, input);
|
||||||
self.cursor_right();
|
self.cursor_right();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_previous(&mut self) {
|
fn remove_previous(&mut self) {
|
||||||
let current = self.input_position;
|
let current = self.input_position;
|
||||||
if current > 0 {
|
if current > 0 {
|
||||||
|
@ -158,12 +207,25 @@ impl Filter {
|
||||||
self.cursor_left();
|
self.cursor_left();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_next(&mut self) {
|
fn remove_next(&mut self) {
|
||||||
let current = self.input_position;
|
let current = self.input_position;
|
||||||
if current < self.search_input.len() {
|
if current < self.search_input.len() {
|
||||||
self.search_input.remove(current);
|
self.search_input.remove(current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn complete_search(&mut self) -> SearchAction {
|
||||||
|
if let Some(completion) = self.completion_preview.take() {
|
||||||
|
self.search_input.extend(completion.chars());
|
||||||
|
self.input_position = self.search_input.len();
|
||||||
|
self.update_completion_preview();
|
||||||
|
SearchAction::Update
|
||||||
|
} else {
|
||||||
|
SearchAction::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn clear_search(&mut self) {
|
pub fn clear_search(&mut self) {
|
||||||
self.search_input.clear();
|
self.search_input.clear();
|
||||||
self.input_position = 0;
|
self.input_position = 0;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user