Showing preview only (1,108K chars total). Download the full file or copy to clipboard to get everything.
Repository: yorukot/superfile
Branch: main
Commit: cba7254b0157
Files: 338
Total size: 1023.9 KB
Directory structure:
gitextract_l20rs_yr/
├── .envrc
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ ├── enhancement-suggestion.md
│ │ └── feature_request.md
│ ├── PULL_REQUEST_TEMPLATE/
│ │ └── pull_request_template.md
│ ├── renovate.json
│ └── workflows/
│ ├── first-interaction.yml
│ ├── lint-pr-title.yml
│ ├── mirror.yml
│ ├── superfile-build-test.yml
│ ├── testsuite-run.yml
│ ├── update-gomod2nix.yml
│ └── winget.yml
├── .gitignore
├── .golangci.yaml
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── README.md
├── asset/
│ └── spf.desktop
├── build.sh
├── cd_on_quit/
│ ├── cd_on_quit.fish
│ ├── cd_on_quit.ps1
│ └── cd_on_quit.sh
├── dev.sh
├── flake.nix
├── go.mod
├── go.sum
├── gomod2nix.toml
├── main.go
├── release/
│ ├── release.sh
│ ├── release_check.md
│ └── remove_all_spf_config.sh
├── src/
│ ├── cmd/
│ │ ├── debug_info.go
│ │ ├── help_printer.go
│ │ └── main.go
│ ├── config/
│ │ ├── fixed_variable.go
│ │ └── icon/
│ │ ├── function.go
│ │ └── icon.go
│ ├── internal/
│ │ ├── backend/
│ │ │ └── README.md
│ │ ├── common/
│ │ │ ├── README.md
│ │ │ ├── config_type.go
│ │ │ ├── default_config.go
│ │ │ ├── icon_utils.go
│ │ │ ├── icon_utils_test.go
│ │ │ ├── load_config.go
│ │ │ ├── predefined_variable.go
│ │ │ ├── string_function.go
│ │ │ ├── string_function_test.go
│ │ │ ├── style.go
│ │ │ ├── style_function.go
│ │ │ ├── type.go
│ │ │ └── ui_consts.go
│ │ ├── config_function.go
│ │ ├── default_config.go
│ │ ├── file_operation_compress_test.go
│ │ ├── file_operations.go
│ │ ├── file_operations_compress.go
│ │ ├── file_operations_extract.go
│ │ ├── function.go
│ │ ├── function_test.go
│ │ ├── handle_file_operation_test.go
│ │ ├── handle_file_operations.go
│ │ ├── handle_modal.go
│ │ ├── handle_panel_movement.go
│ │ ├── handle_panel_navigation.go
│ │ ├── key_function.go
│ │ ├── model.go
│ │ ├── model_file_operations_test.go
│ │ ├── model_layout_test.go
│ │ ├── model_msg.go
│ │ ├── model_navigation_test.go
│ │ ├── model_process_test.go
│ │ ├── model_prompt_test.go
│ │ ├── model_render.go
│ │ ├── model_test.go
│ │ ├── model_zoxide_test.go
│ │ ├── test_utils.go
│ │ ├── test_utils_teaprog.go
│ │ ├── type.go
│ │ ├── type_utils.go
│ │ ├── ui/
│ │ │ ├── README.md
│ │ │ ├── clipboard/
│ │ │ │ ├── model.go
│ │ │ │ └── model_test.go
│ │ │ ├── filemodel/
│ │ │ │ ├── consts.go
│ │ │ │ ├── dimensions.go
│ │ │ │ ├── navigation.go
│ │ │ │ ├── render.go
│ │ │ │ ├── type.go
│ │ │ │ ├── update.go
│ │ │ │ └── utils.go
│ │ │ ├── filepanel/
│ │ │ │ ├── columns.go
│ │ │ │ ├── consts.go
│ │ │ │ ├── dimension.go
│ │ │ │ ├── get_elements.go
│ │ │ │ ├── get_elements_test.go
│ │ │ │ ├── misc.go
│ │ │ │ ├── model.go
│ │ │ │ ├── navigation.go
│ │ │ │ ├── navigation_test.go
│ │ │ │ ├── render.go
│ │ │ │ ├── selection_test.go
│ │ │ │ ├── sort.go
│ │ │ │ ├── types.go
│ │ │ │ ├── update.go
│ │ │ │ └── utils.go
│ │ │ ├── helpmenu/
│ │ │ │ ├── data.go
│ │ │ │ ├── model_state.go
│ │ │ │ ├── navigation.go
│ │ │ │ ├── render.go
│ │ │ │ ├── type.go
│ │ │ │ └── utils.go
│ │ │ ├── metadata/
│ │ │ │ ├── README.md
│ │ │ │ ├── architecture.go
│ │ │ │ ├── architecture_test.go
│ │ │ │ ├── const.go
│ │ │ │ ├── metadata.go
│ │ │ │ ├── metadata_test.go
│ │ │ │ ├── metadata_unix.go
│ │ │ │ ├── metadata_windows.go
│ │ │ │ ├── model.go
│ │ │ │ ├── model_test.go
│ │ │ │ ├── testdata/
│ │ │ │ │ └── file1.txt
│ │ │ │ ├── update.go
│ │ │ │ └── utils.go
│ │ │ ├── notify/
│ │ │ │ ├── model.go
│ │ │ │ └── type.go
│ │ │ ├── preview/
│ │ │ │ ├── model.go
│ │ │ │ ├── model_utils.go
│ │ │ │ ├── render.go
│ │ │ │ ├── render_test.go
│ │ │ │ ├── render_unix_test.go
│ │ │ │ ├── render_utils.go
│ │ │ │ └── update.go
│ │ │ ├── processbar/
│ │ │ │ ├── README.md
│ │ │ │ ├── const.go
│ │ │ │ ├── error.go
│ │ │ │ ├── model.go
│ │ │ │ ├── model_navigation.go
│ │ │ │ ├── model_navigation_test.go
│ │ │ │ ├── model_test.go
│ │ │ │ ├── model_update.go
│ │ │ │ ├── model_update_test.go
│ │ │ │ ├── model_utils.go
│ │ │ │ ├── model_utils_test.go
│ │ │ │ ├── operation.go
│ │ │ │ ├── process.go
│ │ │ │ ├── process_test.go
│ │ │ │ └── process_update_msg.go
│ │ │ ├── prompt/
│ │ │ │ ├── README.md
│ │ │ │ ├── consts.go
│ │ │ │ ├── error.go
│ │ │ │ ├── model.go
│ │ │ │ ├── model_test.go
│ │ │ │ ├── tokenize.go
│ │ │ │ ├── tokenize_test.go
│ │ │ │ ├── type.go
│ │ │ │ ├── utils.go
│ │ │ │ └── utils_test.go
│ │ │ ├── rendering/
│ │ │ │ ├── README.md
│ │ │ │ ├── border.go
│ │ │ │ ├── constants.go
│ │ │ │ ├── content_renderer.go
│ │ │ │ ├── content_renderer_test.go
│ │ │ │ ├── renderer.go
│ │ │ │ ├── renderer_core.go
│ │ │ │ ├── renderer_test.go
│ │ │ │ ├── truncate.go
│ │ │ │ └── truncate_test.go
│ │ │ ├── sidebar/
│ │ │ │ ├── README.md
│ │ │ │ ├── consts.go
│ │ │ │ ├── directory_utils.go
│ │ │ │ ├── disk_utils.go
│ │ │ │ ├── navigation.go
│ │ │ │ ├── navigation_test.go
│ │ │ │ ├── pinned.go
│ │ │ │ ├── pinned_test.go
│ │ │ │ ├── render.go
│ │ │ │ ├── sidebar.go
│ │ │ │ ├── type.go
│ │ │ │ ├── utils.go
│ │ │ │ └── utils_test.go
│ │ │ ├── sortmodel/
│ │ │ │ ├── const.go
│ │ │ │ ├── model.go
│ │ │ │ ├── navigation.go
│ │ │ │ ├── render.go
│ │ │ │ ├── types.go
│ │ │ │ └── utils.go
│ │ │ ├── spf_renderers.go
│ │ │ └── zoxide/
│ │ │ ├── README.md
│ │ │ ├── consts.go
│ │ │ ├── model.go
│ │ │ ├── model_test.go
│ │ │ ├── navigation.go
│ │ │ ├── navigation_test.go
│ │ │ ├── render.go
│ │ │ ├── render_test.go
│ │ │ ├── test_helpers.go
│ │ │ ├── type.go
│ │ │ ├── utils.go
│ │ │ └── utils_test.go
│ │ ├── validation.go
│ │ └── wheel_function.go
│ ├── pkg/
│ │ ├── cache/
│ │ │ └── cache.go
│ │ ├── file_preview/
│ │ │ ├── ansi.go
│ │ │ ├── constants.go
│ │ │ ├── image_preview.go
│ │ │ ├── image_resize.go
│ │ │ ├── kitty.go
│ │ │ ├── thumbnail_generator.go
│ │ │ ├── utils.go
│ │ │ ├── utils_unix.go
│ │ │ └── utils_windows.go
│ │ ├── string_function/
│ │ │ └── overplace.go
│ │ └── utils/
│ │ ├── README.md
│ │ ├── bool_file_store.go
│ │ ├── bool_file_store_test.go
│ │ ├── config_interface.go
│ │ ├── consts.go
│ │ ├── detach_unix.go
│ │ ├── detach_windows.go
│ │ ├── error.go
│ │ ├── file_utils.go
│ │ ├── file_utils_test.go
│ │ ├── fzf_utils.go
│ │ ├── log_utils.go
│ │ ├── shell_utils.go
│ │ ├── tea_utils.go
│ │ ├── test_utils.go
│ │ ├── testdata/
│ │ │ └── load_toml/
│ │ │ ├── default.toml
│ │ │ ├── ignorer/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── default.toml
│ │ │ │ ├── default_extra_fields.toml
│ │ │ │ ├── invalid_format.toml
│ │ │ │ ├── invalid_value_type.toml
│ │ │ │ ├── missing_str2.toml
│ │ │ │ ├── missing_str_ignore.toml
│ │ │ │ ├── missing_str_ignore2.toml
│ │ │ │ └── missing_str_int.toml
│ │ │ └── missing_str.toml
│ │ └── ui_utils.go
│ └── superfile_config/
│ ├── config.toml
│ ├── hotkeys.toml
│ ├── theme/
│ │ ├── 0x96f.toml
│ │ ├── ayu-dark.toml
│ │ ├── blood.toml
│ │ ├── catppuccin-frappe.toml
│ │ ├── catppuccin-latte.toml
│ │ ├── catppuccin-macchiato.toml
│ │ ├── catppuccin-mocha.toml
│ │ ├── dracula.toml
│ │ ├── everforest-dark-hard.toml
│ │ ├── everforest-dark-medium.toml
│ │ ├── gruvbox-dark-hard.toml
│ │ ├── gruvbox.toml
│ │ ├── hacks.toml
│ │ ├── kaolin.toml
│ │ ├── monokai.toml
│ │ ├── nord.toml
│ │ ├── onedark.toml
│ │ ├── poimandres.toml
│ │ ├── rose-pine.toml
│ │ ├── sugarplum.toml
│ │ └── tokyonight.toml
│ └── vimHotkeys.toml
├── testsuite/
│ ├── .gitignore
│ ├── Notes.md
│ ├── README.md
│ ├── core/
│ │ ├── __init__.py
│ │ ├── base_test.py
│ │ ├── environment.py
│ │ ├── fs_manager.py
│ │ ├── keys.py
│ │ ├── pyautogui_manager.py
│ │ ├── runner.py
│ │ ├── spf_manager.py
│ │ ├── test_constants.py
│ │ ├── tmux_manager.py
│ │ └── utils.py
│ ├── docs/
│ │ └── tmux.md
│ ├── main.py
│ ├── requirements.txt
│ └── tests/
│ ├── __init__.py
│ ├── chooser_file_test.py
│ ├── command_test.py
│ ├── compress_extract_test.py
│ ├── copy_dir_test.py
│ ├── copy_test.py
│ ├── copyw_test.py
│ ├── cut_test.py
│ ├── delete_dir_test.py
│ ├── delete_test.py
│ ├── empty_panel_test.py
│ ├── nav_and_copy_path_test.py
│ └── rename_test.py
├── vhs/
│ ├── demo.tape
│ ├── open_spf_and_quit.tape
│ ├── spf_file_panel_movement.tape
│ ├── spf_file_panel_navigation.tape
│ ├── spf_file_panel_selection_mode.tape
│ └── spf_panel_navigation.tape
└── website/
├── README.md
├── astro.config.mjs
├── ec.config.mjs
├── package.json
├── public/
│ ├── _redirects
│ ├── google0fdf22175b8dde4d.html
│ ├── install.ps1
│ ├── install.sh
│ └── uninstall.ps1
├── src/
│ ├── components/
│ │ ├── GithubStar.astro
│ │ ├── LastUpdated.astro
│ │ ├── about.astro
│ │ └── code.astro
│ ├── content/
│ │ ├── config.ts
│ │ └── docs/
│ │ ├── changelog.md
│ │ ├── configure/
│ │ │ ├── config-file-path.md
│ │ │ ├── custom-hotkeys.mdx
│ │ │ ├── custom-theme.mdx
│ │ │ ├── enable-plugin.md
│ │ │ └── superfile-config.mdx
│ │ ├── contribute/
│ │ │ ├── file-struct.md
│ │ │ ├── how-to-contribute.md
│ │ │ └── implementation-info.md
│ │ ├── getting-started/
│ │ │ ├── image-preview.md
│ │ │ ├── installation.md
│ │ │ └── tutorial.md
│ │ ├── index.mdx
│ │ ├── list/
│ │ │ ├── hotkey-list.md
│ │ │ ├── plugin-list.md
│ │ │ └── theme-list.md
│ │ ├── overview.md
│ │ ├── special-thanks.mdx
│ │ └── troubleshooting.md
│ ├── env.d.ts
│ └── styles/
│ └── custom.css
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .envrc
================================================
use flake
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: yorukot # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**System information (please complete the following information):**
- OS: [e.g. iOS]
- Version [e.g. 22]
- superfile Version [e.g. 1.1.1]
================================================
FILE: .github/ISSUE_TEMPLATE/enhancement-suggestion.md
================================================
---
name: Enhancement suggestion
about: Enhance existing designs
title: ''
labels: enhancement
assignees: ''
---
**The part you want to Enhancement**
Please briefly describe the part you want to strengthen
**Why it is necessary to enhancement**
Please explain why it needs to be enhancement, what are the flaws in the existing design, etc.
**Additional context**
Add any other context or screenshots about the feature request here.
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: idea
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
================================================
FILE: .github/PULL_REQUEST_TEMPLATE/pull_request_template.md
================================================
# Description
Briefly summarize what this PR changes.
Include any context or motivation behind the change. If it depends on other changes or tools, please mention that too.
# Related Issues
If this PR fixes or relates to existing issues, list them here.
Example: `Fixes #123`
# Screenshots (Optional)
Add screenshots if this helps reviewers understand the change.
---
# ✅ Pre-Submission Checklist
Please go through the following steps **before** submitting this PR.
You can delete this section after confirming everything is done.
- [ ] I have run `go fmt ./...` to format the code
- [ ] I have run `golangci-lint run` and fixed any reported issues
- [ ] I have tested my changes and verified they work as expected
- [ ] I have reviewed the diff to make sure I’m not committing any debug logs or TODOs
- [ ] I have checked that the PR title follows the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) format
================================================
FILE: .github/renovate.json
================================================
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended", ":dependencyDashboard", "default:automergeDigest"],
"packageRules": [
{
"matchDatasources": ["go", "github-releases", "github-tags"],
"matchUpdateTypes": ["minor", "patch", "pin", "digest"],
"automerge": true,
"paths": ["/"],
"ignorePaths": [
"website/"
]
}
]
}
================================================
FILE: .github/workflows/first-interaction.yml
================================================
name: "Welcome First-Time Contributor"
on:
issues:
types: [opened]
pull_request:
types: [opened]
permissions:
contents: read
issues: write
pull-requests: write
jobs:
greet:
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@v3
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
issue_message: |
👋 Hi there, and welcome to **superfile**!
Thanks for opening your first issue. We really appreciate your interest and involvement.
A maintainer might ask you for more details or clarification to better understand the issue.
That’s totally normal and helps us solve the problem more effectively.
If you plan to submit a PR, make sure to check our [Contribution Guide](https://github.com/yorukot/superfile/blob/main/CONTRIBUTING.md)
pr_message: |
🎉 Thank you for your first contribution to **superfile**!
We’re really excited to have you here 🙌
A maintainer might ask you to make a few changes before we can merge this PR.
That’s totally normal and part of the process. Don’t worry, we’ll help guide you through it.
👉 Please also take a moment to review our [Contribution Guide](https://github.com/yorukot/superfile/blob/main/CONTRIBUTING.md)
If you have any questions, feel free to open a [Discussion](https://github.com/yorukot/superfile/discussions) or just ask in the comments!
================================================
FILE: .github/workflows/lint-pr-title.yml
================================================
name: "Lint PR Title"
on:
pull_request_target:
types:
- opened
- edited
- reopened
- synchronize
permissions:
pull-requests: write
jobs:
lint:
name: Check PR title format
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@v6
id: lint_pr_title
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
types: |
feat
fix
refactor
chore
docs
test
style
perf
ci
build
- uses: marocchino/sticky-pull-request-comment@v2
if: always() && (steps.lint_pr_title.outputs.error_message != null)
with:
header: pr-title-lint-error
message: |
⚠️ PR title format invalid.
superfile uses [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) for squash merges.
Allowed types:
```
feat, fix, refactor, chore, docs, test, style, perf, ci, build
```
👉 While not required, it’s **recommended** to include a scope like:
```
feat(file-preview): support Kitty image protocol
fix(renderer): correct ANSI fallback
```
---
```
${{ steps.lint_pr_title.outputs.error_message }}
```
- if: ${{ steps.lint_pr_title.outputs.error_message == null }}
uses: marocchino/sticky-pull-request-comment@v2
with:
header: pr-title-lint-error
delete: true
================================================
FILE: .github/workflows/mirror.yml
================================================
name: Mirror to Codeberg
permissions:
contents: read
on: [push] # Trigger on push to ANY branch
jobs:
mirror:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: yesolutions/mirror-action@master
with:
REMOTE: 'https://codeberg.org/yorukot/superfile.git'
GIT_USERNAME: yorukot
GIT_PASSWORD: ${{ secrets.CODEBERG_TOKEN }}
PUSH_ALL_REFS: "true"
================================================
FILE: .github/workflows/superfile-build-test.yml
================================================
name: Go CI
on:
push:
branches: [main]
pull_request:
branches: [main, develop]
permissions:
contents: read
jobs:
build:
name: Build and Test (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Setup dependencies (only on linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y exiftool
curl -sS https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | bash
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: '1.25.5'
- name: Cache Go modules
uses: actions/cache@v5
with:
path: |
~/.cache/go-build
${{ runner.temp }}/gomodcache
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Install dependencies
run: go mod download
env:
GOMODCACHE: ${{ runner.temp }}/gomodcache
- name: Build
run: go build -v ./...
env:
GOMODCACHE: ${{ runner.temp }}/gomodcache
- name: Test
run: go test -v ./...
env:
GOMODCACHE: ${{ runner.temp }}/gomodcache
- name: Check gofmt (skip on Windows)
if: runner.os != 'Windows'
run: |
go fmt ./...
git diff --exit-code
- name: golangci-lint (skip on Windows)
if: runner.os != 'Windows'
uses: golangci/golangci-lint-action@v9
with:
version: v2.8.0
args: --timeout 3m
================================================
FILE: .github/workflows/testsuite-run.yml
================================================
name: Python Testsuite Run
on:
push:
branches: [ main ]
pull_request:
branches: [ main, develop ]
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Install tmux
run: sudo apt-get update && sudo apt-get install -y tmux
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: '1.25.5'
- name: Build superfile
run: ./build.sh
# timeout command just launches and kills spf, to create the config directories
- name: Check installation
run: tmux -V; ls; pwd; ls bin/; bin/spf path-list; timeout 1s bin/spf
continue-on-error: true
- name: set debug
run: sed -i 's/debug = false/debug = true/g' /home/runner/.config/superfile/config.toml
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.14'
- name: Install Dependencies
run: pip install -r testsuite/requirements.txt
- name: Run Tests
run: python testsuite/main.py -d
- name: Print logs
if: always()
run: cat ~/.local/state/superfile/superfile.log
================================================
FILE: .github/workflows/update-gomod2nix.yml
================================================
name: Update gomod2nix.toml
on:
push:
paths:
- 'go.mod'
- 'go.sum'
permissions:
contents: write
jobs:
dependabot:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install Nix
uses: cachix/install-nix-action@v31
with:
github_access_token: ${{ secrets.GITHUB_TOKEN }}
nix_path: nixpkgs=channel:nixos-unstable
- name: Update checksum
run: |
nix develop --extra-experimental-features "nix-command flakes" '.#' -c "gomod2nix"
# git push if we have a diff
if [[ -n $(git diff) ]]; then
git config --global user.email "107802416+yorukot@users.noreply.github.com"
git config --global user.name "yorukot"
git commit -am "chore: update gomod2nix"
BRANCH_NAME=$(echo ${{ github.ref }} | sed -e 's/refs\/heads\///g')
git push origin HEAD:$BRANCH_NAME
fi
================================================
FILE: .github/workflows/winget.yml
================================================
name: Publish to WinGet
on:
release:
types: [released]
jobs:
publish:
name: Publish WinGet package
runs-on: windows-latest
steps:
- name: Submit package to Windows Package Manager Community Repository
uses: vedantmgoyal2009/winget-releaser@v2
with:
identifier: yorukot.superfile
installers-regex: '\.(zip|msi)$'
version: ${{ github.event.release.tag_name }}
release-tag: ${{ github.event.release.tag_name }}
token: ${{ secrets.WINGET_TOKEN }}
================================================
FILE: .gitignore
================================================
*.log
bin/
dist/
.idea/
# generated types
.astro/
# dependencies
node_modules/
# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Go test coverage reports
coverage.out
coverage.html
# environment variables
.env
.env.production
.direnv
# Python virtual environments
venv/
.venv/
testsuite/venv/
testsuite/.venv/
# macOS-specific files
.DS_Store
# Agent configs
CLAUDE.md
================================================
FILE: .golangci.yaml
================================================
# Based on https://gist.github.com/maratori/47a4d00457a92aa426dbd48a18776322
# Version used -
# https://gist.githubusercontent.com/maratori/47a4d00457a92aa426dbd48a18776322/raw/933de4558de48c79322aee44b44a9619eeaba167/.golangci.yml
# Note: Superfile doesn't ensure that this file's version is in sync with
# the version we use in CI. It can be outdated.
# Additional changes done for superfile
# - govet shadow analyzer is set to "strict : false" settings.
# strict : true causes too much noise
# This file is licensed under the terms of the MIT license https://opensource.org/license/mit
# Copyright (c) 2021-2025 Marat Reymers
## Golden config for golangci-lint v2.4.0
#
# This is the best config for golangci-lint based on my experience and opinion.
# It is very strict, but not extremely strict.
# Feel free to adapt it to suit your needs.
# If this config helps you, please consider keeping a link to this file (see the next comment).
# Based on https://gist.github.com/maratori/47a4d00457a92aa426dbd48a18776322
version: "2"
issues:
# Maximum count of issues with the same text.
# Set to 0 to disable.
# Default: 3
max-same-issues: 50
formatters:
enable:
- goimports # checks if the code and import statements are formatted according to the 'goimports' command
- golines # checks if code is formatted, and fixes long lines
## you may want to enable
# TODO
#- gci # checks if code and import statements are formatted, with additional rules
#- gofmt # checks if the code is formatted according to 'gofmt' command
#- gofumpt # enforces a stricter format than 'gofmt', while being backwards compatible
#- swaggo # formats swaggo comments
# All settings can be found here https://github.com/golangci/golangci-lint/blob/HEAD/.golangci.reference.yml
settings:
goimports:
# A list of prefixes, which, if set, checks import paths
# with the given prefixes are grouped after 3rd-party packages.
# Default: []
local-prefixes:
- github.com/yorukot/superfile
golines:
# Target maximum line length.
# Default: 100
max-len: 120
linters:
enable:
- asasalint # checks for pass []any as any in variadic func(...any)
- asciicheck # checks that your code does not contain non-ASCII identifiers
- bidichk # checks for dangerous unicode character sequences
- bodyclose # checks whether HTTP response body is closed successfully
- canonicalheader # checks whether net/http.Header uses canonical header
- copyloopvar # detects places where loop variables are copied (Go 1.22+)
- cyclop # checks function and package cyclomatic complexity
- depguard # checks if package imports are in a list of acceptable packages
- dupl # tool for code clone detection
- durationcheck # checks for two durations multiplied together
- embeddedstructfieldcheck # checks embedded types in structs
- errcheck # checking for unchecked errors, these unchecked errors can be critical bugs in some cases
- errname # checks that sentinel errors are prefixed with the Err and error types are suffixed with the Error
- errorlint # finds code that will cause problems with the error wrapping scheme introduced in Go 1.13
- exhaustive # checks exhaustiveness of enum switch statements
- exptostd # detects functions from golang.org/x/exp/ that can be replaced by std functions
- fatcontext # detects nested contexts in loops
# Not needed. this blocks only fmt.Print family and is not useful right now
# - forbidigo # forbids identifiers
- funcorder # checks the order of functions, methods, and constructors
- funlen # tool for detection of long functions
- gocheckcompilerdirectives # validates go compiler directive comments (//go:)
- gochecknoglobals # checks that no global variables exist
- gochecknoinits # checks that no init functions are present in Go code
- gochecksumtype # checks exhaustiveness on Go "sum types"
- gocognit # computes and checks the cognitive complexity of functions
- goconst # finds repeated strings that could be replaced by a constant
- gocritic # provides diagnostics that check for bugs, performance and style issues
- gocyclo # computes and checks the cyclomatic complexity of functions
# Not needed
# - godot # checks if comments end in a period
- gomoddirectives # manages the use of 'replace', 'retract', and 'excludes' directives in go.mod
- goprintffuncname # checks that printf-like functions are named with f at the end
- gosec # inspects source code for security problems
- govet # reports suspicious constructs, such as Printf calls whose arguments do not align with the format string
- iface # checks the incorrect use of interfaces, helping developers avoid interface pollution
- ineffassign # detects when assignments to existing variables are not used
- intrange # finds places where for loops could make use of an integer range
- loggercheck # checks key value pairs for common logger libraries (kitlog,klog,logr,zap)
- makezero # finds slice declarations with non-zero initial length
- mirror # reports wrong mirror patterns of bytes/strings usage
- mnd # detects magic numbers
- musttag # enforces field tags in (un)marshaled structs
- nakedret # finds naked returns in functions greater than a specified function length
# TODO enable : Many reports. A bit hard to understand the nesting value.
# - nestif # reports deeply nested if statements
- nilerr # finds the code that returns nil even if it checks that the error is not nil
- nilnesserr # reports that it checks for err != nil, but it returns a different nil value error (powered by nilness and nilerr)
- nilnil # checks that there is no simultaneous return of nil error and an invalid value
- noctx # finds sending http request without context.Context
- nolintlint # reports ill-formed or insufficient nolint directives
- nonamedreturns # reports all named returns
- nosprintfhostport # checks for misuse of Sprintf to construct a host with port in a URL
- perfsprint # checks that fmt.Sprintf can be replaced with a faster alternative
- predeclared # finds code that shadows one of Go's predeclared identifiers
- promlinter # checks Prometheus metrics naming via promlint
- protogetter # reports direct reads from proto message fields when getters should be used
- reassign # checks that package variables are not reassigned
- recvcheck # checks for receiver type consistency
- revive # fast, configurable, extensible, flexible, and beautiful linter for Go, drop-in replacement of golint
- rowserrcheck # checks whether Err of rows is checked successfully
# Need to use non-root logger. Not really needed.
# - sloglint # ensure consistent code style when using log/slog
- spancheck # checks for mistakes with OpenTelemetry/Census spans
- sqlclosecheck # checks that sql.Rows and sql.Stmt are closed
- staticcheck # is a go vet on steroids, applying a ton of static analysis checks
- testableexamples # checks if examples are testable (have an expected output)
- testifylint # checks usage of github.com/stretchr/testify
# [SPF Specific] Not needed - Makes it harder to test unexported package functions.
# - testpackage # makes you use a separate _test package
- tparallel # detects inappropriate usage of t.Parallel() method in your Go test codes
- unconvert # removes unnecessary type conversions
- unparam # reports unused function parameters
- unused # checks for unused constants, variables, functions and types
- usestdlibvars # detects the possibility to use variables/constants from the Go standard library
- usetesting # reports uses of functions with replacement inside the testing package
- wastedassign # finds wasted assignment statements
- whitespace # detects leading and trailing whitespace
## you may want to enable
#- arangolint # opinionated best practices for arangodb client
- decorder # checks declaration order and count of types, constants, variables and functions
# TODO Enable: Many issues right now.
#- exhaustruct # [highly recommend to enable] checks if all structure fields are initialized
#- ginkgolinter # [if you use ginkgo/gomega] enforces standards of using ginkgo and gomega
# TODO Enable. After fixing all TODOs
#- godox # detects usage of FIXME, TODO and other keywords inside comments
- goheader # checks is file header matches to pattern
#- inamedparam # [great idea, but too strict, need to ignore a lot of cases by default] reports interfaces with unnamed method parameters
- interfacebloat # checks the number of methods inside an interface
# TODO Enable: Function Update() is caught
#- ireturn # accept interfaces, return concrete types
#- noinlineerr # disallows inline error handling `if err := ...; err != nil {`
#- prealloc # [premature optimization, but can be used in some cases] finds slice declarations that could potentially be preallocated
#- tagalign # checks that struct tags are well aligned
#- varnamelen # [great idea, but too many false positives] checks that the length of a variable's name matches its scope
#- wrapcheck # checks that errors returned from external packages are wrapped
#- zerologlint # detects the wrong usage of zerolog that a user forgets to dispatch zerolog.Event
## disabled
#- containedctx # detects struct contained context.Context field
#- contextcheck # [too many false positives] checks the function whether use a non-inherited context
#- dogsled # checks assignments with too many blank identifiers (e.g. x, _, _, _, := f())
#- dupword # [useless without config] checks for duplicate words in the source code
#- err113 # [too strict] checks the errors handling expressions
#- errchkjson # [don't see profit + I'm against of omitting errors like in the first example https://github.com/breml/errchkjson] checks types passed to the json encoding functions. Reports unsupported types and optionally reports occasions, where the check for the returned error can be omitted
#- forcetypeassert # [replaced by errcheck] finds forced type assertions
#- gomodguard # [use more powerful depguard] allow and block lists linter for direct Go module dependencies
- gosmopolitan # reports certain i18n/l10n anti-patterns in your Go codebase
- grouper # analyzes expression groups
- importas # enforces consistent import aliases
#- lll # [replaced by golines] reports long lines
- maintidx # measures the maintainability index of each function
- misspell # [useless] finds commonly misspelled English words in comments
#- nlreturn # [too strict and mostly code is not more readable] checks for a new line before return and branch statements to increase code clarity
#- paralleltest # [too many false positives] detects missing usage of t.Parallel() method in your Go test
#- tagliatelle # checks the struct tags
#- thelper # detects golang test helpers without t.Helper() call and checks the consistency of test helpers
#- wsl # [too strict and mostly code is not more readable] whitespace linter forces you to use empty lines
#- wsl_v5 # [too strict and mostly code is not more readable] add or remove empty lines
# All settings can be found here https://github.com/golangci/golangci-lint/blob/HEAD/.golangci.reference.yml
settings:
cyclop:
# The maximal code complexity to report.
# Default: 10
max-complexity: 30
# The maximal average package complexity.
# If it's higher than 0.0 (float) the check is enabled.
# Default: 0.0
package-average: 10.0
depguard:
# Rules to apply.
#
# Variables:
# - File Variables
# Use an exclamation mark `!` to negate a variable.
# Example: `!$test` matches any file that is not a go test file.
#
# `$all` - matches all go files
# `$test` - matches all go test files
#
# - Package Variables
#
# `$gostd` - matches all of go's standard library (Pulled from `GOROOT`)
#
# Default (applies if no custom rules are defined): Only allow $gostd in all files.
rules:
"deprecated":
# List of file globs that will match this list of settings to compare against.
# By default, if a path is relative, it is relative to the directory where the golangci-lint command is executed.
# The placeholder '${base-path}' is substituted with a path relative to the mode defined with `run.relative-path-mode`.
# The placeholder '${config-path}' is substituted with a path relative to the configuration file.
# Default: $all
files:
- "$all"
# List of packages that are not allowed.
# Entries can be a variable (starting with $), a string prefix, or an exact match (if ending with $).
# Default: []
deny:
- pkg: github.com/golang/protobuf
desc: Use google.golang.org/protobuf instead, see https://developers.google.com/protocol-buffers/docs/reference/go/faq#modules
- pkg: github.com/satori/go.uuid
desc: Use github.com/google/uuid instead, satori's package is not maintained
- pkg: github.com/gofrs/uuid$
desc: Use github.com/gofrs/uuid/v5 or later, it was not a go module before v5
"non-test files":
files:
- "!$test"
deny:
- pkg: math/rand$
desc: Use math/rand/v2 instead, see https://go.dev/blog/randv2
"non-main files":
files:
- "!**/main.go"
deny:
- pkg: log$
desc: Use log/slog instead, see https://go.dev/blog/slog
embeddedstructfieldcheck:
# Checks that sync.Mutex and sync.RWMutex are not used as embedded fields.
# Default: false
forbid-mutex: true
errcheck:
# Report about not checking of errors in type assertions: `a := b.(MyStruct)`.
# Such cases aren't reported by default.
# Default: false
check-type-assertions: true
exhaustive:
# Program elements to check for exhaustiveness.
# Default: [ switch ]
check:
- switch
- map
exhaustruct:
# List of regular expressions to match type names that should be excluded from processing.
# Anonymous structs can be matched by '<anonymous>' alias.
# Has precedence over `include`.
# Each regular expression must match the full type name, including package path.
# For example, to match type `net/http.Cookie` regular expression should be `.*/http\.Cookie`,
# but not `http\.Cookie`.
# Default: []
exclude:
# std libs
- ^net/http.Client$
- ^net/http.Cookie$
- ^net/http.Request$
- ^net/http.Response$
- ^net/http.Server$
- ^net/http.Transport$
- ^net/url.URL$
- ^os/exec.Cmd$
- ^reflect.StructField$
# public libs
- ^github.com/Shopify/sarama.Config$
- ^github.com/Shopify/sarama.ProducerMessage$
- ^github.com/mitchellh/mapstructure.DecoderConfig$
- ^github.com/prometheus/client_golang/.+Opts$
- ^github.com/spf13/cobra.Command$
- ^github.com/spf13/cobra.CompletionOptions$
- ^github.com/stretchr/testify/mock.Mock$
- ^github.com/testcontainers/testcontainers-go.+Request$
- ^github.com/testcontainers/testcontainers-go.FromDockerfile$
- ^golang.org/x/tools/go/analysis.Analyzer$
- ^google.golang.org/protobuf/.+Options$
- ^gopkg.in/yaml.v3.Node$
# Allows empty structures in return statements.
# Default: false
allow-empty-returns: true
funcorder:
# Checks if the exported methods of a structure are placed before the non-exported ones.
# Default: true
struct-method: false
funlen:
# Checks the number of lines in a function.
# If lower than 0, disable the check.
# Default: 60
lines: 100
# Checks the number of statements in a function.
# If lower than 0, disable the check.
# Default: 40
statements: 50
gochecksumtype:
# Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.
# Default: true
default-signifies-exhaustive: false
gocognit:
# Minimal code complexity to report.
# Default: 30 (but we recommend 10-20)
min-complexity: 20
gocritic:
# Settings passed to gocritic.
# The settings key is the name of a supported gocritic checker.
# The list of supported checkers can be found at https://go-critic.com/overview.
settings:
captLocal:
# Whether to restrict checker to params only.
# Default: true
paramsOnly: false
underef:
# Whether to skip (*x).method() calls where x is a pointer receiver.
# Default: true
skipRecvDeref: false
govet:
# Enable all analyzers.
# Default: false
enable-all: true
# Disable analyzers by name.
# Run `GL_DEBUG=govet golangci-lint run --enable=govet` to see default, all available analyzers, and enabled analyzers.
# Default: []
disable:
- fieldalignment # too strict
# Settings per analyzer.
settings:
shadow:
# Whether to be strict about shadowing; can be noisy.
# Default: false
strict: false
inamedparam:
# Skips check for interface methods with only a single parameter.
# Default: false
skip-single-param: true
mnd:
# List of function patterns to exclude from analysis.
# Values always ignored: `time.Date`,
# `strconv.FormatInt`, `strconv.FormatUint`, `strconv.FormatFloat`,
# `strconv.ParseInt`, `strconv.ParseUint`, `strconv.ParseFloat`.
# Default: []
ignored-functions:
- args.Error
- flag.Arg
- flag.Duration.*
- flag.Float.*
- flag.Int.*
- flag.Uint.*
- os.Chmod
- os.Mkdir.*
- os.OpenFile
- os.WriteFile
- prometheus.ExponentialBuckets.*
- prometheus.LinearBuckets
nakedret:
# Make an issue if func has more lines of code than this setting, and it has naked returns.
# Default: 30
max-func-lines: 0
nolintlint:
# Exclude following linters from requiring an explanation.
# Default: []
allow-no-explanation: [ funlen, gocognit, golines ]
# Enable to require an explanation of nonzero length after each nolint directive.
# Default: false
require-explanation: true
# Enable to require nolint directives to mention the specific linter being suppressed.
# Default: false
require-specific: true
perfsprint:
# Optimizes into strings concatenation.
# Default: true
strconcat: false
reassign:
# Patterns for global variable names that are checked for reassignment.
# See https://github.com/curioswitch/go-reassign#usage
# Default: ["EOF", "Err.*"]
patterns:
- ".*"
revive:
rules:
- name: exported
disabled: true
- name: package-comments
disabled: true
rowserrcheck:
# database/sql is always checked.
# Default: []
packages:
- github.com/jmoiron/sqlx
sloglint:
# Enforce not using global loggers.
# Values:
# - "": disabled
# - "all": report all global loggers
# - "default": report only the default slog logger
# https://github.com/go-simpler/sloglint?tab=readme-ov-file#no-global
# Default: ""
no-global: all
# Enforce using methods that accept a context.
# Values:
# - "": disabled
# - "all": report all contextless calls
# - "scope": report only if a context exists in the scope of the outermost function
# https://github.com/go-simpler/sloglint?tab=readme-ov-file#context-only
# Default: ""
context: scope
staticcheck:
# SAxxxx checks in https://staticcheck.dev/docs/configuration/options/#checks
# Example (to disable some checks): [ "all", "-SA1000", "-SA1001"]
# Default: ["all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022"]
checks:
- all
# Incorrect or missing package comment.
# https://staticcheck.dev/docs/checks/#ST1000
- -ST1000
# Use consistent method receiver names.
# https://staticcheck.dev/docs/checks/#ST1016
- -ST1016
# Omit embedded fields from selector expression.
# https://staticcheck.dev/docs/checks/#QF1008
- -QF1008
usetesting:
# Enable/disable `os.TempDir()` detections.
# Default: false
os-temp-dir: true
exclusions:
# Log a warning if an exclusion rule is unused.
# Default: false
warn-unused: false
# Predefined exclusion rules.
# Default: []
presets:
- std-error-handling
- common-false-positives
# Excluding configuration per-path, per-linter, per-text and per-source.
rules:
- source: 'TODO'
linters: [ godot ]
- text: 'should have a package comment'
linters: [ revive ]
- text: 'exported \S+ \S+ should have comment( \(or a comment on this block\))? or be unexported'
linters: [ revive ]
- text: 'package comment should be of the form ".+"'
source: '// ?(nolint|TODO)'
linters: [ revive ]
- text: 'comment on exported \S+ \S+ should be of the form ".+"'
source: '// ?(nolint|TODO)'
linters: [ revive, staticcheck ]
- path: '_test\.go'
linters:
- bodyclose
- dupl
- errcheck
- funlen
- goconst
- gosec
- gosmopolitan
- noctx
- wrapcheck
- text: 'ST102[0-2]: comment.*should be of the form'
linters: [staticcheck]
# TODO: Fix this
- text: 'os/exec\.Command must not be called'
linters: [noctx]
# Stores globally accessible icon strings
- path: 'src/config/icon/icon.go'
linters:
- gochecknoglobals
# Stores prerendered styles
- path: 'src/internal/common/style.go'
linters:
- gochecknoglobals
# Some fixed variables like default config paths, version, etc.
- path: 'src/config/fixed_variable.go'
linters:
- gochecknoglobals
# Stores predefined variables, like re-used non-const strings
- path: 'src/internal/common/predefined_variable.go'
linters:
- gochecknoglobals
# Global variables storing config
- path: 'src/internal/common/default_config.go'
linters:
- gochecknoglobals
# Type defining config.toml and hotkey.toml
- path: 'src/internal/common/config_type.go'
linters:
- golines
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to superfile
Welcome to **superfile**! This guide will help you get started contributing to the project, whether you're fixing bugs, building features, or just sharing ideas.
There are many ways to contribute:
* Reporting bugs
* Fixing issues
* Adding a theme
* Suggesting and implementing new features
* Sharing ideas or feedback
---
## 🐞 Issues
### Found a bug?
Check if there's already an open or closed issue for it. If not, open a new one and describe the problem clearly.
### Want to fix an issue?
1. Fork this repository
2. Create a new branch for the issue you're working on
3. Commit your changes with clear messages
4. Open a pull request (PR) with a description of the problem and your solution
Maintainers may request changes before merging.
---
## 🎨 Adding a Theme
Before starting, make sure the theme you want to add doesn’t already exist.
1. Copy an existing theme's `.toml` file as a base
2. Customize it to your needs
3. Test it by editing your `~/.config/superfile/config/config.toml`
4. When ready, submit a pull request
5. To ensure the theme looks consistent and functions properly, please include the following screenshots in your PR:
- Full view of superfile (Including sidebar, file previewer, process panel, metadata panel, and clipboard panel )
- Make sure that file previewer is non empty, process panel has at least one process, and clipboard has at least one entry
- Add a screenshot of these individual panel being focused (To make sure border focus color is good)
- Sidebar
- Processbar
- Add a screenshot of help menu (Press ?)
- Add a screenshot of popup that opens when you create a new file (Ctrl+n)
- Add a screenshot of image being preview using your theme.
- Add a screenshot of successful and unsuccessful shell command.
<details>
<summary>Example:</summary>
- Full view of superfile (Including sidebar, file previewer, process panel, metadata panel, and clipboard panel)
- Make sure that file previewer is non empty, process panel has at least one process, and clipboard has at least one entry

- Add a screenshot of these individual panels being focused (To make sure border focus color is good)
- Sidebar
- Processbar


- Add a screenshot of help menu (Press `?`)

- Add a screenshot of popup that opens when you create a new file (Ctrl+n)

- Add a screenshot of image being previewed using your theme

- Add a screenshot of successful and unsuccessful shell command


</details>
---
## 💡 Sharing Ideas
Got a new idea? Awesome!
1. Check if similar ideas exist in Discussions or Issues
2. Open a discussion at: [https://github.com/yorukot/superfile/discussions](https://github.com/yorukot/superfile/discussions)
3. If you want to implement it yourself, follow the PR steps above
---
## 🧩 Don’t Know Where to Start?
Check out GitHub’s official guide:
[https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project](https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project)
Still unsure? Open a discussion — we’re happy to help.
---
## ✅ Pull Request Checklist
Please make sure your PR follows these steps:
* [ ] I have run `go fmt ./...` to format the code
* [ ] I have run `golangci-lint run` and fixed any reported issues
* [ ] I have tested my changes and verified they work as expected
* [ ] I have reviewed the diff to make sure I’m not committing any debug logs or TODOs
* [ ] I have filled out the PR template with description, context, and screenshots if needed
- [ ] I have checked that the PR title follows the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) format
---
## 🙏 Thank You
Thank you for contributing to superfile! We appreciate every issue, pull request, and idea. Your help makes this project better for everyone.
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2024 - Yorukot
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: Makefile
================================================
.PHONY: all build test lint clean dev testsuite help
# Default target
all: dev
# Development workflow (equivalent to ./dev.sh)
dev:
@FORCE_COLOR=1 ./dev.sh
# Build only
build:
@FORCE_COLOR=1 ./dev.sh --skip-tests
# Run tests
test:
@go test ./...
# Run linter
lint:
@golangci-lint run
# Run full testsuite
testsuite:
@FORCE_COLOR=1 ./dev.sh --testsuite
# Clean build artifacts
clean:
@rm -rf ./bin/
# Show help
help:
@echo "Available targets:"
@echo " all - Run full development workflow (default)"
@echo " dev - Run development workflow (./dev.sh)"
@echo " build - Build only (skip tests)"
@echo " test - Run unit tests only"
@echo " lint - Run linter only"
@echo " testsuite - Run full testsuite"
@echo " clean - Clean build artifacts"
@echo " help - Show this help"
@echo ""
@echo "For more options, use: ./dev.sh --help"
================================================
FILE: README.md
================================================
<div align="center">
<p>
<h4>
<a href="https://ko-fi.com/yorukot">superfile is supported by the community.</a>
</h4>
<div align="center" markdown="1">
<sup>Special thanks to:</sup>
<br>
<br>
<a href="https://www.warp.dev/?utm_source=github&utm_medium=referral&utm_campaign=superfile">
<img alt="Warp sponsorship" width="300" src="/asset/warp.png">
</a>
### [Warp, the AI terminal for developers](https://www.warp.dev/?utm_source=github&utm_medium=referral&utm_campaign=superfile)
[Available for macOS, Linux, & Windows](https://www.warp.dev/?utm_source=github&utm_medium=referral&utm_campaign=superfile)<br>
</div>
<hr>
</div>
<div align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="/asset/superfilelogowhite.png" />
<source media="(prefers-color-scheme: light)" srcset="/asset/superfilelogoblack.png" />
<img alt="superfile LOGO" src="/asset/superfilelogowhite.png" />
</picture>
[](https://goreportcard.com/report/github.com/yorukot/superfile)
[](https://raw.githubusercontent.com/yorukot/superfile/refs/heads/main/LICENSE)
[](https://discord.gg/YYtJ23Du7B)
[](https://github.com/yorukot/superfile/releases/latest)
[](https://www.coderabbit.ai/)

</div>
## Demo
| Perform common operations |
| ------------------------- |
|  |
## Content
- [Installation](#installation)
- [Build](#build)
- [Supported Systems](#supported-systems)
- [Tutorial](#tutorial)
- [Plugins](#plugins)
- [Themes](#themes)
- [Hotkeys](#hotkeys)
- [Notes](#notes)
- [Contributing](#contributing)
- [Troubleshooting](#troubleshooting)
- [Thanks](#thanks)
- [Support](#Support)
- [Core maintainer](#core-maintainer)
- [Contributors](#contributors)
- [Powered by](#powered-by)
- [Star History](#star-history)
## Installation
### macOS and Linux
```bash
bash -c "$(curl -sLo- https://superfile.dev/install.sh)"
```
If you want to inspect the script, see : [install.sh](./website/public/install.sh)
### Windows
#### Powershell
```powershell
powershell -ExecutionPolicy Bypass -Command "Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://superfile.dev/install.ps1'))"
```
If you want to inspect the script, see : [install.ps1](./website/public/install.ps1)
#### [Winget](https://winget.run/)
```powershell
winget install --id yorukot.superfile
```
#### [Scoop](https://scoop.sh/)
```
scoop install superfile
```
### More installation methods
[Click me to check on how to install](https://superfile.dev/getting-started/installation/)
## Build
You can build the source code yourself by using these steps:
**Requirements**
- [golang](https://go.dev/doc/install)
**Build Steps**
Clone this repository using the following command:
```
git clone https://github.com/yorukot/superfile.git --depth=1
```
Enter the downloaded directory:
```bash
cd superfile
```
### For macOS/Linux
Run the `build.sh` file:
```bash
./build.sh
```
Add the binary file to your $PATH, e.g., in `/usr/local/bin`:
```bash
sudo mv ./bin/spf /usr/local/bin
```
### For Windows
```bash
go build -o bin/spf.exe
```
Edit System Environment Variables and add superfile repo's `bin` directory to your PATH
## Start superfile
```bash
spf
```
## Supported Systems
- \[x\] Linux
- \[x\] macOS
- \[x\] Windows (Not fully supported yet)
## Tutorial
After you install superfile, you can go [here](https://superfile.dev/getting-started/tutorial/) to briefly understand how to use superfile!
## Plugins
[Click me to the plugins wiki](https://superfile.dev/list/plugin-list/)
## Themes
[Click me to the theme wiki](https://superfile.dev/configure/custom-theme/)
## Hotkeys
> [!WARNING]
> If you are vim/nvim user please change your default hotkeys config to vim version!
[**Click me to see the hotkey wiki**](https://superfile.dev/configure/custom-hotkeys/)
## Notes
We have an auto update functionality, that fetches superfile's latest released version from github (if last timestamp of last version check was less than 24 hours) and prints a prompt to user, if there is a newer version available.
You can turn this off, by setting `auto_check_update` to false in superfile config. [**Click me to see the config wiki**](https://superfile.dev/configure/superfile-config/)
## Troubleshooting
[**Click me to see common problem fix**](https://superfile.dev/troubleshooting/)
## Uninstalling
### macOS and Linux
On macOS and Linux, you can uninstall superfile by simply removing the binary. If you installed superfile with sudo, run:
```bash
sudo rm /usr/local/bin/spf
```
If you installed superfile without sudo, run:
```bash
rm ~/.local/bin/spf
```
If you don't rember, just try removing both.
### Window
To uninstall superfile on Windows, use this powershell script.
```powershell
powershell -ExecutionPolicy Bypass -Command "Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://superfile.dev/uninstall.ps1'))"
```
## Contributing
If you want to contribute please follow the [contribution guide](./CONTRIBUTING.md)
[**Click me to see changelog**](https://superfile.dev/changelog)
## Thanks
### Support
- a Star on my GitHub repository would be nice 🌟
- You can buy a coffee for me 💖
[](https://ko-fi.com/G2G1JEGGC)
### Core maintainer
> We welcome anyone who wants to become a core maintainer. Feel free to reach out!
- **[@yorukot](https://github.com/yorukot)** - Original author and maintainer
- **[@lazysegtree](https://github.com/lazysegtree)** - Core maintainer
### Contributors
**Thanks to all the contributors for making this project even greater!**
<a href="https://github.com/yorukot/superfile/graphs/contributors">
<img src="https://contrib.rocks/image?repo=yorukot/superfile" />
</a>
### Powered by
<a href="https://jb.gg/OpenSource"><img alt="JetBrains logo" align="right" width="200" src="https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg"></a>
Thanks to JetBrains team for providing open-source licenses to support the maintenance of superfile.
### Star History
**THANKS FOR All OF YOUR STARS!**
Your stars are my motivation to keep updating!
<a href="https://star-history.com/#yorukot/superfile&Timeline">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=yorukot/superfile&type=Timeline&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=yorukot/superfile&type=Timeline" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=yorukot/superfile&type=Timeline" />
</picture>
</a>
<div align="center">
## ༼ つ ◕_◕ ༽つ Please share.
</div>
================================================
FILE: asset/spf.desktop
================================================
[Desktop Entry]
Name=spf
GenericName=superfile
Comment=fancy and modern terminal file manager
Type=Application
MimeType=inode/directory
Icon=utilities-terminal
Terminal=true
TryExec=spf
Exec=spf %u
Categories=Utility;System;FileTools;FileManager;Filesystem;ConsoleOnly
Keywords=File;Manager;Explorer
================================================
FILE: build.sh
================================================
#!/usr/bin/env bash
# build the app
CGO_ENABLED=0 go build -o ./bin/spf
================================================
FILE: cd_on_quit/cd_on_quit.fish
================================================
function spf
set os $(uname -s)
if test "$os" = "Linux"
set spf_last_dir "$HOME/.local/state/superfile/lastdir"
end
if test "$os" = "Darwin"
set spf_last_dir "$HOME/Library/Application Support/superfile/lastdir"
end
command spf $argv
if test -f "$spf_last_dir"
source "$spf_last_dir"
rm -f -- "$spf_last_dir" >> /dev/null
end
end
================================================
FILE: cd_on_quit/cd_on_quit.ps1
================================================
function spf() {
param (
[string[]]$Params
)
$spf_location = [Environment]::GetFolderPath("LocalApplicationData") + "\Programs\superfile\spf.exe"
$SPF_LAST_DIR_PATH = [Environment]::GetFolderPath("LocalApplicationData") + "\superfile\lastdir"
& $spf_location @Params
if (Test-Path $SPF_LAST_DIR_PATH) {
$SPF_LAST_DIR = Get-Content -Path $SPF_LAST_DIR_PATH
Invoke-Expression $SPF_LAST_DIR
Remove-Item -Force $SPF_LAST_DIR_PATH
}
}
================================================
FILE: cd_on_quit/cd_on_quit.sh
================================================
spf() {
os=$(uname -s)
# Linux
if [[ "$os" == "Linux" ]]; then
export SPF_LAST_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/superfile/lastdir"
fi
# macOS
if [[ "$os" == "Darwin" ]]; then
export SPF_LAST_DIR="$HOME/Library/Application Support/superfile/lastdir"
fi
command spf "$@"
[ ! -f "$SPF_LAST_DIR" ] || {
. "$SPF_LAST_DIR"
rm -f -- "$SPF_LAST_DIR" > /dev/null
}
}
================================================
FILE: dev.sh
================================================
#!/usr/bin/env bash
set -e # Exit on any error
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Check if colors should be disabled
if [ "$FORCE_COLOR" != "1" ] && ([ -n "$MAKEFLAGS" ] || [ "$TERM" = "dumb" ] || [ ! -t 1 ]); then
# Disable colors when running under Make or non-interactive
RED=''
GREEN=''
YELLOW=''
BLUE=''
NC=''
fi
# Default values
RUN_TESTSUITE=false
SKIP_TESTS=false
VERBOSE=false
USE_GLOBAL_ENV=false
# Function to print colored output
print_step() {
printf "${BLUE}==>${NC} %s\n" "$1"
}
print_success() {
printf "${GREEN}✓${NC} %s\n" "$1"
}
print_warning() {
printf "${YELLOW}⚠${NC} %s\n" "$1"
}
print_error() {
printf "${RED}✗${NC} %s\n" "$1"
}
# Function to setup Python virtual environment
setup_venv() {
local venv_path="$1"
# Remove existing incomplete virtual environment if activate script is missing or pip is broken
if [ -d "$venv_path" ]; then
if [ ! -f "$venv_path/bin/activate" ]; then
print_warning "Removing incomplete virtual environment (missing activate)..."
rm -rf "$venv_path"
else
# Test if pip works in the existing virtual environment
if ! (source "$venv_path/bin/activate" && python -m pip --version > /dev/null 2>&1); then
print_warning "Removing broken virtual environment (pip not working)..."
rm -rf "$venv_path"
fi
fi
fi
if [ ! -d "$venv_path" ]; then
print_step "Creating Python virtual environment..."
if python3 -m venv "$venv_path" --upgrade-deps; then
print_success "Virtual environment created at $venv_path"
else
print_error "Failed to create virtual environment"
return 1
fi
else
print_step "Using existing virtual environment at $venv_path"
fi
# Check if activate script exists and has proper permissions
if [ ! -f "$venv_path/bin/activate" ]; then
print_error "Virtual environment activate script not found at $venv_path/bin/activate"
return 1
fi
# Ensure activate script has execution permissions
chmod +x "$venv_path/bin/activate"
# Activate virtual environment
source "$venv_path/bin/activate"
# Verify that we're in the virtual environment
if [ -z "$VIRTUAL_ENV" ]; then
print_error "Failed to activate virtual environment"
return 1
fi
# Upgrade pip to latest version
print_step "Upgrading pip in virtual environment..."
if python -m pip install --upgrade pip > /dev/null 2>&1; then
print_success "Pip upgraded successfully"
else
print_warning "Failed to upgrade pip - continuing anyway"
fi
return 0
}
# Function to cleanup virtual environment
cleanup_venv() {
if [ -n "$VIRTUAL_ENV" ]; then
deactivate 2>/dev/null || true
fi
}
# Setup trap for cleanup on exit/interruption
trap cleanup_venv EXIT INT TERM
# Function to show usage
usage() {
echo "Usage: $0 [OPTIONS]"
echo ""
echo "A comprehensive script for formatting, testing, and building superfile"
echo ""
echo "OPTIONS:"
echo " -t, --testsuite Run integration testsuite after unit tests"
echo " -s, --skip-tests Skip unit tests (only format, lint, and build)"
echo " -v, --verbose Enable verbose output"
echo " --use-global-env Use global Python environment instead of virtual environment"
echo " -h, --help Show this help message"
echo ""
echo "STEPS PERFORMED:"
echo " 1. Tidy Go modules"
echo " 2. Format code with 'go fmt'"
echo " 3. Run golangci-lint"
echo " 4. Run unit tests (unless --skip-tests)"
echo " 5. Run integration testsuite (if --testsuite)"
echo " 6. Build spf binary"
}
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-t|--testsuite)
RUN_TESTSUITE=true
shift
;;
-s|--skip-tests)
SKIP_TESTS=true
shift
;;
-v|--verbose)
VERBOSE=true
shift
;;
--use-global-env)
USE_GLOBAL_ENV=true
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown option: $1"
usage
exit 1
;;
esac
done
# Set verbose flag for commands if requested
VERBOSE_FLAG=""
if [ "$VERBOSE" = true ]; then
VERBOSE_FLAG="-v"
fi
printf "${BLUE}🚀 Starting superfile development workflow${NC}\n"
echo ""
# Step 1: Tidy up the go mod
print_step "Tidying Go modules..."
if go mod tidy $VERBOSE_FLAG; then
print_success "Go modules tidied"
else
print_error "Failed to tidy Go modules"
exit 1
fi
# Step 2: Format the code
print_step "Formatting Go code..."
if go fmt ./...; then
print_success "Code formatted"
else
print_error "Failed to format code"
exit 1
fi
# Step 3: Run the linter
print_step "Running golangci-lint..."
if golangci-lint run; then
print_success "Linting passed"
else
print_error "Linting failed"
exit 1
fi
# Step 4: Run unit tests (unless skipped)
if [ "$SKIP_TESTS" = false ]; then
print_step "Running unit tests..."
if [ "$VERBOSE" = true ]; then
if go test -v ./...; then
print_success "Unit tests passed"
else
print_error "Unit tests failed"
exit 1
fi
else
if go test ./...; then
print_success "Unit tests passed"
else
print_error "Unit tests failed"
exit 1
fi
fi
else
print_warning "Skipping unit tests"
fi
# Step 5: Run integration testsuite (if requested)
if [ "$RUN_TESTSUITE" = true ]; then
print_step "Running integration testsuite..."
# Check if Python is available
if ! command -v python3 &> /dev/null; then
print_error "Python3 is required for testsuite but not found"
exit 1
fi
# Check if testsuite requirements are installed
if [ ! -f "testsuite/requirements.txt" ]; then
print_error "testsuite/requirements.txt not found"
exit 1
fi
cd testsuite
# Use virtual environment by default, global environment if requested
if [ "$USE_GLOBAL_ENV" = true ]; then
# Install requirements globally
print_step "Installing testsuite requirements globally..."
print_warning "Using global Python environment - consider removing --use-global-env flag to use virtual environment"
if python3 -m pip install -r requirements.txt > /dev/null 2>&1; then
print_success "Testsuite requirements installed globally"
else
print_warning "Failed to install testsuite requirements - continuing anyway"
fi
else
# Setup virtual environment (default behavior)
VENV_PATH="./venv"
if ! setup_venv "$VENV_PATH"; then
print_error "Failed to setup virtual environment"
cd ..
exit 1
fi
# Install requirements in virtual environment
print_step "Installing testsuite requirements in virtual environment..."
if python -m pip install -r requirements.txt > /dev/null 2>&1; then
print_success "Testsuite requirements installed in virtual environment"
else
print_error "Failed to install testsuite requirements in virtual environment"
cd ..
exit 1
fi
fi
# Run the testsuite
if [ "$VERBOSE" = true ]; then
if python3 main.py --debug; then
print_success "Integration testsuite passed"
else
print_error "Integration testsuite failed"
cd ..
exit 1
fi
else
if python3 main.py; then
print_success "Integration testsuite passed"
else
print_error "Integration testsuite failed"
cd ..
exit 1
fi
fi
cd ..
fi
# Step 6: Build the app
print_step "Building spf binary..."
if CGO_ENABLED=0 go build -o ./bin/spf; then
print_success "Build completed successfully"
else
print_error "Build failed"
exit 1
fi
echo ""
printf "${GREEN}🎉 All steps completed successfully!${NC}\n"
printf "${BLUE}Binary location:${NC} ./bin/spf\n"
# Show binary info
if [ -f "./bin/spf" ]; then
BINARY_SIZE=$(du -h ./bin/spf | cut -f1)
printf "${BLUE}Binary size:${NC} $BINARY_SIZE\n"
fi
================================================
FILE: flake.nix
================================================
{
description = "A fancy, pretty terminal file manager";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
flake-compat.url = "github:edolstra/flake-compat";
flake-compat.flake = false;
gomod2nix.url = "github:nix-community/gomod2nix";
gomod2nix.inputs.nixpkgs.follows = "nixpkgs";
gomod2nix.inputs.flake-utils.follows = "flake-utils";
};
outputs = inputs @ {...}:
inputs.flake-utils.lib.eachDefaultSystem
(
system: let
overlays = [
inputs.gomod2nix.overlays.default
];
pkgs = import inputs.nixpkgs {
inherit system overlays;
};
in rec {
packages = rec {
superfile = pkgs.buildGoApplication {
pname = "superfile";
version = "1.5.0";
src = ./.;
modules = ./gomod2nix.toml;
nativeCheckInputs = with pkgs; [
zoxide
exiftool
writableTmpDirAsHomeHook
];
};
default = superfile;
};
apps = rec {
superfile = {
type = "app";
program = "${packages.superfile}/bin/superfile";
};
default = superfile;
};
devShells = {
default = pkgs.mkShell {
packages = with pkgs; [
## golang
delve
go-outline
go
golangci-lint
gopkgs
gopls
gotools
nix
gomod2nix
nixpkgs-fmt
];
};
};
}
);
}
================================================
FILE: go.mod
================================================
module github.com/yorukot/superfile
go 1.25.5
require (
github.com/adrg/xdg v0.5.3
github.com/alecthomas/chroma/v2 v2.21.1
github.com/atotto/clipboard v0.1.4
github.com/barasher/go-exiftool v1.10.0
github.com/charmbracelet/bubbles v0.21.0
github.com/charmbracelet/bubbletea v1.3.10
github.com/charmbracelet/lipgloss v1.1.0
github.com/charmbracelet/x/ansi v0.10.1
github.com/fatih/color v1.18.0
github.com/fvbommel/sortorder v1.1.0
github.com/hymkor/trash-go v0.2.0
github.com/lazysegtree/go-zoxide v0.1.0
github.com/lithammer/shortuuid v3.0.0+incompatible
github.com/muesli/termenv v0.16.0
github.com/reinhrst/fzf-lib v0.9.0
github.com/rkoesters/xdg v0.0.1
github.com/shirou/gopsutil/v4 v4.25.12
github.com/stretchr/testify v1.11.1
github.com/urfave/cli/v3 v3.6.1
golang.org/x/image v0.35.0
golang.org/x/mod v0.31.0
golift.io/xtractr v0.2.2
)
require (
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
github.com/charmbracelet/x/term v0.2.1 // indirect
github.com/clipperhouse/stringish v0.1.1 // indirect
github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
github.com/ebitengine/purego v0.9.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
golang.org/x/term v0.18.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
require (
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/bodgit/plumbing v1.3.0 // indirect
github.com/bodgit/sevenzip v1.4.0 // indirect
github.com/bodgit/windows v1.0.1 // indirect
github.com/connesc/cipherio v0.2.1 // indirect
github.com/dlclark/regexp2 v1.11.5 // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/kdomanski/iso9660 v0.3.3 // indirect
github.com/klauspost/compress v1.16.3 // indirect
github.com/nwaples/rardecode v1.1.3 // indirect
github.com/pierrec/lz4/v4 v4.1.17 // indirect
github.com/ulikunitz/xz v0.5.15 // indirect
github.com/yorukot/ansichroma v0.1.0
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
)
require (
github.com/BourgeoisBear/rasterm v1.1.2
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/harmonica v0.2.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/disintegration/imaging v1.6.2
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-localereader v0.0.1 // indirect
github.com/mattn/go-runewidth v0.0.19 // indirect
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/reflow v0.3.0
github.com/pelletier/go-toml/v2 v2.2.4
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd
github.com/yusufpapurcu/wmi v1.2.4 // indirect
golang.org/x/sys v0.38.0 // indirect
golang.org/x/text v0.33.0
)
================================================
FILE: go.sum
================================================
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BourgeoisBear/rasterm v1.1.2 h1:hWHZBZ45N366uNSqxWFYBV0y19q8fXRXADhPkoLF4Ss=
github.com/BourgeoisBear/rasterm v1.1.2/go.mod h1:Ifd+To5s/uyUiYx+B4fxhS8lUNwNLSxDBjskmC5pEyw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78=
github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ=
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
github.com/alecthomas/chroma/v2 v2.21.1 h1:FaSDrp6N+3pphkNKU6HPCiYLgm8dbe5UXIXcoBhZSWA=
github.com/alecthomas/chroma/v2 v2.21.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o=
github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs=
github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/barasher/go-exiftool v1.10.0 h1:f5JY5jc42M7tzR6tbL9508S2IXdIcG9QyieEXNMpIhs=
github.com/barasher/go-exiftool v1.10.0/go.mod h1:F9s/a3uHSM8YniVfwF+sbQUtP8Gmh9nyzigNF+8vsWo=
github.com/bodgit/plumbing v1.3.0 h1:pf9Itz1JOQgn7vEOE7v7nlEfBykYqvUYioC61TwWCFU=
github.com/bodgit/plumbing v1.3.0/go.mod h1:JOTb4XiRu5xfnmdnDJo6GmSbSbtSyufrsyZFByMtKEs=
github.com/bodgit/sevenzip v1.4.0 h1:OPUy/dCA9KvDTxcwQQYkv/W7kHmxhP4B3vpW8S02WlA=
github.com/bodgit/sevenzip v1.4.0/go.mod h1:0WaxeLofKpADVzngQXcMoXb98627kLDiqTZyDLaVxiA=
github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4=
github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs=
github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg=
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4=
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk=
github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ=
github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ=
github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8=
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4=
github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
github.com/connesc/cipherio v0.2.1 h1:FGtpTPMbKNNWByNrr9aEBtaJtXjqOzkIXNYJp6OEycw=
github.com/connesc/cipherio v0.2.1/go.mod h1:ukY0MWJDFnJEbXMQtOcn2VmTpRfzcTz4OoVrWGGJZcA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A=
github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw=
github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/hymkor/trash-go v0.2.0 h1:t51zidKT8WuMTeeiMBsJxx+BDwnJtaaf/ckpjle2GOE=
github.com/hymkor/trash-go v0.2.0/go.mod h1:pZ07qBUuGdTWPdymNtE97NAXHDY5W/b5szvoBVOhJ3U=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kdomanski/iso9660 v0.3.3 h1:cNwM9L2L1Hzc5hZWGy6fPJ92UyWDccaY69DmEPlfDNY=
github.com/kdomanski/iso9660 v0.3.3/go.mod h1:K+UlIGxKgtrdAWyoigPnFbeQLVs/Xudz4iztWFThBwo=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY=
github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lazysegtree/go-zoxide v0.1.0 h1:gL11AWS9fJDuB7FYxsh+ohf8ozMXeK31E/PC6f9jNBc=
github.com/lazysegtree/go-zoxide v0.1.0/go.mod h1:C1K2SDM4iHkQeFVrWBiRX3tU9jpAz6BrnoHQYSiHZl0=
github.com/lithammer/shortuuid v3.0.0+incompatible h1:NcD0xWW/MZYXEHa6ITy6kaXN5nwm/V115vj2YXfhS0w=
github.com/lithammer/shortuuid v3.0.0+incompatible/go.mod h1:FR74pbAuElzOUuenUHTK2Tciko1/vKuIKS9dSkDrA4w=
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw=
github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc=
github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc=
github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/reinhrst/fzf-lib v0.9.0 h1:P57AkpmDOmRhuBTDclvasclcOY7kNVWJUVVEBEB9kCA=
github.com/reinhrst/fzf-lib v0.9.0/go.mod h1:06+ssO8WzlXxOUT7RtLo2gXf9tSR7HU8fbBgFX1VP6k=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rkoesters/xdg v0.0.1 h1:RmfYxghVvIsb4d51u5LtNOcwqY5r3P44u6o86qqvBMA=
github.com/rkoesters/xdg v0.0.1/go.mod h1:5DcbjvJkY00fIOKkaBnylbC/rmc1NNJP5dmUcnlcm7U=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd h1:CmH9+J6ZSsIjUK3dcGsnCnO41eRBOnY12zwkn5qVwgc=
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
github.com/shirou/gopsutil/v4 v4.25.12 h1:e7PvW/0RmJ8p8vPGJH4jvNkOyLmbkXgXW4m6ZPic6CY=
github.com/shirou/gopsutil/v4 v4.25.12/go.mod h1:EivAfP5x2EhLp2ovdpKSozecVXn1TmuG7SMzs/Wh4PU=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY=
github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli/v3 v3.6.1 h1:j8Qq8NyUawj/7rTYdBGrxcH7A/j7/G8Q5LhWEW4G3Mo=
github.com/urfave/cli/v3 v3.6.1/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
github.com/yorukot/ansichroma v0.1.0 h1:S7mAB41CgSbYp2tcERMN/bT3cNfdNbexmLm5R0GftzA=
github.com/yorukot/ansichroma v0.1.0/go.mod h1:Er9xbqeEBUScZnfUezMWl31vBYleQBxoZ0tBhOnqhwI=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc=
go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.34.0 h1:33gCkyw9hmwbZJeZkct8XyR11yH889EQt/QH4VmXMn8=
golang.org/x/image v0.34.0/go.mod h1:2RNFBZRB+vnwwFil8GkMdRvrJOFd1AzdZI6vOY+eJVU=
golang.org/x/image v0.35.0 h1:LKjiHdgMtO8z7Fh18nGY6KDcoEtVfsgLDPeLyguqb7I=
golang.org/x/image v0.35.0/go.mod h1:MwPLTVgvxSASsxdLzKrl8BRFuyqMyGhLwmC+TO1Sybk=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golift.io/xtractr v0.2.2 h1:MvujxeuX629d1rQs2VJbbcvYMvMmN5SzIkEflU5ryOc=
golift.io/xtractr v0.2.2/go.mod h1:30CvLMUY3yOS2VoKZTTMtzeeljCzBcWkr8dU6EHqfh8=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
================================================
FILE: gomod2nix.toml
================================================
schema = 3
[mod]
[mod.'github.com/BourgeoisBear/rasterm']
version = 'v1.1.2'
hash = 'sha256-fYV85hVcIAT01xriEpWn0f/YyGgsc7W+0SW6iz9K/+A='
[mod.'github.com/adrg/xdg']
version = 'v0.5.3'
hash = 'sha256-bo6tBgHS+3sl6f4oWpmdFrZjfV6eA/3xAlysSW0bIEs='
[mod.'github.com/alecthomas/chroma/v2']
version = 'v2.21.1'
hash = 'sha256-N6ske1LCEJy7MZS1L/0DEaWXnWlVqGaoU6oCwrM5teQ='
[mod.'github.com/andybalholm/brotli']
version = 'v1.0.5'
hash = 'sha256-/qS8wU8yZQJ+uTOg66rEl9s7spxq9VIXF5L1BcaEClc='
[mod.'github.com/atotto/clipboard']
version = 'v0.1.4'
hash = 'sha256-ZZ7U5X0gWOu8zcjZcWbcpzGOGdycwq0TjTFh/eZHjXk='
[mod.'github.com/aymanbagabas/go-osc52/v2']
version = 'v2.0.1'
hash = 'sha256-6Bp0jBZ6npvsYcKZGHHIUSVSTAMEyieweAX2YAKDjjg='
[mod.'github.com/barasher/go-exiftool']
version = 'v1.10.0'
hash = 'sha256-ed+Jhji3usyMROzjw7Xq++khLz3mDrlgfn+vrBXWZgg='
[mod.'github.com/bodgit/plumbing']
version = 'v1.3.0'
hash = 'sha256-nmLdJAB2sWpwHb2lFrYTcMR4yusMM1U629Pm2K9hfm0='
[mod.'github.com/bodgit/sevenzip']
version = 'v1.4.0'
hash = 'sha256-1y3jeuXQPEYWe8iuOhplbHtZjN2GgAXDnJaJohDMwLc='
[mod.'github.com/bodgit/windows']
version = 'v1.0.1'
hash = 'sha256-GSpAGboli54A5wDMpDEdZDYh55o1Zs8dZzFIf7hYdMY='
[mod.'github.com/charmbracelet/bubbles']
version = 'v0.21.0'
hash = 'sha256-cfjUHgy9eq5SretTHuYuRaeeT6QmJYQBB9dsI8QSnW0='
[mod.'github.com/charmbracelet/bubbletea']
version = 'v1.3.10'
hash = 'sha256-7wr85TLszu1CHNEMv+o4w+r24Z0xdzCgecPv+ZtRX/A='
[mod.'github.com/charmbracelet/colorprofile']
version = 'v0.2.3-0.20250311203215-f60798e515dc'
hash = 'sha256-D9E/bMOyLXAUVOHA1/6o3i+vVmLfwIMOWib6sU7A6+Q='
[mod.'github.com/charmbracelet/harmonica']
version = 'v0.2.0'
hash = 'sha256-fi5N0IXhSbbYHdSZFngCfpT4kdiEaKedqj8YpnlvX0o='
[mod.'github.com/charmbracelet/lipgloss']
version = 'v1.1.0'
hash = 'sha256-RHsRT2EZ1nDOElxAK+6/DC9XAaGVjDTgPvRh3pyCfY4='
[mod.'github.com/charmbracelet/x/ansi']
version = 'v0.10.1'
hash = 'sha256-nY4zkUGnuD+Lczwt+NMXdQ38cAsy5mtxzXrFSJmR0E4='
[mod.'github.com/charmbracelet/x/cellbuf']
version = 'v0.0.13-0.20250311204145-2c3ea96c31dd'
hash = 'sha256-XAhCOt8qJ2vR77lH1ez0IVU1/2CaLTq9jSmrHVg5HHU='
[mod.'github.com/charmbracelet/x/term']
version = 'v0.2.1'
hash = 'sha256-VBkCZLI90PhMasftGw3403IqoV7d3E5WEGAIVrN5xQM='
[mod.'github.com/clipperhouse/stringish']
version = 'v0.1.1'
hash = 'sha256-Mp8M1CRbwr6dcJ4BD9tXD5I78ZgCFEm0GDxJv0GYReg='
[mod.'github.com/clipperhouse/uax29/v2']
version = 'v2.3.0'
hash = 'sha256-dLL70mEOxrmYVoQjy2K7QvZiahAlJKOcFDz2mW/R/Do='
[mod.'github.com/connesc/cipherio']
version = 'v0.2.1'
hash = 'sha256-PeuFnTak2WADesP8YTBqHP/XyvBue9bdKHYser2v6LU='
[mod.'github.com/davecgh/go-spew']
version = 'v1.1.2-0.20180830191138-d8f796af33cc'
hash = 'sha256-fV9oI51xjHdOmEx6+dlq7Ku2Ag+m/bmbzPo6A4Y74qc='
[mod.'github.com/disintegration/imaging']
version = 'v1.6.2'
hash = 'sha256-pSeMTPvSkxlthh65LjNYYhPLvCZDkBgVgAGYWW0Aguo='
[mod.'github.com/dlclark/regexp2']
version = 'v1.11.5'
hash = 'sha256-jN5+2ED+YbIoPIuyJ4Ou5pqJb2w1uNKzp5yTjKY6rEQ='
[mod.'github.com/ebitengine/purego']
version = 'v0.9.1'
hash = 'sha256-iVfU8vaJ7IPa92dUeHeuW+yKvUbe59F/eV7GlDRIAcE='
[mod.'github.com/erikgeiser/coninput']
version = 'v0.0.0-20211004153227-1c3628e74d0f'
hash = 'sha256-OWSqN1+IoL73rWXWdbbcahZu8n2al90Y3eT5Z0vgHvU='
[mod.'github.com/fatih/color']
version = 'v1.18.0'
hash = 'sha256-pP5y72FSbi4j/BjyVq/XbAOFjzNjMxZt2R/lFFxGWvY='
[mod.'github.com/fvbommel/sortorder']
version = 'v1.1.0'
hash = 'sha256-553Rg/amloO6nv67p0ARsKas9QNnTQucpi08vNLtjQU='
[mod.'github.com/go-ole/go-ole']
version = 'v1.2.6'
hash = 'sha256-+oxitLeJxYF19Z6g+6CgmCHJ1Y5D8raMi2Cb3M6nXCs='
[mod.'github.com/google/uuid']
version = 'v1.6.0'
hash = 'sha256-VWl9sqUzdOuhW0KzQlv0gwwUQClYkmZwSydHG2sALYw='
[mod.'github.com/hashicorp/errwrap']
version = 'v1.1.0'
hash = 'sha256-6lwuMQOfBq+McrViN3maJTIeh4f8jbEqvLy2c9FvvFw='
[mod.'github.com/hashicorp/go-multierror']
version = 'v1.1.1'
hash = 'sha256-ANzPEUJIZIlToxR89Mn7Db73d9LGI51ssy7eNnUgmlA='
[mod.'github.com/hymkor/trash-go']
version = 'v0.2.0'
hash = 'sha256-p7zJYJpPjNAYKRNW7No+BXRemNabGp/No1mp9ItHXII='
[mod.'github.com/kdomanski/iso9660']
version = 'v0.3.3'
hash = 'sha256-iMyzZnZCKXUfBKJDdqwEYyzcFKo/VEkoo4Lm/Ct8tj4='
[mod.'github.com/klauspost/compress']
version = 'v1.16.3'
hash = 'sha256-dU0OgO5afQ1z5s83Y3w8Bg0ftvg+ikWbktUACEgY3OQ='
[mod.'github.com/lazysegtree/go-zoxide']
version = 'v0.1.0'
hash = 'sha256-PKEV+zCKf/7MsFAMMctL/pFSnEsri1yS8Bzxcj1dLWE='
[mod.'github.com/lithammer/shortuuid']
version = 'v3.0.0+incompatible'
hash = 'sha256-dD6ArCHGnpo84RBy6SI2kUjMqHS4IZU+K+DgAgmRakY='
[mod.'github.com/lucasb-eyer/go-colorful']
version = 'v1.3.0'
hash = 'sha256-6BKrJsfmxie+YFAWzTYVPQfrwjQEXRo+J8LY+50C1BU='
[mod.'github.com/mattn/go-colorable']
version = 'v0.1.13'
hash = 'sha256-qb3Qbo0CELGRIzvw7NVM1g/aayaz4Tguppk9MD2/OI8='
[mod.'github.com/mattn/go-isatty']
version = 'v0.0.20'
hash = 'sha256-qhw9hWtU5wnyFyuMbKx+7RB8ckQaFQ8D+8GKPkN3HHQ='
[mod.'github.com/mattn/go-localereader']
version = 'v0.0.1'
hash = 'sha256-JlWckeGaWG+bXK8l8WEdZqmSiTwCA8b1qbmBKa/Fj3E='
[mod.'github.com/mattn/go-runewidth']
version = 'v0.0.19'
hash = 'sha256-GpnbKplhX410Q/eIdknvWbYZgdav1keN+7wNUeOSMHE='
[mod.'github.com/muesli/ansi']
version = 'v0.0.0-20230316100256-276c6243b2f6'
hash = 'sha256-qRKn0Bh2yvP0QxeEMeZe11Vz0BPFIkVcleKsPeybKMs='
[mod.'github.com/muesli/cancelreader']
version = 'v0.2.2'
hash = 'sha256-uEPpzwRJBJsQWBw6M71FDfgJuR7n55d/7IV8MO+rpwQ='
[mod.'github.com/muesli/reflow']
version = 'v0.3.0'
hash = 'sha256-Pou2ybE9SFSZG6YfZLVV1Eyfm+X4FuVpDPLxhpn47Cc='
[mod.'github.com/muesli/termenv']
version = 'v0.16.0'
hash = 'sha256-hGo275DJlyLtcifSLpWnk8jardOksdeX9lH4lBeE3gI='
[mod.'github.com/nwaples/rardecode']
version = 'v1.1.3'
hash = 'sha256-X7Cg0kEygyy6Xw6sxRF9HirgefkH9tn9UPPelxRaAGg='
[mod.'github.com/pelletier/go-toml/v2']
version = 'v2.2.4'
hash = 'sha256-8qQIPldbsS5RO8v/FW/se3ZsAyvLzexiivzJCbGRg2Q='
[mod.'github.com/pierrec/lz4/v4']
version = 'v4.1.17'
hash = 'sha256-36L+GNhRrHBCyhbHCqweCk5rfmggdRtHqH6g5m1ViQI='
[mod.'github.com/pmezard/go-difflib']
version = 'v1.0.1-0.20181226105442-5d4384ee4fb2'
hash = 'sha256-XA4Oj1gdmdV/F/+8kMI+DBxKPthZ768hbKsO3d9Gx90='
[mod.'github.com/power-devops/perfstat']
version = 'v0.0.0-20240221224432-82ca36839d55'
hash = 'sha256-ujzuJ1ttQgjHQJEij4O/2+I8DZaUVZQCQgA4ysfqulI='
[mod.'github.com/reinhrst/fzf-lib']
version = 'v0.9.0'
hash = 'sha256-UUe5g+oXopDj+JjvzAguqJ70/a4pqZhn7pdJiFE97yI='
[mod.'github.com/rivo/uniseg']
version = 'v0.4.7'
hash = 'sha256-rDcdNYH6ZD8KouyyiZCUEy8JrjOQoAkxHBhugrfHjFo='
[mod.'github.com/rkoesters/xdg']
version = 'v0.0.1'
hash = 'sha256-+ckoKNaiEqQIpRFPr3CNRE3w8+OHmRKZ2cn6MquNIOE='
[mod.'github.com/rwcarlsen/goexif']
version = 'v0.0.0-20190401172101-9e8deecbddbd'
hash = 'sha256-AiY2T9hXj6jnfldYDoe4WNr3FldpVTxc3lScR++HOLc='
[mod.'github.com/shirou/gopsutil/v4']
version = 'v4.25.12'
hash = 'sha256-gzk9GW4+tXUWmxAVD3by/k4D/+l++TvajRVTkQJvwmM='
[mod.'github.com/stretchr/testify']
version = 'v1.11.1'
hash = 'sha256-sWfjkuKJyDllDEtnM8sb/pdLzPQmUYWYtmeWz/5suUc='
[mod.'github.com/ulikunitz/xz']
version = 'v0.5.15'
hash = 'sha256-L5KYLue5U14bxUuNyhZ6lIjbda6eCQsx1V6gToqfRdk='
[mod.'github.com/urfave/cli/v3']
version = 'v3.6.1'
hash = 'sha256-q1WeKEvWoSyA0Wcan+Edjm71e0/vnPmqVvlfjUix7+8='
[mod.'github.com/xo/terminfo']
version = 'v0.0.0-20220910002029-abceb7e1c41e'
hash = 'sha256-GyCDxxMQhXA3Pi/TsWXpA8cX5akEoZV7CFx4RO3rARU='
[mod.'github.com/yorukot/ansichroma']
version = 'v0.1.0'
hash = 'sha256-aIQZ16auuGfGLltKt2lm2T83f4sALrmRpOujxQepkS4='
[mod.'github.com/yusufpapurcu/wmi']
version = 'v1.2.4'
hash = 'sha256-N+YDBjOW59YOsZ2lRBVtFsEEi48KhNQRb63/0ZSU3bA='
[mod.'go4.org']
version = 'v0.0.0-20230225012048-214862532bf5'
hash = 'sha256-8y7krSESdxZfxTzo16EDqmF8USRzGmLPYr3iKuVYzzE='
[mod.'golang.org/x/exp']
version = 'v0.0.0-20231006140011-7918f672742d'
hash = 'sha256-2SO1etTQ6UCUhADR5sgvDEDLHcj77pJKCIa/8mGDbAo='
[mod.'golang.org/x/image']
version = 'v0.35.0'
hash = 'sha256-l9GP7N78XsAxe+LFUrBERp16SnerF7I5/WSTvHLGe2M='
[mod.'golang.org/x/mod']
version = 'v0.31.0'
hash = 'sha256-ZVNmaZADgM3+30q9rW8q4gP6ySkT7r1eb4vrHIlpCjM='
[mod.'golang.org/x/sys']
version = 'v0.38.0'
hash = 'sha256-1+i5EaG3JwH3KMtefzJLG5R6jbOeJM4GK3/LHBVnSy0='
[mod.'golang.org/x/term']
version = 'v0.18.0'
hash = 'sha256-lpze9arFZIhBV8Ht3VZyoiUwqPkeH2IwfXt8M3xljiM='
[mod.'golang.org/x/text']
version = 'v0.33.0'
hash = 'sha256-XdA6D39ESuJkaaM/SRBnqZzjKUwi6Gbt1Si1nvauTr4='
[mod.'golift.io/xtractr']
version = 'v0.2.2'
hash = 'sha256-ihKdIrWG1DKADjQ4X1AW62EGZWGgYU+9dY3g260bNOY='
[mod.'gopkg.in/yaml.v3']
version = 'v3.0.1'
hash = 'sha256-FqL9TKYJ0XkNwJFnq9j0VvJ5ZUU1RvH/52h/f5bkYAU='
================================================
FILE: main.go
================================================
package main
import (
"embed"
"github.com/yorukot/superfile/src/cmd"
)
var (
//go:embed src/superfile_config/*
content embed.FS
)
func main() {
cmd.Run(content)
}
================================================
FILE: release/release.sh
================================================
#!/usr/bin/env -S bash -euo pipefail
projectName="superfile"
version="v1.5.0"
osList=("darwin" "linux" "windows")
archList=("amd64" "arm64")
mkdir dist
# Prevent macOS from adding ._* files to archives
export COPYFILE_DISABLE=1
for os in "${osList[@]}"; do
if [ "$os" = "windows" ]; then
for arch in "${archList[@]}"; do
echo "$projectName-$os-$version-$arch"
mkdir "./dist/$projectName-$os-$version-$arch"
cd ../ || exit
env GOOS="$os" GOARCH="$arch" CGO_ENABLED=0 go build -o "./release/dist/$projectName-$os-$version-$arch/spf.exe" main.go
cd ./release || exit
zip -r "./dist/$projectName-$os-$version-$arch.zip" "./dist/$projectName-$os-$version-$arch"
done
else
for arch in "${archList[@]}"; do
echo "$projectName-$os-$version-$arch"
mkdir "./dist/$projectName-$os-$version-$arch"
cd ../ || exit
env GOOS="$os" GOARCH="$arch" CGO_ENABLED=0 go build -o "./release/dist/$projectName-$os-$version-$arch/spf" main.go
cd ./release || exit
tar czf "./dist/$projectName-$os-$version-$arch.tar.gz" "./dist/$projectName-$os-$version-$arch"
done
fi
done
================================================
FILE: release/release_check.md
================================================
- [ ] check all plugins is disable
- [ ] check update version and zip file
================================================
FILE: release/remove_all_spf_config.sh
================================================
#!/usr/bin/env bash
rm -r "$HOME/.config/superfile"
rm -r "$HOME/.local/state/superfile"
rm -r "$HOME/.local/share/superfile"
================================================
FILE: src/cmd/debug_info.go
================================================
package cmd
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"github.com/fatih/color"
"github.com/yorukot/superfile/src/pkg/utils"
variable "github.com/yorukot/superfile/src/config"
)
const (
keyWidth = 20
maxVersionLength = 50
)
type debugPrinter struct {
titleColor *color.Color
flagColor *color.Color
warningColor *color.Color
successColor *color.Color
}
func newDebugPrinter() *debugPrinter {
return &debugPrinter{
titleColor: color.New(color.FgGreen, color.Bold),
flagColor: color.New(color.FgCyan, color.Bold),
warningColor: color.New(color.FgRed, color.Bold),
successColor: color.New(color.FgGreen),
}
}
func printDebugInfo() {
dp := newDebugPrinter()
fmt.Println()
dp.printHeader("Superfile")
dp.printKeyValue("Version", variable.CurrentVersion+variable.PreReleaseSuffix)
fmt.Println()
dp.printHeader("System")
dp.printKeyValue("OS", runtime.GOOS)
dp.printKeyValue("Arch", runtime.GOARCH)
if kernel, err := getKernelVersion(); err == nil {
dp.printKeyValue("Kernel", kernel)
}
fmt.Println()
dp.printHeader("Configuration")
dp.printKeyValue("Config File", variable.ConfigFile)
dp.printKeyValue("Hotkeys File", variable.HotkeysFile)
dp.printKeyValue("Theme Folder", variable.ThemeFolder)
dp.printKeyValue("Log File", variable.LogFile)
dp.printKeyValue("Data Dir", variable.SuperFileDataDir)
fmt.Println()
dp.printHeader("Environment")
if runtime.GOOS == utils.OsWindows {
dp.printEnv("COMSPEC")
dp.printEnv("APPDATA")
dp.printEnv("LOCALAPPDATA")
} else {
dp.printEnv("TERM")
dp.printEnv("TERM_PROGRAM")
dp.printEnv("TERM_PROGRAM_VERSION")
dp.printEnv("SHELL")
dp.printEnv("EDITOR")
dp.printEnv("VISUAL")
dp.printEnv("XDG_SESSION_TYPE")
dp.printEnv("WAYLAND_DISPLAY")
dp.printEnv("DISPLAY")
}
fmt.Println()
dp.printHeader("Dependencies")
dp.checkDependency("ffmpeg", "-version")
dp.checkDependency("pdftoppm", "-v")
dp.checkDependency("exiftool", "-ver")
dp.checkDependency("bat", "--version")
dp.checkDependency("zoxide", "--version")
switch runtime.GOOS {
case utils.OsDarwin:
dp.checkDependency("open", "")
dp.checkDependency("pbcopy", "")
case utils.OsWindows:
dp.checkDependency("clip", "")
case utils.OsLinux:
dp.checkDependency("xdg-open", "--version")
dp.checkDependency("wl-copy", "--version")
dp.checkDependency("xclip", "-version")
dp.checkDependency("xsel", "--version")
}
}
func (dp *debugPrinter) printHeader(text string) {
_, _ = dp.titleColor.Add(color.Underline).Println(text)
}
func (dp *debugPrinter) printKeyValue(key, value string) {
if filepath.IsAbs(value) {
if _, err := os.Stat(value); os.IsNotExist(err) {
value = dp.warningColor.Sprint(value + " (Not Found)")
}
}
// Use fixed width formatting for key
keyStr := fmt.Sprintf("%-*s", keyWidth, key)
_, _ = dp.flagColor.Print(keyStr)
fmt.Printf(": %s\n", value)
}
func (dp *debugPrinter) printEnv(key string) {
val := os.Getenv(key)
if val == "" {
val = "Not Set"
}
dp.printKeyValue(key, val)
}
func (dp *debugPrinter) checkDependency(name string, flag string) {
path, err := exec.LookPath(name)
var status string
if err != nil {
status = dp.warningColor.Sprint("Not Found")
} else {
// Try to get version
version := "Found at " + path
if flag != "" {
//nolint:gosec // flags are hardcoded strings
cmd := exec.Command(name, strings.Split(flag, " ")...)
out, err := cmd.CombinedOutput()
if err == nil {
lines := strings.Split(string(out), "\n")
if len(lines) > 0 {
v := strings.TrimSpace(lines[0])
if len(v) > maxVersionLength {
v = v[:maxVersionLength] + "..."
}
if v != "" {
version = v
}
}
}
}
status = dp.successColor.Sprint(version)
}
keyStr := fmt.Sprintf("%-*s", keyWidth, name)
_, _ = dp.flagColor.Print(keyStr)
fmt.Printf(": %s\n", status)
}
func getKernelVersion() (string, error) {
if runtime.GOOS == utils.OsWindows {
cmd := exec.Command("cmd", "/c", "ver")
out, err := cmd.Output()
if err != nil {
return "", err
}
return strings.TrimSpace(string(out)), nil
}
out, err := exec.Command("uname", "-r").Output()
if err != nil {
return "", err
}
return strings.TrimSpace(string(out)), nil
}
================================================
FILE: src/cmd/help_printer.go
================================================
package cmd
import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/fatih/color"
"github.com/urfave/cli/v3"
)
// CustomHelpPrinter provides cargo-style colored help output for superfile CLI
func CustomHelpPrinter(w io.Writer, templ string, data interface{}) {
// Define color styles matching superfile's aesthetic
titleColor := color.New(color.FgGreen, color.Bold)
flagColor := color.New(color.FgCyan, color.Bold)
commandColor := color.New(color.FgBlue, color.Bold)
accentColor := color.New(color.FgMagenta, color.Bold)
switch v := data.(type) {
case *cli.Command:
// Get the actual binary name from os.Args[0]
binaryName := filepath.Base(os.Args[0])
printUsage(w, titleColor, accentColor, binaryName, v)
printCommands(w, titleColor, commandColor, v)
printFlags(w, titleColor, flagColor, v)
// Print version info if available
if v.Version != "" {
fmt.Printf("Version: ")
_, _ = accentColor.Fprintf(w, "%s\n\n", v.Version)
}
// Print help footer using the actual binary name
fmt.Fprint(w, "Use \"")
_, _ = accentColor.Fprintf(w, "%s", binaryName)
fmt.Fprint(w, " [COMMAND] --help\" for more information about a command.\n")
default:
// Fallback to default template rendering for other cases
cli.HelpPrinterCustom(w, templ, data, nil)
}
}
func printUsage(w io.Writer, titleColor *color.Color, accentColor *color.Color, binaryName string, v *cli.Command) {
_, _ = titleColor.Fprintf(w, "Usage:")
fmt.Fprint(w, " ")
_, _ = accentColor.Fprintf(w, "%s", binaryName)
if len(v.Commands) > 0 {
fmt.Fprint(w, " [COMMAND]")
}
if len(v.Flags) > 0 {
fmt.Fprint(w, " [OPTIONS]")
}
if v.ArgsUsage != "" {
fmt.Fprintf(w, " %s", v.ArgsUsage)
}
fmt.Fprintln(w)
fmt.Fprintln(w)
if v.Description != "" {
fmt.Fprintf(w, "%s\n\n", strings.TrimSpace(v.Description))
}
}
func printCommands(w io.Writer, titleColor *color.Color, commandColor *color.Color, v *cli.Command) {
if len(v.Commands) == 0 {
return
}
_, _ = titleColor.Fprintf(w, "Commands:\n")
for _, cmd := range v.Commands {
// Format command name with aliases
cmdDisplay := cmd.Name
if len(cmd.Aliases) > 0 {
cmdDisplay = fmt.Sprintf("%s, %s", cmd.Name, strings.Join(cmd.Aliases, ", "))
}
_, _ = commandColor.Fprintf(w, " %-20s", cmdDisplay)
fmt.Fprintf(w, " %s\n", cmd.Usage)
}
fmt.Fprintln(w)
}
func printFlags(w io.Writer, titleColor *color.Color, flagColor *color.Color, v *cli.Command) {
if len(v.Flags) == 0 {
return
}
_, _ = titleColor.Fprintf(w, "Options:\n")
for _, flag := range v.Flags {
names := flag.Names()
// Format flag names with proper prefixes and aliases
var flagParts []string
var valuePlaceholder string
var usage string
// Determine flag type, value placeholder, and usage in one switch
switch f := flag.(type) {
case *cli.BoolFlag:
// Boolean flags don't need values
valuePlaceholder = ""
usage = f.Usage
case *cli.StringFlag:
valuePlaceholder = " <value>"
usage = f.Usage
if f.Value != "" {
usage += fmt.Sprintf(" (default: %q)", f.Value)
}
case *cli.StringSliceFlag:
valuePlaceholder = " <value>..."
usage = f.Usage
case *cli.IntFlag:
valuePlaceholder = " <number>"
usage = f.Usage
if f.Value != 0 {
usage += fmt.Sprintf(" (default: %d)", f.Value)
}
default:
valuePlaceholder = " <value>"
usage = "No description available"
}
for _, name := range names {
if len(name) == 1 {
flagParts = append(flagParts, "-"+name)
} else {
flagParts = append(flagParts, "--"+name)
}
}
flagStr := strings.Join(flagParts, ", ") + valuePlaceholder
_, _ = flagColor.Fprintf(w, " %-30s", flagStr)
fmt.Fprintf(w, " %s\n", usage)
}
fmt.Fprintln(w)
}
================================================
FILE: src/cmd/main.go
================================================
package cmd
import (
"context"
"embed"
"encoding/json"
"fmt"
"io"
"log/slog"
"net/http"
"os"
"time"
"github.com/yorukot/superfile/src/internal/common"
"github.com/yorukot/superfile/src/pkg/utils"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/urfave/cli/v3"
"golang.org/x/mod/semver"
variable "github.com/yorukot/superfile/src/config"
internal "github.com/yorukot/superfile/src/internal"
)
// Run superfile app
func Run(content embed.FS) {
// Enable custom colored help output
cli.HelpPrinter = CustomHelpPrinter //nolint:reassign // Intentionally reassigning to customize help output
// Before we open log file, set all "non debug" logs to stdout
utils.SetRootLoggerToStdout(false)
common.LoadInitialPrerenderedVariables()
common.LoadAllDefaultConfig(content)
app := &cli.Command{
Name: "superfile",
Version: variable.CurrentVersion + variable.PreReleaseSuffix,
Description: "Pretty fancy and modern terminal file manager ",
ArgsUsage: "[PATH]...",
Commands: []*cli.Command{
{
Name: "path-list",
Aliases: []string{"pl"},
Usage: "Print the path to the configuration and directory",
Action: func(_ context.Context, c *cli.Command) error {
if c.Bool("lastdir-file") {
fmt.Println(variable.LastDirFile)
return nil
}
fmt.Printf("%-*s %s\n",
common.HelpKeyColumnWidth,
lipgloss.NewStyle().Foreground(lipgloss.Color("#66b2ff")).Render("[Configuration file path]"),
variable.ConfigFile,
)
fmt.Printf("%-*s %s\n",
common.HelpKeyColumnWidth,
lipgloss.NewStyle().Foreground(lipgloss.Color("#ffcc66")).Render("[Hotkeys file path]"),
variable.HotkeysFile,
)
logStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#66ff66"))
configStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#ff9999"))
dataStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#ff66ff"))
fmt.Printf("%-*s %s\n", common.HelpKeyColumnWidth,
logStyle.Render("[Log file path]"), variable.LogFile)
fmt.Printf("%-*s %s\n", common.HelpKeyColumnWidth,
configStyle.Render("[Configuration directory path]"), variable.SuperFileMainDir)
fmt.Printf("%-*s %s\n", common.HelpKeyColumnWidth,
dataStyle.Render("[Data directory path]"), variable.SuperFileDataDir)
return nil
},
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "lastdir-file",
Aliases: []string{"ld"},
Usage: "Print path to lastdir file (Where last dir is written when cd_on_quit config is true)",
Value: false,
},
},
},
},
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "debug-info",
Aliases: []string{"di"},
Usage: "Print debug information",
Value: false,
},
&cli.BoolFlag{
Name: "fix-hotkeys",
Aliases: []string{"fh"},
Usage: "Adds any missing hotkeys to the hotkey config file",
Value: false,
},
&cli.BoolFlag{
Name: "fix-config-file",
Aliases: []string{"fch"},
Usage: "Adds any missing hotkeys to the hotkey config file",
Value: false,
},
&cli.BoolFlag{
Name: "print-last-dir",
Aliases: []string{"pld"},
Usage: "Print the last dir to stdout on exit (to use for cd)",
Value: false,
},
&cli.StringFlag{
Name: "config-file",
Aliases: []string{"c"},
Usage: "Specify the path to a different config file",
Value: "", // Default to the blank string indicating non-usage of flag
},
&cli.StringFlag{
Name: "hotkey-file",
Aliases: []string{"hf"},
Usage: "Specify the path to a different hotkey file",
Value: "", // Default to the blank string indicating non-usage of flag
},
&cli.StringFlag{
Name: "chooser-file",
Aliases: []string{"cf"},
Usage: "On trying to open any file, superfile will write to its path to this file, and exit",
Value: "", // Default to the blank string indicating non-usage of flag
},
},
Action: spfAppAction,
}
err := app.Run(context.Background(), os.Args)
if err != nil {
utils.PrintlnAndExit(err)
}
}
func spfAppAction(_ context.Context, c *cli.Command) error {
variable.UpdateVarFromCliArgs(c)
if c.Bool("debug-info") {
printDebugInfo()
return nil
}
// If no args are called along with "spf" use current dir
firstPanelPaths := []string{""}
if c.Args().Present() {
firstPanelPaths = c.Args().Slice()
}
InitConfigFile()
firstUse := checkFirstUse()
p := tea.NewProgram(internal.InitialModel(firstPanelPaths, firstUse),
tea.WithAltScreen(), tea.WithMouseCellMotion())
if _, err := p.Run(); err != nil {
utils.PrintfAndExitf("Alas, there's been an error: %v", err)
}
// This must be after calling internal.InitialModel()
// so that we know `common.Config` is loaded
// Should not be a goroutine, Otherwise the main
// goroutine will exit first, and this will not be able to finish
CheckForUpdates()
if variable.PrintLastDir {
fmt.Println(variable.LastDir)
}
return nil
}
// Create proper directories for storing configuration and write default
// configurations to Config and Hotkeys toml
func InitConfigFile() {
// Create directories
if err := utils.CreateDirectories(
variable.SuperFileMainDir,
variable.SuperFileDataDir,
variable.SuperFileStateDir,
variable.ThemeFolder,
); err != nil {
utils.PrintlnAndExit("Error creating directories:", err)
}
// Create files
if err := utils.CreateFiles(
variable.ToggleDotFile,
variable.LogFile,
variable.ThemeFileVersion,
variable.ToggleFooter,
); err != nil {
utils.PrintlnAndExit("Error creating files:", err)
}
// Write config file
if err := writeConfigFile(variable.ConfigFile, common.ConfigTomlString); err != nil {
utils.PrintlnAndExit("Error writing config file:", err)
}
if err := writeConfigFile(variable.HotkeysFile, common.HotkeysTomlString); err != nil {
utils.PrintlnAndExit("Error writing config file:", err)
}
}
// Check if is the first time initializing the app, if it is create
// use check file
func checkFirstUse() bool {
file := variable.FirstUseCheck
firstUse := false
if _, err := os.Stat(file); os.IsNotExist(err) {
firstUse = true
if err = os.WriteFile(file, nil, utils.ConfigFilePerm); err != nil {
utils.PrintfAndExitf("Failed to create file: %v", err)
}
}
return firstUse
}
// Write data to the path file if it does not exists
func writeConfigFile(path, data string) error {
if _, err := os.Stat(path); os.IsNotExist(err) {
if err = os.WriteFile(path, []byte(data), utils.ConfigFilePerm); err != nil {
return fmt.Errorf("failed to write config file %s: %w", path, err)
}
}
return nil
}
func writeLastCheckTime(t time.Time) {
err := os.WriteFile(variable.LastCheckVersion, []byte(t.Format(time.RFC3339)), utils.ConfigFilePerm)
if err != nil {
slog.Error("Error writing LastCheckVersion file", "error", err)
}
}
// Check for the need of updates if AutoCheckUpdate is on, if its the first time
// that version is checked or if has more than 24h since the last version check,
// look into the repo if there's any more recent version
func CheckForUpdates() {
if !common.Config.AutoCheckUpdate {
return
}
currentTime := time.Now().UTC()
lastCheckTime := readLastCheckTime()
if !shouldCheckForUpdate(currentTime, lastCheckTime) {
return
}
defer writeLastCheckTime(currentTime)
checkAndNotifyUpdate()
}
// Default to zero time if file doesn't exist, is empty, or has errors
func readLastCheckTime() time.Time {
content, err := os.ReadFile(variable.LastCheckVersion)
if err != nil || len(content) == 0 {
return time.Time{}
}
parsedTime, parseErr := time.Parse(time.RFC3339, string(content))
if parseErr != nil {
slog.Error("Failed to parse LastCheckVersion timestamp", "error", parseErr)
return time.Time{}
}
return parsedTime.UTC()
}
func shouldCheckForUpdate(now, last time.Time) bool {
return last.IsZero() || now.Sub(last) >= 24*time.Hour
}
func checkAndNotifyUpdate() {
ctx, cancel := context.WithTimeout(context.Background(), common.DefaultCLIContextTimeout)
defer cancel()
resp, err := fetchLatestRelease(ctx)
if err != nil {
slog.Error("Failed to fetch update", "error", err)
return
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
slog.Error("Failed to read update response", "error", err)
return
}
type GitHubRelease struct {
TagName string `json:"tag_name"`
}
var release GitHubRelease
if err := json.Unmarshal(body, &release); err != nil {
slog.Error("Failed to parse GitHub JSON", "error", err)
return
}
if semver.Compare(release.TagName, variable.CurrentVersion) > 0 {
notifyUpdateAvailable(release.TagName)
}
}
func fetchLatestRelease(ctx context.Context) (*http.Response, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, variable.LatestVersionURL, nil)
if err != nil {
return nil, err
}
return (&http.Client{}).Do(req)
}
func notifyUpdateAvailable(latest string) {
fmt.Println(
lipgloss.NewStyle().Foreground(lipgloss.Color("#FF69E1")).Render("┃ ") +
lipgloss.NewStyle().Foreground(lipgloss.Color("#FFBA52")).Bold(true).Render("A new version ") +
lipgloss.NewStyle().Foreground(lipgloss.Color("#00FFF2")).Bold(true).Italic(true).Render(latest) +
lipgloss.NewStyle().Foreground(lipgloss.Color("#FFBA52")).Bold(true).Render(" is available."),
)
fmt.Printf(
lipgloss.NewStyle().Foreground(lipgloss.Color("#FF69E1")).Render("┃ ")+"Please update.\n┏\n\n => %s\n\n",
variable.LatestVersionGithub,
)
fmt.Println(" ┛")
}
================================================
FILE: src/config/fixed_variable.go
================================================
package variable
import (
"os"
"path/filepath"
"github.com/urfave/cli/v3"
"github.com/yorukot/superfile/src/pkg/utils"
"github.com/adrg/xdg"
)
const (
CurrentVersion = "v1.5.0"
// Allowing pre-releases with non production version
// Set this to "" for production releases
PreReleaseSuffix = ""
// This gives most recent non-prerelease, non-draft release
LatestVersionURL = "https://api.github.com/repos/yorukot/superfile/releases/latest"
LatestVersionGithub = "github.com/yorukot/superfile/releases/latest"
// This will not break in windows. This is a relative path for Embed FS. It uses "/" only
EmbedConfigDir = "src/superfile_config"
EmbedConfigFile = EmbedConfigDir + "/config.toml"
EmbedHotkeysFile = EmbedConfigDir + "/hotkeys.toml"
EmbedThemeDir = EmbedConfigDir + "/theme"
EmbedThemeCatppuccinFile = EmbedThemeDir + "/catppuccin-mocha.toml"
)
var (
HomeDir = xdg.Home
SuperFileMainDir = filepath.Join(xdg.ConfigHome, "superfile")
SuperFileCacheDir = filepath.Join(xdg.CacheHome, "superfile")
SuperFileDataDir = filepath.Join(xdg.DataHome, "superfile")
SuperFileStateDir = filepath.Join(xdg.StateHome, "superfile")
// MainDir files
ThemeFolder = filepath.Join(SuperFileMainDir, "theme")
// DataDir files
LastCheckVersion = filepath.Join(SuperFileDataDir, "lastCheckVersion")
ThemeFileVersion = filepath.Join(SuperFileDataDir, "themeFileVersion")
FirstUseCheck = filepath.Join(SuperFileDataDir, "firstUseCheck")
PinnedFile = filepath.Join(SuperFileDataDir, "pinned.json")
ToggleDotFile = filepath.Join(SuperFileDataDir, "toggleDotFile")
ToggleFooter = filepath.Join(SuperFileDataDir, "toggleFooter")
// StateDir files
LogFile = filepath.Join(SuperFileStateDir, "superfile.log")
LastDirFile = filepath.Join(SuperFileStateDir, "lastdir")
// Trash Directories
DarwinTrashDirectory = filepath.Join(HomeDir, ".Trash")
// These are used by github.com/rkoesters/xdg/trash package
// We need to make sure that these directories exist
LinuxTrashDirectory = filepath.Join(xdg.DataHome, "Trash")
LinuxTrashDirectoryFiles = filepath.Join(xdg.DataHome, "Trash", "files")
LinuxTrashDirectoryInfo = filepath.Join(xdg.DataHome, "Trash", "info")
)
// These variables are actually not fixed, they are sometimes updated dynamically
var (
ConfigFile = filepath.Join(SuperFileMainDir, "config.toml")
HotkeysFile = filepath.Join(SuperFileMainDir, "hotkeys.toml")
// ChooserFile is the path where superfile will write the file's path, which is to be
// opened, before exiting
ChooserFile = ""
// Other state variables
FixHotkeys = false
FixConfigFile = false
LastDir = ""
PrintLastDir = false
)
// Still we are preventing other packages to directly modify them via reassign linter
func SetLastDir(path string) {
LastDir = path
}
func SetChooserFile(path string) {
ChooserFile = path
}
func UpdateVarFromCliArgs(c *cli.Command) {
// Setting the config file path
configFileArg := c.String("config-file")
// Validate the config file exists
if configFileArg != "" {
if _, err := os.Stat(configFileArg); err != nil {
utils.PrintfAndExitf("Error: While reading config file '%s' from argument : %v", configFileArg, err)
}
ConfigFile = configFileArg
}
hotkeyFileArg := c.String("hotkey-file")
if hotkeyFileArg != "" {
if _, err := os.Stat(hotkeyFileArg); err != nil {
utils.PrintfAndExitf("Error: While reading hotkey file '%s' from argument : %v", hotkeyFileArg, err)
}
HotkeysFile = hotkeyFileArg
}
// It could be non existent. We are writing to the file. If file doesn't exists, we would attempt to create it.
SetChooserFile(c.String("chooser-file"))
FixHotkeys = c.Bool("fix-hotkeys")
FixConfigFile = c.Bool("fix-config-file")
PrintLastDir = c.Bool("print-last-dir")
}
================================================
FILE: src/config/icon/function.go
================================================
package icon
// InitIcon initializes the icon configuration for the application.
// It sets up different icons based on whether nerd fonts are enabled and configures directory icon colors.
//
// Parameters:
// - nerdfont: boolean flag to determine if nerd fonts should be used
// When false, uses simple ASCII characters for icons
// When true, uses nerd font icons (default behavior)
// - directoryIconColor: string representing the color for directory icons
// If empty, defaults to "NONE" (dark yellowish)
//
// The function configures various icons for:
// - System directories (Home, Download, Documents, etc.)
// - File operations (Compress, Extract, Copy, Cut, Delete)
// - UI elements (Cursor, Browser, Select, etc.)
// - Status indicators (Error, Warn, Done, InOperation)
// - Navigation and sorting (Directory, Search, SortAsc, SortDesc)
func InitIcon(nerdfont bool, directoryIconColor string) {
// Make sure that these alternatives are ASCII characters only.
// Dont place any special unicode characters here.
if !nerdfont {
// When nerdfont is disabled, we use simple ASCII characters
// Space is set to empty string because we don't need special spacing
// for ASCII characters, unlike nerd fonts which often need proper spacing
// to display correctly
Space = ""
SuperfileIcon = ""
Home = ""
Download = ""
Documents = ""
Pictures = ""
Videos = ""
Music = ""
Templates = ""
PublicShare = ""
// file operations
CompressFile = ""
ExtractFile = ""
Copy = ""
Cut = ""
Delete = ""
// other
Cursor = ">"
Browser = "B"
Select = "S"
Error = ""
Warn = ""
Done = ""
InOperation = ""
Directory = ""
Search = ""
SortAsc = "^"
SortDesc = "v"
Terminal = ""
Pinned = ""
Disk = ""
}
if directoryIconColor == "" {
directoryIconColor = "NONE" // Dark yellowish
}
Folders["folder"] = Style{
Icon: "\uf07b", // Printable Rune : ""
Color: directoryIconColor,
}
}
func GetCopyOrCutIcon(cut bool) string {
if cut {
return Cut
}
return Copy
}
================================================
FILE: src/config/icon/icon.go
================================================
package icon
// Style for icons
type Style struct {
Icon string
Color string
}
var (
Space = " "
SuperfileIcon = "\ue6ad" // Printable Rune : ""
// Well Known Directories
Home = "\U000f02dc" // Printable Rune : ""
Download = "\U000f03d4" // Printable Rune : ""
Documents = "\U000f0219" // Printable Rune : ""
Pictures = "\U000f02e9" // Printable Rune : ""
Videos = "\U000f0381" // Printable Rune : ""
Music = "♬" // Printable Rune : "♬"
Templates = "\U000f03e2" // Printable Rune : ""
PublicShare = "\uf0ac" // Printable Rune : ""
Trash = "\uf1f8" // Printable Rune : ""
// file operations
CompressFile = "\U000f05c4" // Printable Rune : ""
ExtractFile = "\U000f06eb" // Printable Rune : ""
Copy = "\U000f018f" // Printable Rune : ""
Cut = "\U000f0190" // Printable Rune : ""
Delete = "\U000f01b4" // Printable Rune : ""
// other
Cursor = "\uf054" // Printable Rune : ""
Browser = "\U000f0208" // Printable Rune : ""
Select = "\U000f01bd" // Printable Rune : ""
CheckboxEmpty = "\U000f0131" // Printable Rune : ""
CheckboxChecked = "\U000f0856" // Printable Rune : ""
Error = "\uf530" // Printable Rune : ""
Warn = "\uf071" // Printable Rune : ""
Done = "\uf4a4" // Printable Rune : ""
InOperation = "\U000f0954" // Printable Rune : ""
Directory = "\uf07b" // Printable Rune : ""
Search = "\ue68f" // Printable Rune : ""
SortAsc = "\uf0de" // Printable Rune : ""
SortDesc = "\uf0dd" // Printable Rune : ""
Terminal = "\ue795" // Printable Rune : ""
Pinned = "\U000f0403" // Printable Rune : ""
Disk = "\U000f11f0" // Printable Rune : ""
)
/*
THESE CODE BASE ON https://github.com/acarl005/ls-go
thanks for the great work!!
*/
var Icons = map[string]Style{
"ai": {Icon: "\ue669", Color: "#ce6f14"}, // Printable Rune : ""
"android": {Icon: "\uf17b", Color: "#a7c83f"}, // Printable Rune : ""
"apple": {Icon: "\ue711", Color: "#78909c"}, // Printable Rune : ""
"asm": {Icon: "\U000f061a", Color: "#ff7844"}, // Printable Rune : ""
"audio": {Icon: "\uf001", Color: "#ee524f"}, // Printable Rune : ""
"binary": {Icon: "\uf471", Color: "#ff7844"}, // Printable Rune : ""
"c": {Icon: "\ue649", Color: "#0188d2"}, // Printable Rune : ""
"cfg": {Icon: "\ue615", Color: "#8B8B8B"}, // Printable Rune : ""
"clj": {Icon: "\ue76a", Color: "#68b338"}, // Printable Rune : ""
"conf": {Icon: "\ue615", Color: "#8B8B8B"}, // Printable Rune : ""
"cpp": {Icon: "\ue646", Color: "#0188d2"}, // Printable Rune : ""
"css": {Icon: "\uf13c", Color: "#2d53e5"}, // Printable Rune : ""
"dart": {Icon: "\ue64c", Color: "#03589b"}, // Printable Rune : ""
"db": {Icon: "\uf1c0", Color: "#FF8400"}, // Printable Rune : ""
"deb": {Icon: "\ue77d", Color: "#ab0836"}, // Printable Rune : ""
"doc": {Icon: "\ue6a5", Color: "#295394"}, // Printable Rune : ""
"dockerfile": {Icon: "\U000f0868", Color: "#099cec"}, // Printable Rune : ""
"ebook": {Icon: "\uf02d", Color: "#67b500"}, // Printable Rune : ""
"env": {Icon: "\uf462", Color: "#eed645"}, // Printable Rune : ""
"f": {Icon: "\U000f121a", Color: "#8e44ad"}, // Printable Rune : ""
"file": {Icon: "\uf15b", Color: "NONE"}, // Printable Rune : ""
"font": {Icon: "\uf031", Color: "#3498db"}, // Printable Rune : ""
"fs": {Icon: "\ue7a7", Color: "#2ecc71"}, // Printable Rune : ""
"gb": {Icon: "\ue272", Color: "#f1c40f"}, // Printable Rune : ""
"gform": {Icon: "\uf298", Color: "#9b59b6"}, // Printable Rune : ""
"git": {Icon: "\ue702", Color: "#e67e22"}, // Printable Rune : ""
"go": {Icon: "\ue627", Color: "#6ed8e5"}, // Printable Rune : ""
"graphql": {Icon: "\ue662", Color: "#e74c3c"}, // Printable Rune : ""
"glp": {Icon: "\U000f01a7", Color: "#3498db"}, // Printable Rune : ""
"groovy": {Icon: "\ue775", Color: "#2ecc71"}, // Printable Rune : ""
"gruntfile.js": {Icon: "\ue74c", Color: "#3498db"}, // Printable Rune : ""
"gulpfile.js": {Icon: "\ue610", Color: "#e67e22"}, // Printable Rune : ""
"gv": {Icon: "\ue225", Color: "#9b59b6"}, // Printable Rune : ""
"h": {Icon: "\uf0fd", Color: "#3498db"}, // Printable Rune : ""
"haml": {Icon: "\ue664", Color: "#9b59b6"}, // Printable Rune : ""
"hs": {Icon: "\ue777", Color: "#2980b9"}, // Printable Rune : ""
"html": {Icon: "\uf13b", Color: "#e67e22"}, // Printable Rune : ""
"hx": {Icon: "\ue666", Color: "#e74c3c"}, // Printable Rune : ""
"ics": {Icon: "\uf073", Color: "#f1c40f"}, // Printable Rune : ""
"image": {Icon: "\uf1c5", Color: "#e74c3c"}, // Printable Rune : ""
"iml": {Icon: "\ue7b5", Color: "#3498db"}, // Printable Rune : ""
"ini": {Icon: "\U000f016a", Color: "#f1c40f"}, // Printable Rune : ""
"ino": {Icon: "\ue255", Color: "#2ecc71"}, // Printable Rune : ""
"iso": {Icon: "\U000f02ca", Color: "#f1c40f"}, // Printable Rune : ""
"jade": {Icon: "\ue66c", Color: "#9b59b6"}, // Printable Rune : ""
"java": {Icon: "\ue738", Color: "#e67e22"}, // Printable Rune : ""
"jenkinsfile": {Icon: "\ue767", Color: "#e74c3c"}, // Printable Rune : ""
"jl": {Icon: "\ue624", Color: "#2ecc71"}, // Printable Rune : ""
"js": {Icon: "\ue781", Color: "#f39c12"}, // Printable Rune : ""
"json": {Icon: "\ue60b", Color: "#f1c40f"}, // Printable Rune : ""
"jsx": {Icon: "\ue7ba", Color: "#e67e22"}, // Printable Rune : ""
"key": {Icon: "\uf43d", Color: "#f1c40f"}, // Printable Rune : ""
"ko": {Icon: "\uebc6", Color: "#9b59b6"}, // Printable Rune : ""
"kt": {Icon: "\ue634", Color: "#2980b9"}, // Printable Rune : ""
"less": {Icon: "\ue758", Color: "#3498db"}, // Printable Rune : ""
"link_file": {Icon: "\uf481", Color: "NONE"}, // Printable Rune : ""
"lock": {Icon: "\uf023", Color: "#f1c40f"}, // Printable Rune : ""
"log": {Icon: "\uf18d", Color: "#7f8c8d"}, // Printable Rune : ""
"lua": {Icon: "\ue620", Color: "#e74c3c"}, // Printable Rune : ""
"maintainers": {Icon: "\uf0c0", Color: "#7f8c8d"}, // Printable Rune : ""
"makefile": {Icon: "\ue20f", Color: "#3498db"}, // Printable Rune : ""
"md": {Icon: "\uf48a", Color: "#7f8c8d"}, // Printable Rune : ""
"mjs": {Icon: "\ue718", Color: "#f39c12"}, // Printable Rune : ""
"ml": {Icon: "\U000f0627", Color: "#2ecc71"}, // Printable Rune : ""
"mustache": {Icon: "\ue60f", Color: "#e67e22"}, // Printable Rune : ""
"nc": {Icon: "\U000f02c1", Color: "#f1c40"}, // Printable Rune : ""
"nim": {Icon: "\ue677", Color: "#3498db"}, // Printable Rune : ""
"nix": {Icon: "\uf313", Color: "#f39c12"}, // Printable Rune : ""
"npmignore": {Icon: "\ue71e", Color: "#e74c3c"}, // Printable Rune : ""
"package": {Icon: "\U000f03d7", Color: "#9b59b6"}, // Printable Rune : ""
"passwd": {Icon: "\uf023", Color: "#f1c40f"}, // Printable Rune : ""
"patch": {Icon: "\uf440", Color: "#e67e22"}, // Printable Rune : ""
"pdf": {Icon: "\uf1c1", Color: "#d35400"}, // Printable Rune : ""
"php": {Icon: "\ue608", Color: "#9b59b6"}, // Printable Rune : ""
"pl": {Icon: "\ue7a1", Color: "#3498db"}, // Printable Rune : ""
"prisma": {Icon: "\ue684", Color: "#9b59b6"}, // Printable Rune : ""
"ppt": {Icon: "\uf1c4", Color: "#c0392b"}, // Printable Rune : ""
"psd": {Icon: "\ue7b8", Color: "#3498db"}, // Printable Rune : ""
"py": {Icon: "\ue606", Color: "#3498db"}, // Printable Rune : ""
"r": {Icon: "\ue68a", Color: "#9b59b6"}, // Printable Rune : ""
"rb": {Icon: "\ue21e", Color: "#9b59b6"}, // Printable Rune : ""
"rdb": {Icon: "\ue76d", Color: "#9b59b6"}, // Printable Rune : ""
"rpm": {Icon: "\uf17c", Color: "#d35400"}, // Printable Rune : ""
"rs": {Icon: "\ue7a8", Color: "#f39c12"}, // Printable Rune : ""
"rss": {Icon: "\uf09e", Color: "#c0392b"}, // Printable Rune : ""
"rst": {Icon: "\U000f016b", Color: "#2ecc71"}, // Printable Rune : ""
"rubydoc": {Icon: "\ue73b", Color: "#e67e22"}, // Printable Rune : ""
"sass": {Icon: "\ue603", Color: "#e74c3c"}, // Printable Rune : ""
"scala": {Icon: "\ue737", Color: "#e67e22"}, // Printable Rune : ""
"shell": {Icon: "\uf489", Color: "#2ecc71"}, // Printable Rune : ""
"shp": {Icon: "\U000f065e", Color: "#f1c40f"}, // Printable Rune : ""
"sol": {Icon: "\U000f086a", Color: "#3498db"}, // Printable Rune : ""
"sqlite": {Icon: "\ue7c4", Color: "#27ae60"}, // Printable Rune : ""
"styl": {Icon: "\ue600", Color: "#e74c3c"}, // Printable Rune : ""
"svelte": {Icon: "\ue697", Color: "#ff3e00"}, // Printable Rune : ""
"swift": {Icon: "\ue755", Color: "#ff6f61"}, // Printable Rune : ""
"tex": {Icon: "\u222b", Color: "#9b59b6"}, // Printable Rune : "∫"
"tf": {Icon: "\ue69a", Color: "#2ecc71"}, // Printable Rune : ""
"toml": {Icon: "\U000f016a", Color: "#f39c12"}, // Printable Rune : ""
"ts": {Icon: "\U000f06e6", Color: "#2980b9"}, // Printable Rune : ""
"twig": {Icon: "\ue61c", Color: "#9b59b6"}, // Printable Rune : ""
"txt": {Icon: "\uf15c", Color: "#7f8c8d"}, // Printable Rune : ""
"vagrantfile": {Icon: "\ue21e", Color: "#3498db"}, // Printable Rune : ""
"video": {Icon: "\uf03d", Color: "#c0392b"}, // Printable Rune : ""
"vim": {Icon: "\ue62b", Color: "#019833"}, // Printable Rune : ""
"vue": {Icon: "\ue6a0", Color: "#41b883"}, // Printable Rune : ""
"windows": {Icon: "\uf17a", Color: "#4a90e2"}, // Printable Rune : ""
"xls": {Icon: "\uf1c3", Color: "#27ae60"}, // Printable Rune : ""
"xml": {Icon: "\ue796", Color: "#3498db"}, // Printable Rune : ""
"yml": {Icon: "\ue601", Color: "#f39c12"}, // Printable Rune : ""
"zig": {Icon: "\ue6a9", Color: "#9b59b6"}, // Printable Rune : ""
"zip": {Icon: "\uf410", Color: "#e74c3c"}, // Printable Rune : ""
}
var Aliases = map[string]string{
"dart": "dart",
"apk": "android",
"gradle": "android",
"ds_store": "apple",
"localized": "apple",
"m": "apple",
"mm": "apple",
"s": "asm",
"aac": "audio",
"alac": "audio",
"flac": "audio",
"m4a": "audio",
"mka": "audio",
"mp3": "audio",
"ogg": "audio",
"opus": "audio",
"wav": "audio",
"wma": "audio",
"bson": "binary",
"feather": "binary",
"mat": "binary",
"o": "binary",
"pb": "binary",
"pickle": "binary",
"pkl": "binary",
"tfrecord": "binary",
"conf": "cfg",
"config": "cfg",
"cljc": "clj",
"cljs": "clj",
"editorconfig": "conf",
"rc": "conf",
"c++": "cpp",
"cc": "cpp",
"cxx": "cpp",
"scss": "css",
"sql": "db",
"docx": "doc",
"gdoc": "doc",
"dockerignore": "dockerfile",
"epub": "ebook",
"ipynb": "ebook",
"mobi": "ebook",
"env": "env",
".env.local": "env",
"local": "env",
"f03": "f",
"f77": "f",
"f90": "f",
"f95": "f",
"for": "f",
"fpp": "f",
"ftn": "f",
"eot": "font",
"otf": "font",
"ttf": "font",
"woff": "font",
"woff2": "font",
"fsi": "fs",
"fsscript": "fs",
"fsx": "fs",
"dna": "gb",
"gitattributes": "git",
"gitconfig": "git",
"gitignore": "git",
"gitignore_global": "git",
"gitmirrorall": "git",
"gitmodules": "git",
"gltf": "glp",
"gsh": "groovy",
"gvy": "groovy",
"gy": "groovy",
"h++": "h",
"hh": "h",
"hpp": "h",
"hxx": "h",
"lhs": "hs",
"htm": "html",
"xhtml": "html",
"bmp": "image",
"cbr": "image",
"cbz": "image",
"dvi": "image",
"eps": "image",
"gif": "image",
"ico": "image",
"jpeg": "image",
"jpg": "image",
"nef": "image",
"orf": "image",
"pbm": "image",
"pgm": "image",
"png": "image",
"pnm": "image",
"ppm": "image",
"pxm": "image",
"sixel": "image",
"stl": "image",
"svg": "image",
"tif": "image",
"tiff": "image",
"webp": "image",
"xpm": "image",
"disk": "iso",
"dmg": "iso",
"img": "iso",
"ipsw": "iso",
"smi": "iso",
"vhd": "iso",
"vhdx": "iso",
"vmdk": "iso",
"jar": "java",
"kts": "kt",
"cjs": "js",
"properties": "json",
"webmanifest": "json",
"tsx": "jsx",
"cjsx": "jsx",
"cer": "key",
"crt": "key",
"der": "key",
"gpg": "key",
"p7b": "key",
"pem": "key",
"pfx": "key",
"pgp": "key",
"license": "key",
"codeowners": "maintainers",
"credits": "maintainers",
"cmake": "makefile",
"justfile": "makefile",
"markdown": "md",
"mkd": "md",
"rdoc": "md",
"readme": "md",
"mli": "ml",
"sml": "ml",
"netcdf": "nc",
"brewfile": "package",
"cargo.toml": "package",
"cargo.lock": "package",
"go.mod": "package",
"go.sum": "package",
"pyproject.toml": "package",
"poetry.lock": "package",
"package.json": "package",
"pipfile": "package",
"pipfile.lock": "package",
"php3": "php",
"php4": "php",
"php5": "php",
"phpt": "php",
"phtml": "php",
"gslides": "ppt",
"pptx": "ppt",
"pxd": "py",
"pyc": "py",
"pyx": "py",
"whl": "py",
"rdata": "r",
"rds": "r",
"rmd": "r",
"gemfile": "rb",
"gemspec": "rb",
"guardfile": "rb",
"procfile": "rb",
"rakefile": "rb",
"rspec": "rb",
"rspec_parallel": "rb",
"rspec_status": "rb",
"ru": "rb",
"erb": "rubydoc",
"slim": "rubydoc",
"awk": "shell",
"bash": "shell",
"bash_history": "shell",
"bash_profile": "shell",
"bashrc": "shell",
"csh": "shell",
"fish": "shell",
"ksh": "shell",
"sh": "shell",
"zsh": "shell",
"zsh-theme": "shell",
"zshrc": "shell",
"plpgsql": "sql",
"plsql": "sql",
"psql": "sql",
"tsql": "sql",
"sl3": "sqlite",
"sqlite3": "sqlite",
"stylus": "styl",
"cls": "tex",
"avi": "video",
"flv": "video",
"m2v": "video",
"mkv": "video",
"mov": "video",
"mp4": "video",
"mpeg": "video",
"mpg": "video",
"ogm": "video",
"ogv": "video",
"vob": "video",
"webm": "video",
"vimrc": "vim",
"bat": "windows",
"cmd": "windows",
"exe": "windows",
"csv": "xls",
"gsheet": "xls",
"xlsx": "xls",
"plist": "xml",
"xul": "xml",
"yaml": "yml",
"7z": "zip",
"Z": "zip",
"bz2": "zip",
"gz": "zip",
"lzma": "zip",
"par": "zip",
"rar": "zip",
"tar": "zip",
"tc": "zip",
"tgz": "zip",
"txz": "zip",
"xz": "zip",
"z": "zip",
}
var Folders = map[string]Style{
".atom": {Icon: "\ue764", Color: "#66595c"}, // Atom folder - Dark gray // Printable Rune : ""
".aws": {Icon: "\ue7ad", Color: "#ff9900"}, // AWS folder - Orange // Printable Rune : ""
".docker": {Icon: "\ue7b0", Color: "#0db7ed"}, // Docker folder - Blue // Printable Rune : ""
".gem": {Icon: "\ue21e", Color: "#e9573f"}, // Gem folder - Red // Printable Rune : ""
".git": {Icon: "\ue5fb", Color: "#f14e32"}, // Git folder - Red // Printable Rune : ""
".git-credential-cache": {
Icon: "\ue5fb",
Color: "#f14e32",
}, // Git credential cache folder - Red // Printable Rune : ""
".github": {Icon: "\ue5fd", Color: "#000000"}, // GitHub folder - Black // Printable Rune : ""
".npm": {Icon: "\ue5fa", Color: "#cb3837"}, // npm folder - Red // Printable Rune : ""
".nvm": {Icon: "\ue718", Color: "#cb3837"}, // nvm folder - Red // Printable Rune : ""
".rvm": {Icon: "\ue21e", Color: "#e9573f"}, // rvm folder - Red // Printable Rune : ""
".Trash": {Icon: "\uf1f8", Color: "#7f8c8d"}, // Trash folder - Light gray // Printable Rune : ""
".vscode": {Icon: "\ue70c", Color: "#007acc"}, // VSCode folder - Blue // Printable Rune : ""
".vim": {Icon: "\ue62b", Color: "#019833"}, // Vim folder - Green // Printable Rune : ""
"config": {Icon: "\ue5fc", Color: "#ffb86c"}, // Config folder - Light orange // Printable Rune : ""
// Item for Generic folder, with key "folder" is initialized in InitIcon()
"hidden": {Icon: "\uf023", Color: "#75715e"}, // Hidden folder - Dark yellowish // Printable Rune : ""
"node_modules": {Icon: "\ue5fa", Color: "#cb3837"}, // Node modules folder - Red // Printable Rune : ""
"link_folder": {Icon: "\uf482", Color: "NONE"}, // link folder - None // Printable Rune : ""
"superfile": {Icon: "\U000f069d", Color: "#FF6F00"}, // Printable Rune : ""
}
================================================
FILE: src/internal/backend/README.md
================================================
# Backend Package
Handles operations on the User's OS.
For example, executing shell commands, performing file operations on user's files...
Reading OS-specific configurations like disk partitions.
The name 'backend' isn't the most appropriate, open to suggestions.
This would modularize the code, and would enable us to write unit tests
where we would 'mock' the backend functionality with dummy interface
implementations
# Dependencies
Should not import any "ui" package
Can import common and its subpackages
# Implementation specifications
Try to implement everything via interfaces, so that we can easily write unit tests
================================================
FILE: src/internal/common/README.md
================================================
# common package
Defines common utilities for ui and file operations package
everyone can use common package, but common package should not have any dependency on
any other package. Currently, common package is a big monolith, but we plan to separate it into config,
# Dependencies
- src/config package
================================================
FILE: src/internal/common/config_type.go
================================================
package common
// Theme configuration
type ThemeType struct {
// Code syntax highlight theme
CodeSyntaxHighlightTheme string `toml:"code_syntax_highlight"`
// Border
FilePanelBorder string `toml:"file_panel_border"`
SidebarBorder string `toml:"sidebar_border"`
FooterBorder string `toml:"footer_border"`
// Border Active
FilePanelBorderActive string `toml:"file_panel_border_active"`
SidebarBorderActive string `toml:"sidebar_border_active"`
FooterBorderActive string `toml:"footer_border_active"`
ModalBorderActive string `toml:"modal_border_active"`
// Background (bg)
FullScreenBG string `toml:"full_screen_bg"`
FilePanelBG string `toml:"file_panel_bg"`
SidebarBG string `toml:"sidebar_bg"`
FooterBG string `toml:"footer_bg"`
ModalBG string `toml:"modal_bg"`
// Foreground (fg)
FullScreenFG string `toml:"full_screen_fg"`
FilePanelFG string `toml:"file_panel_fg"`
SidebarFG string `toml:"sidebar_fg"`
FooterFG string `toml:"footer_fg"`
ModalFG string `toml:"modal_fg"`
// Special Color
Cursor string `toml:"cursor"`
Correct string `toml:"correct"`
Error string `toml:"error"`
Hint string `toml:"hint"`
Cancel string `toml:"cancel"`
// Note: this is linked with `RequiredGradientColorCount` constant
GradientColor []string `toml:"gradient_color"`
DirectoryIconColor string `toml:"directory_icon_color"`
// File Panel Special Items
FilePanelTopDirectoryIcon string `toml:"file_panel_top_directory_icon"`
FilePanelTopPath string `toml:"file_panel_top_path"`
FilePanelItemSelectedFG string `toml:"file_panel_item_selected_fg"`
FilePanelItemSelectedBG string `toml:"file_panel_item_selected_bg"`
// Sidebar Special Items
SidebarTitle string `toml:"sidebar_title"`
SidebarItemSelectedFG string `toml:"sidebar_item_selected_fg"`
SidebarItemSelectedBG string `toml:"sidebar_item_selected_bg"`
SidebarDivider string `toml:"sidebar_divider"`
// Modal Special Items
ModalCancelFG string `toml:"modal_cancel_fg"`
ModalCancelBG string `toml:"modal_cancel_bg"`
ModalConfirmFG string `toml:"modal_confirm_fg"`
ModalConfirmBG string `toml:"modal_confirm_bg"`
HelpMenuHotkey string `toml:"help_menu_hotkey"`
HelpMenuTitle string `toml:"help_menu_title"`
}
// Configuration settings
type ConfigType struct {
Theme string `toml:"theme" comment:"More details are at https://superfile.dev/configure/superfile-config/\nchange your theme"`
Editor string `toml:"editor" comment:"\nThe editor files will be opened with. (Leave blank to use the EDITOR environment variable)."`
DirEditor string `toml:"dir_editor" comment:"\nThe editor directories will be opened with. (Leave blank to use the default editors)."`
// The table (map) for editor by file extension
OpenWith map[string]string `toml:"open_with" comment:"\nCustom open commands by file extension."`
AutoCheckUpdate bool `toml:"auto_check_update" comment:"\nAuto check for update"`
CdOnQuit bool `toml:"cd_on_quit" comment:"\nCd on quit (For more details, please check out https://superfile.dev/configure/superfile-config/#cd_on_quit)"`
DefaultOpenFilePreview bool `toml:"default_open_file_preview" comment:"\nWhether to open file preview automatically every time superfile is opened."`
ShowImagePreview bool `toml:"show_image_preview" comment:"\nWhether to show image preview."`
ShowPanelFooterInfo bool `toml:"show_panel_footer_info" comment:"\nWhether to show additional footer info for file panel."`
DefaultDirectory string `toml:"default_directory" comment:"\nThe path of the first file panel when superfile is opened."`
FileSizeUseSI bool `toml:"file_size_use_si" comment:"\nDisplay file sizes using powers of 1000 (kB, MB, GB) instead of powers of 1024 (KiB, MiB, GiB)."`
DefaultSortType int `toml:"default_sort_type" comment:"\nDefault sort type (0: Name, 1: Size, 2: Date Modified, 3: Type, 4: Natural)."`
SortOrderReversed bool `toml:"sort_order_reversed" comment:"\nDefault sort order (false: Ascending, true: Descending)."`
CaseSensitiveSort bool `toml:"case_sensitive_sort" comment:"\nCase sensitive sort by name (capital \"B\" comes before \"a\" if true)."`
ShellCloseOnSuccess bool `toml:"shell_close_on_success" comment:"\nWhether to close the shell on successful command execution."`
Debug bool `toml:"debug" comment:"\nWhether to enable debug mode."`
// IgnoreMissingFields controls whether warnings about missing TOML fields are suppressed.
IgnoreMissingFields bool `toml:"ignore_missing_fields" comment:"\nWhether to ignore warnings about missing fields in the config file."`
PageScrollSize int `toml:"page_scroll_size" comment:"\nNumber of lines to scroll for PgUp/PgDown keys (0: full page, default behavior)."`
FilePanelExtraColumns int `toml:"file_panel_extra_columns" comment:"\nCount of extra columns in file panel in addition to file name. When option equal 0 then feature is disabled."`
FilePanelNamePercent int `toml:"file_panel_name_percent" comment:"\nPercentage of file panel width allocated to file names (25-100). Higher values give more space to names, less to extra columns."`
Nerdfont bool `toml:"nerdfont" comment:"\n================ Style =================\n\n If you don't have or don't want Nerdfont installed you can turn this off"`
ShowSelectIcons bool `toml:"show_select_icons" comment:"\nShow checkbox icons in select mode (requires nerdfont)"`
TransparentBackground bool `toml:"transparent_background" comment:"\nSet transparent background or not (this only work when your terminal background is transparent)"`
FilePreviewWidth int `toml:"file_preview_width" comment:"\nFile preview width allow '0' (this mean same as file panel),'x' x must be less than 10 and greater than 1 (This means that the width of the file preview will be one xth of the total width.)"`
EnableFilePreviewBorder bool `toml:"enable_file_preview_border" comment:"\nEnable border around the file preview panel (default: false)"`
CodePreviewer string `toml:"code_previewer" comment:"\nWhether to use the builtin syntax highlighting with chroma or use bat. Values: \"\" for builtin chroma, \"bat\" for bat"`
SidebarWidth int `toml:"sidebar_width" comment:"\nThe length of the sidebar(excluding borders). If you don't find to display the sidebar, you can input 0 directly. If you want to display the value, please place it in the range of 5-20."`
SidebarSections []string `toml:"sidebar_sections" comment:"\nOrder of sidebar sections (valid values: \"home\", \"pinned\", \"disks\").\nOnly sections included in this list will be displayed."`
BorderTop string `toml:"border_top" comment:"\nBorder style"`
BorderBottom string `toml:"border_bottom"`
BorderLeft string `toml:"border_left"`
BorderRight string `toml:"border_right"`
BorderTopLeft string `toml:"border_top_left"`
BorderTopRight string `toml:"border_top_right"`
BorderBottomLeft string `toml:"border_bottom_left"`
BorderBottomRight string `toml:"border_bottom_right"`
BorderMiddleLeft string `toml:"border_middle_left"`
BorderMiddleRight string `toml:"border_middle_right"`
Metadata bool `toml:"metadata" comment:"\n==========PLUGINS========== #\nPlugins means that you need to install some external dependencies to use them.\n\nShow more detailed metadata, please install exiftool before enabling this plugin!"`
EnableMD5Checksum bool `toml:"enable_md5_checksum" comment:"Enable MD5 checksum generation for files"`
ZoxideSupport bool `toml:"zoxide_support" comment:"Zoxide support for the fast navigation"`
}
// GetIgnoreMissingFields reports whether warnings about missing TOML fields should be ignored.
func (c *ConfigType) GetIgnoreMissingFields() bool {
return c.IgnoreMissingFields
}
type HotkeysType struct {
Confirm []string `toml:"confirm" comment:"=================================================================================================\nGlobal hotkeys (cannot conflict with other hotkeys)"`
Quit []string `toml:"quit"`
CdQuit []string `toml:"cd_quit"`
// movement
ListUp []string `toml:"list_up" comment:"movement"`
ListDown []string `toml:"list_down"`
PageUp []string `toml:"page_up"`
PageDown []string `toml:"page_down"`
CloseFilePanel []string `toml:"close_file_panel" comment:"file panel control"`
CreateNewFilePanel []string `toml:"create_new_file_panel"`
SplitFilePanel []string `toml:"split_file_panel"`
NextFilePanel []string `toml:"next_file_panel"`
PreviousFilePanel []string `toml:"previous_file_panel"`
ToggleFilePreviewPanel []string `toml:"toggle_file_preview_panel"`
OpenSortOptionsMenu []string `toml:"open_sort_options_menu"`
ToggleReverseSort []string `toml:"toggle_reverse_sort"`
FocusOnProcessBar []string `toml:"focus_on_process_bar" comment:"change focus"`
FocusOnSidebar []string `toml:"focus_on_sidebar"`
FocusOnMetaData []string `toml:"focus_on_metadata"`
FilePanelItemCreate []string `toml:"file_panel_item_create" comment:"create file/directory and rename "`
FilePanelItemRename []string `toml:"file_panel_item_rename"`
CopyItems []string `toml:"copy_items" comment:"file operate"`
PasteItems []string `toml:"paste_items"`
CutItems []string `toml:"cut_items"`
DeleteItems []string `toml:"delete_items"`
PermanentlyDeleteItems []string `toml:"permanently_delete_items"`
ExtractFile []string `toml:"extract_file" comment:"compress and extract"`
CompressFile []string `toml:"compress_file"`
OpenFileWithEditor []string `toml:"open_file_with_editor" comment:"editor"`
OpenCurrentDirectoryWithEditor []string `toml:"open_current_directory_with_editor"`
PinnedDirectory []string `toml:"pinned_directory" comment:"other"`
ToggleDotFile []string `toml:"toggle_dot_file"`
ChangePanelMode []string `toml:"change_panel_mode"`
OpenHelpMenu []string `toml:"open_help_menu"`
OpenCommandLine []string `toml:"open_command_line"`
OpenSPFPrompt []string `toml:"open_spf_prompt"`
OpenZoxide []string `toml:"open_zoxide"`
CopyPath []string `toml:"copy_path"`
CopyPWD []string `toml:"copy_present_working_directory"`
ToggleFooter []string `toml:"toggle_footer"`
ConfirmTyping []string `toml:"confirm_typing" comment:"=================================================================================================\nTyping hotkeys (can conflict with all hotkeys)"`
CancelTyping []string `toml:"cancel_typing"`
ParentDirectory []string `toml:"parent_directory" comment:"=================================================================================================\nNormal mode hotkeys (can conflict with other modes, cannot conflict with global hotkeys)"`
SearchBar []string `toml:"search_bar"`
FilePanelSelectModeItemsSelectDown []string `toml:"file_panel_select_mode_items_select_down" comment:"=================================================================================================\nSelect mode hotkeys (can conflict with other modes, cannot conflict with global hotkeys)"`
FilePanelSelectModeItemsSelectUp []string `toml:"file_panel_select_mode_items_select_up"`
FilePanelSelectAllItem []string `toml:"file_panel_select_all_items"`
}
================================================
FILE: src/internal/common/default_config.go
================================================
package common
// Variables for holding default configurations of each settings
var (
HotkeysTomlString string
ConfigTomlString string
DefaultThemeString string
)
var Theme ThemeType
var Config ConfigType
var Hotkeys HotkeysType
================================================
FILE: src/internal/common/icon_utils.go
================================================
package common
import (
"path/filepath"
"strings"
"github.com/yorukot/superfile/src/config/icon"
)
func getFileIcon(file string, isLink bool) icon.Style {
if isLink {
return icon.Icons["link_file"]
}
ext := strings.TrimPrefix(filepath.Ext(file), ".")
// default icon for all files. try to find a better one though...
resultIcon := icon.Icons["file"]
// resolve aliased extensions
extKey := strings.ToLower(ext)
alias, hasAlias := icon.Aliases[extKey]
if hasAlias {
extKey = alias
}
// see if we can find a better icon based on extension alone
betterIcon, hasBetterIcon := icon.Icons[extKey]
if hasBetterIcon {
resultIcon = betterIcon
}
// now look for icons based on full names
fullName := file
fullName = strings.ToLower(fullName)
fullAlias, hasFullAlias := icon.Aliases[fullName]
if hasFullAlias {
fullName = fullAlias
}
bestIcon, hasBestIcon := icon.Icons[fullName]
if hasBestIcon {
resultIcon = bestIcon
}
if resultIcon.Color == "NONE" {
return icon.Style{
Icon: resultIcon.Icon,
Color: Theme.FilePanelFG,
}
}
return resultIcon
}
func GetElementIcon(file string, isDir bool, isLink bool, nerdFont bool) icon.Style {
if !nerdFont {
return icon.Style{
Icon: "",
Color: Theme.FilePanelFG,
}
}
if isDir {
if isLink {
return icon.Folders["link_folder"]
}
resultIcon := icon.Folders["folder"]
betterIcon, hasBetterIcon := icon.Folders[file]
if hasBetterIcon {
resultIcon = betterIcon
}
return resultIcon
}
return getFileIcon(file, isLink)
}
================================================
FILE: src/internal/common/icon_utils_test.go
================================================
package common
import (
"testing"
"github.com/yorukot/superfile/src/config/icon"
)
func TestGetElementIcon(t *testing.T) {
tests := []struct {
name string
file string
isDir bool
isLink bool
nerdFont bool
expected icon.Style
}{
{
name: "Non-nerdfont returns empty icon",
file: "test.txt",
isDir: false,
isLink: false,
nerdFont: false,
expected: icon.Style{
Icon: "",
Color: Theme.FilePanelFG,
},
},
{
name: "Directory with nerd font",
file: "folder",
isDir: true,
isLink: false,
nerdFont: true,
expected: icon.Folders["folder"],
},
{
name: "File with known extension",
file: "test.js",
isDir: false,
isLink: false,
nerdFont: true,
expected: icon.Icons["js"],
},
{
name: "Full name takes priority over extension",
file: "gulpfile.js",
isDir: false,
isLink: false,
nerdFont: true,
expected: icon.Icons["gulpfile.js"],
},
{
name: ".git directory",
file: ".git",
isDir: true,
isLink: false,
nerdFont: true,
expected: icon.Folders[".git"],
},
{
name: "superfile directory",
file: "superfile",
isDir: true,
isLink: false,
nerdFont: true,
expected: icon.Folders["superfile"],
},
{
name: "package.json file",
file: "package.json",
isDir: false,
isLink: false,
nerdFont: true,
expected: icon.Icons["package"],
},
{
name: "File with unknown extension",
file: "test.xyz",
isDir: false,
isLink: false,
nerdFont: true,
expected: icon.Style{
Icon: icon.Icons["file"].Icon,
// Theme is not defined here, so this will be blank
Color: Theme.FilePanelFG,
},
},
{
name: "File with aliased name",
file: "dockerfile",
isDir: false,
isLink: false,
nerdFont: true,
expected: icon.Icons["dockerfile"],
},
{
name: "Link to Directory with nerd font",
file: "folder",
isDir: true,
isLink: true,
nerdFont: true,
expected: icon.Folders["link_folder"],
},
{
name: "Link to File",
file: "test.js",
isDir: false,
isLink: true,
nerdFont: true,
expected: icon.Icons["link_file"],
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := GetElementIcon(tt.file, tt.isDir, tt.isLink, tt.nerdFont)
if result.Icon != tt.expected.Icon || result.Color != tt.expected.Color {
t.Errorf("GetElementIcon() = %v, want %v", result, tt.expected)
}
})
}
}
================================================
FILE: src/internal/common/load_config.go
================================================
package common
import (
"embed"
"errors"
"fmt"
"log/slog"
"os"
"path/filepath"
"reflect"
"runtime"
"github.com/charmbracelet/x/ansi"
"github.com/pelletier/go-toml/v2"
"github.com/yorukot/superfile/src/pkg/utils"
variable "github.com/yorukot/superfile/src/config"
"github.com/yorukot/superfile/src/config/icon"
)
// Load configurations from the configuration file. Compares the content
// with the default values and modify the config file to include default configs
// if the FixConfigFile flag is on
// TODO : Fix the code duplication with LoadHotkeysFile().
func LoadConfigFile() {
err := utils.LoadTomlFile(variable.ConfigFile, ConfigTomlString, &Config, variable.FixConfigFile, false)
if err != nil {
userMsg := fmt.Sprintf("%s%s", LipglossError, err.Error())
toExit := true
var loadError *utils.TomlLoadError
if errors.As(err, &loadError) && loadError != nil {
if loadError.MissingFields() && !variable.FixConfigFile {
// Had missing fields and we did not fix
userMsg += "\nTo add missing fields to configuration file automatically run superfile " +
"with the --fix-config-file flag `spf --fix-config-file`"
}
toExit = loadError.IsFatal()
}
if toExit {
utils.PrintfAndExitf("%s\n", userMsg)
} else {
fmt.Println(userMsg)
}
}
// Even if there is a missing field, we want to validate fields that are present
if err := ValidateConfig(&Config); err != nil {
// If config is incorrect we cannot continue. We need to exit
utils.PrintlnAndExit(err.Error())
}
}
func ValidateConfig(c *ConfigType) error {
if (c.FilePreviewWidth > 10 || c.FilePreviewWidth < 2) && c.FilePreviewWidth != 0 {
return errors.New(
LoadConfigError("file_preview_width", "File preview width must be 2–10, or 0 to disable preview."),
)
}
if c.SidebarWidth != 0 && (c.SidebarWidth < 5 || c.SidebarWidth > 20) {
return errors.New(LoadConfigError("sidebar_width", "Sidebar width must be 5–20, or 0 to hide the sidebar."))
}
for _, order := range c.SidebarSections {
if order != utils.SidebarSectionHome &&
order != utils.SidebarSectionPinned &&
order != utils.SidebarSectionDisks {
return errors.New(
LoadConfigError(
"sidebar_sections",
"Sidebar sections contain an unsupported value. Allowed values are: home, pinned, disks.",
),
)
}
}
if c.DefaultSortType < 0 || c.DefaultSortType > 4 {
return errors.New(LoadConfigError("default_sort_type", "Default sort type must be between 0 and 4."))
}
if c.FilePanelNamePercent < FileNameRatioMin || c.FilePanelNamePercent > FileNameRatioMax {
return errors.New(
LoadConfigError("file_panel_name_percent", "File panel name percent is outside the supported range."),
)
}
if ansi.StringWidth(c.BorderTop) != 1 {
return errors.New(LoadConfigError("border_top", "Border character must be exactly one cell wide."))
}
return validateBorders(c)
}
func validateBorders(c *ConfigType) error {
if ansi.StringWidth(c.BorderBottom) != 1 {
return errors.New(LoadConfigError("border_bottom", "Border character must be exactly one cell wide."))
}
if ansi.StringWidth(c.BorderLeft) != 1 {
return errors.New(LoadConfigError("border_left", "Border character must be exactly one cell wide."))
}
if ansi.StringWidth(c.BorderRight) != 1 {
return errors.New(LoadConfigError("border_right", "Border character must be exactly one cell wide."))
}
if ansi.StringWidth(c.BorderBottomLeft) != 1 {
return errors.New(LoadConfigError("border_bottom_left", "Border character must be exactly one cell wide."))
}
if ansi.StringWidth(c.BorderBottomRight) != 1 {
return errors.New(LoadConfigError("border_bottom_right", "Border character must be exactly one cell wide."))
}
if ansi.StringWidth(c.BorderTopLeft) != 1 {
return errors.New(LoadConfigError("border_top_left", "Border character must be exactly one cell wide."))
}
if ansi.StringWidth(c.BorderTopRight) != 1 {
return errors.New(LoadConfigError("border_top_right", "Border character must be exactly one cell wide."))
}
if ansi.StringWidth(c.BorderMiddleLeft) != 1 {
return errors.New(LoadConfigError("border_middle_left", "Border character must be exactly one cell wide."))
}
if ansi.StringWidth(c.BorderMiddleRight) != 1 {
return errors.New(LoadConfigError("border_middle_right", "Border character must be exactly one cell wide."))
}
return nil
}
// Load keybinds from the hotkeys file. Compares the content
// with the default values and modify the hotkeys if the FixHotkeys flag is on.
func LoadHotkeysFile(ignoreMissingFields bool) {
err := utils.LoadTomlFile(
variable.HotkeysFile,
HotkeysTomlString,
&Hotkeys,
variable.FixHotkeys,
ignoreMissingFields,
)
if err != nil {
userMsg := fmt.Sprintf("%s%s", LipglossError, err.Error())
toExit := true
var loadError *utils.TomlLoadError
if errors.As(err, &loadError) {
if loadError.MissingFields() && !variable.FixHotkeys {
// Had missing fields and we did not fix
userMsg += "\nTo add missing fields to hotkeys file automatically run superfile " +
"with the --fix-hotkeys flag `spf --fix-hotkeys`"
}
toExit = loadError.IsFatal()
}
if toExit {
utils.PrintfAndExitf("%s\n", userMsg)
} else {
fmt.Println(userMsg)
}
}
// Validate hotkey values
val := reflect.ValueOf(Hotkeys)
for i := range val.NumField() {
field := val.Type().Field(i)
value := val.Field(i)
// Although this is redundant as Hotkey is always a slice
// This adds a layer against accidental struct modifications
// Makes sure its always be a string slice. It's somewhat like a unit test
if value.Kind() != reflect.Slice || value.Type().Elem().Kind() != reflect.String {
utils.PrintlnAndExit(
LoadHotkeysError(
field.Name,
"Hotkey value must be a list of strings.",
),
)
}
hotkeysList, ok := value.Interface().([]string)
if !ok || len(hotkeysList) == 0 || hotkeysList[0] == "" {
utils.PrintlnAndExit(
LoadHotkeysError(
field.Name,
"Hotkey list is empty; at least one key binding is required.",
),
)
}
}
}
// LoadThemeFile : Load configurations from theme file into &theme
// set default values if we cant read user's theme file
func LoadThemeFile() {
themeFile := filepath.Join(variable.ThemeFolder, Config.Theme+".toml")
if err := LoadUserTheme(themeFile, &Theme); err != nil {
slog.Error("Could not read user's theme file. Falling back to default theme", "error", err)
err = toml.Unmarshal([]byte(DefaultThemeString), &Theme)
if err != nil {
utils.PrintfAndExitf("Unexpected error while reading default theme file : %v. Exiting...", err)
}
}
// Validations
if len(Theme.GradientColor) != RequiredGradientColorCount {
utils.PrintlnAndExit(
LoadThemeError(
"gradient_color",
"Gradient color must contain exactly two values.",
),
)
}
}
func LoadUserTheme(themeFile string, obj *ThemeType) error {
data, err := os.ReadFile(themeFile)
if err != nil {
return fmt.Errorf("could not read user's theme file(%s), err : %w", themeFile, err)
}
if err = toml.Unmarshal(data, obj); err != nil {
return fmt.Errorf("could not unmarshal user's theme file(%s) : %w", themeFile, err)
}
return nil
}
// LoadAllDefaultConfig : Load all default configurations from embedded superfile_config folder into global
// configurations variables and write theme files if its needed.
func LoadAllDefaultConfig(content embed.FS) {
err := LoadConfigStringGlobals(content)
if err != nil {
slog.Error("Could not load default config from embed FS", "error", err)
return
}
currentThemeVersion, err := os.ReadFile(variable.ThemeFileVersion)
if err != nil && !os.IsNotExist(err) {
slog.Error("Unexpected error reading from file:", "error", err)
return
}
if string(currentThemeVersion) == variable.CurrentVersion {
// We don't need to update themes as its already up to date
return
}
// Write theme files to theme directory
err = WriteThemeFiles(content)
if err != nil {
slog.Error("Error while writing default theme directories", "error", err)
return
}
// Prevent failure for first time app run by making sure parent directories exists
if err = os.MkdirAll(filepath.Dir(variable.ThemeFileVersion), utils.ConfigDirPerm); err != nil {
slog.Error("Error creating theme file parent directory", "error", err)
return
}
err = os.WriteFile(variable.ThemeFileVersion, []byte(variable.CurrentVersion), utils.ConfigFilePerm)
if err != nil {
slog.Error("Error writing theme file version", "error", err)
}
}
func LoadConfigStringGlobals(content embed.FS) error {
hotkeyData, err := content.ReadFile(variable.EmbedHotkeysFile)
if err != nil {
return err
}
HotkeysTomlString = string(hotkeyData)
configData, err := content.ReadFile(variable.EmbedConfigFile)
if err != nil {
return err
}
ConfigTomlString = string(configData)
themeData, err := content.ReadFile(variable.EmbedThemeCatppuccinFile)
if err != nil {
return err
}
DefaultThemeString = string(themeData)
return nil
}
func WriteThemeFiles(content embed.FS) error {
_, err := os.Stat(variable.ThemeFolder)
if os.IsNotExist(err) {
if err = os.MkdirAll(variable.ThemeFolder, utils.ConfigDirPerm); err != nil {
slog.Error("Error creating theme directory", "error", err)
return err
}
}
files, err := content.ReadDir(variable.EmbedThemeDir)
if err != nil {
slog.Error("Error reading theme directory from embed", "error", err)
return err
}
for _, file := range files {
if file.IsDir() {
continue
}
// This will not break in windows. This is a relative path for Embed FS. It uses "/" only
src, err := content.ReadFile(variable.EmbedThemeDir + "/" + file.Name())
if err != nil {
slog.Error("Error reading theme file from embed", "error", err)
return err
}
curThemeFile, err := os.Create(filepath.Join(variable.ThemeFolder, file.Name()))
if err != nil {
slog.Error("Error creating theme file from embed", "error", err)
return err
}
defer curThemeFile.Close()
_, err = curThemeFile.Write(src)
if err != nil {
slog.Error("Error writing theme file from embed", "error", err)
return err
}
}
return nil
}
// Used only in unit tests
// Populate config variables based on given file
func PopulateGlobalConfigs() error {
_, filename, _, ok := runtime.Caller(0)
if !ok {
return errors.New("failed to determine source file location")
}
// This is src/internal/common/load_config.go
// we want src/superfile_config
spfConfigDir := filepath.Join(filepath.Dir(filepath.Dir(filepath.Dir(filename))),
"superfile_config")
configFilePath := filepath.Join(spfConfigDir, "config.toml")
hotkeyFilePath := filepath.Join(spfConfigDir, "hotkeys.toml")
themeFilePath := filepath.Join(spfConfigDir, "theme", "monokai.toml")
err := PopulateConfigFromFile(configFilePath)
if err != nil {
return err
}
err = PopulateHotkeyFromFile(hotkeyFilePath)
if err != nil {
return err
}
err = PopulateThemeFromFile(themeFilePath)
if err != nil {
return err
}
// Populate fixed variables
LoadInitialPrerenderedVariables()
icon.InitIcon(Config.Nerdfont, Theme.DirectoryIconColor)
LoadPrerenderedVariables()
return nil
}
// No validation required
func populateFromFile(filePath string, target interface{}) error {
data, err := os.ReadFile(filePath)
if err != nil {
return err
}
err = toml.Unmarshal(data, target)
if err != nil {
return err
}
return nil
}
func PopulateConfigFromFile(configFilePath string) error {
return populateFromFile(configFilePath, &Config)
}
func PopulateHotkeyFromFile(hotkeyFilePath string) error {
return populateFromFile(hotkeyFilePath, &Hotkeys)
}
func PopulateThemeFromFile(themeFilePath string) error {
return populateFromFile(themeFilePath, &Theme)
}
func InitTrash() bool {
// Create trash directories
if runtime.GOOS != utils.OsLinux {
return true
}
err := utils.CreateDirectories(
variable.LinuxTrashDirectory,
variable.LinuxTrashDirectoryFiles,
variable.LinuxTrashDirectoryInfo,
)
if err != nil {
slog.Warn("Failed to initialize XDG trash; falling back to permanent delete",
"error", err, "trashDir", variable.LinuxTrashDirectory)
return false
}
return true
}
================================================
FILE: src/internal/common/predefined_variable.go
================================================
package common
import (
"time"
"github.com/charmbracelet/lipgloss"
"github.com/yorukot/superfile/src/config/icon"
)
const (
WheelRunTime = 5
DefaultCommandTimeout = 5000 * time.Millisecond
DateModifiedOption = "Date Modified"
InvalidTypeString = "InvalidType"
)
const (
SameRenameWarnTitle = "There is already a file or directory with that name"
SameRenameWarnContent = "This operation will override the existing file"
)
const (
TrashWarnTitle = "Are you sure you want to move this to trash can"
TrashWarnContent = "This operation will move file or directory to trash can."
PermanentDeleteWarnTitle = "Are you sure you want to completely delete"
PermanentDeleteWarnContent = "This operation cannot be undone and your data will be completely lost."
)
const (
MinimumHeight = 24
MinimumWidth = 60
// TODO : These are model object properties, not global properties
// We are modifying them in the code many time. They need to be part of model struct.
MinFooterHeight = 6
ModalWidth = 60
ModalHeight = 7
)
var (
SideBarSuperfileTitle string
SideBarHomeDivider string
SideBarPinnedDivider string
SideBarDisksDivider string
SideBarNoneText string
ProcessBarNoneText string
ClipboardNoneText string
FilePanelTopDirectoryIcon string
FilePanelNoneText string
FilePreviewNoFileInfoText string
FilePreviewNoContentText string
FilePreviewUnsupportedFormatText string
FilePreviewUnsupportedFileMode string
FilePreviewDirectoryUnreadableText string
FilePreviewEmptyText string
FilePreviewError string
FilePreviewPanelClosedText string
FilePreviewImagePreviewDisabledText string
FilePreviewUnsupportedImageFormatsText string
FilePreviewImageConversionErrorText string
FilePreviewBatNotInstalledText string
FilePreviewThumbnailGenerationErrorText string
CheckboxChecked string
CheckboxCheckedFocused string
CheckboxEmpty string
CheckboxEmptyFocused string
ModalConfirmInputText string
ModalCancelInputText string
ModalOkayInputText string
ModalInputSpacingText string
LipglossError string
)
var (
UnsupportedPreviewFormats = []string{".torrent"}
ImageExtensions = map[string]bool{
".jpg": true,
".jpeg": true,
".png": true,
".gif": true,
".bmp": true,
".tiff": true,
".svg": true,
".webp": true,
".ico": true,
}
VideoExtensions = map[string]bool{
".mkv": true,
".mp4": true,
".mov": true,
".avi": true,
".flv": true,
".webm": true,
".wmv": true,
".m4v": true,
".mpeg": true,
".3gp": true,
".ogv": true,
}
)
// No dependencies
func LoadInitialPrerenderedVariables() {
LipglossError = lipgloss.NewStyle().Foreground(lipgloss.Color("#F93939")).Render("Error") +
lipgloss.NewStyle().Foreground(lipgloss.Color("#00FFEE")).Render(" ┃ ")
}
// This should be used only after InitIcon() has been called.
func wrapFilePreviewErrorMsg(msg string) string {
return "\n--- " + icon.Error + icon.Space + msg + " ---"
}
// Dependecies - TODO We should programmatically guarantee these dependencies. And log error
// if its not satisfied.
// LoadThemeConfig() in style.go should be finished
// loadConfigFile() in config_types.go should be finished
// InitIcon() in config package in function.go should be finished
func LoadPrerenderedVariables() {
SideBarSuperfileTitle = SidebarTitleStyle.Render(" " + icon.SuperfileIcon + icon.Space + "superfile")
SideBarHomeDivider = SidebarTitleStyle.Render(icon.Home+icon.Space+"Home") +
SidebarDividerStyle.Render(" ─────────────")
SideBarPinnedDivider = SidebarTitleStyle.Render(icon.Pinned+icon.Space+"Pinned") +
SidebarDividerStyle.Render(" ───────────")
SideBarDisksDivider = SidebarTitleStyle.Render(icon.Disk+icon.Space+"Disks") +
SidebarDividerStyle.Render(" ────────────")
SideBarNoneText = SidebarStyle.Render(" " + icon.Error + icon.Space + "None")
ProcessBarNoneText = icon.Error + icon.Space + "No processes running"
ClipboardNoneText = " " + icon.Error + icon.Space + " No content in clipboard"
FilePanelTopDirectoryIcon = FilePanelTopDirectoryIconStyle.Render(" " + icon.Directory + icon.Space)
FilePanelNoneText = FilePanelStyle.Render(" " + icon.Error + icon.Space + "No such file or directory")
FilePreviewNoContentText = wrapFilePreviewErrorMsg(
"No content to preview")
FilePreviewNoFileInfoText = wrapFilePreviewErrorMsg(
"Could not get file info")
FilePreviewUnsupportedFormatText = wrapFilePreviewErrorMsg(
"Unsupported formats")
FilePreviewUnsupportedFileMode = wrapFilePreviewErrorMsg(
"Unsupported File Mode")
FilePreviewDirectoryUnreadableText = wrapFilePreviewErrorMsg(
"Cannot read directory")
FilePreviewError = wrapFilePreviewErrorMsg(
"Error")
FilePreviewEmptyText = wrapFilePreviewErrorMsg(
"Empty")
FilePreviewPanelClosedText = wrapFilePreviewErrorMsg(
"Preview panel is closed")
FilePreviewImagePreviewDisabledText = wrapFilePreviewErrorMsg(
"Image preview is disabled")
FilePreviewUnsupportedImageFormatsText = wrapFilePreviewErrorMsg(
"Unsupported image formats")
FilePreviewImageConversionErrorText = wrapFilePreviewErrorMsg(
"Error convert image to ansi")
FilePreviewBatNotInstalledText = wrapFilePreviewErrorMsg(
"'bat' is not installed or not found")
FilePreviewThumbnailGenerationErrorText = wrapFilePreviewErrorMsg(
"Thumbnail generation failed")
CheckboxChecked = FilePanelSelectBoxStyle.
Foreground(FilePanelBorderColor).
Render(icon.CheckboxChecked + icon.Space)
CheckboxCheckedFocused = FilePanelSelectBoxStyle.
Foreground(FilePanelBorderActiveColor).
Render(icon.CheckboxChecked + icon.Space)
CheckboxEmpty = FilePanelSelectBoxSty
gitextract_l20rs_yr/
├── .envrc
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ ├── enhancement-suggestion.md
│ │ └── feature_request.md
│ ├── PULL_REQUEST_TEMPLATE/
│ │ └── pull_request_template.md
│ ├── renovate.json
│ └── workflows/
│ ├── first-interaction.yml
│ ├── lint-pr-title.yml
│ ├── mirror.yml
│ ├── superfile-build-test.yml
│ ├── testsuite-run.yml
│ ├── update-gomod2nix.yml
│ └── winget.yml
├── .gitignore
├── .golangci.yaml
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── README.md
├── asset/
│ └── spf.desktop
├── build.sh
├── cd_on_quit/
│ ├── cd_on_quit.fish
│ ├── cd_on_quit.ps1
│ └── cd_on_quit.sh
├── dev.sh
├── flake.nix
├── go.mod
├── go.sum
├── gomod2nix.toml
├── main.go
├── release/
│ ├── release.sh
│ ├── release_check.md
│ └── remove_all_spf_config.sh
├── src/
│ ├── cmd/
│ │ ├── debug_info.go
│ │ ├── help_printer.go
│ │ └── main.go
│ ├── config/
│ │ ├── fixed_variable.go
│ │ └── icon/
│ │ ├── function.go
│ │ └── icon.go
│ ├── internal/
│ │ ├── backend/
│ │ │ └── README.md
│ │ ├── common/
│ │ │ ├── README.md
│ │ │ ├── config_type.go
│ │ │ ├── default_config.go
│ │ │ ├── icon_utils.go
│ │ │ ├── icon_utils_test.go
│ │ │ ├── load_config.go
│ │ │ ├── predefined_variable.go
│ │ │ ├── string_function.go
│ │ │ ├── string_function_test.go
│ │ │ ├── style.go
│ │ │ ├── style_function.go
│ │ │ ├── type.go
│ │ │ └── ui_consts.go
│ │ ├── config_function.go
│ │ ├── default_config.go
│ │ ├── file_operation_compress_test.go
│ │ ├── file_operations.go
│ │ ├── file_operations_compress.go
│ │ ├── file_operations_extract.go
│ │ ├── function.go
│ │ ├── function_test.go
│ │ ├── handle_file_operation_test.go
│ │ ├── handle_file_operations.go
│ │ ├── handle_modal.go
│ │ ├── handle_panel_movement.go
│ │ ├── handle_panel_navigation.go
│ │ ├── key_function.go
│ │ ├── model.go
│ │ ├── model_file_operations_test.go
│ │ ├── model_layout_test.go
│ │ ├── model_msg.go
│ │ ├── model_navigation_test.go
│ │ ├── model_process_test.go
│ │ ├── model_prompt_test.go
│ │ ├── model_render.go
│ │ ├── model_test.go
│ │ ├── model_zoxide_test.go
│ │ ├── test_utils.go
│ │ ├── test_utils_teaprog.go
│ │ ├── type.go
│ │ ├── type_utils.go
│ │ ├── ui/
│ │ │ ├── README.md
│ │ │ ├── clipboard/
│ │ │ │ ├── model.go
│ │ │ │ └── model_test.go
│ │ │ ├── filemodel/
│ │ │ │ ├── consts.go
│ │ │ │ ├── dimensions.go
│ │ │ │ ├── navigation.go
│ │ │ │ ├── render.go
│ │ │ │ ├── type.go
│ │ │ │ ├── update.go
│ │ │ │ └── utils.go
│ │ │ ├── filepanel/
│ │ │ │ ├── columns.go
│ │ │ │ ├── consts.go
│ │ │ │ ├── dimension.go
│ │ │ │ ├── get_elements.go
│ │ │ │ ├── get_elements_test.go
│ │ │ │ ├── misc.go
│ │ │ │ ├── model.go
│ │ │ │ ├── navigation.go
│ │ │ │ ├── navigation_test.go
│ │ │ │ ├── render.go
│ │ │ │ ├── selection_test.go
│ │ │ │ ├── sort.go
│ │ │ │ ├── types.go
│ │ │ │ ├── update.go
│ │ │ │ └── utils.go
│ │ │ ├── helpmenu/
│ │ │ │ ├── data.go
│ │ │ │ ├── model_state.go
│ │ │ │ ├── navigation.go
│ │ │ │ ├── render.go
│ │ │ │ ├── type.go
│ │ │ │ └── utils.go
│ │ │ ├── metadata/
│ │ │ │ ├── README.md
│ │ │ │ ├── architecture.go
│ │ │ │ ├── architecture_test.go
│ │ │ │ ├── const.go
│ │ │ │ ├── metadata.go
│ │ │ │ ├── metadata_test.go
│ │ │ │ ├── metadata_unix.go
│ │ │ │ ├── metadata_windows.go
│ │ │ │ ├── model.go
│ │ │ │ ├── model_test.go
│ │ │ │ ├── testdata/
│ │ │ │ │ └── file1.txt
│ │ │ │ ├── update.go
│ │ │ │ └── utils.go
│ │ │ ├── notify/
│ │ │ │ ├── model.go
│ │ │ │ └── type.go
│ │ │ ├── preview/
│ │ │ │ ├── model.go
│ │ │ │ ├── model_utils.go
│ │ │ │ ├── render.go
│ │ │ │ ├── render_test.go
│ │ │ │ ├── render_unix_test.go
│ │ │ │ ├── render_utils.go
│ │ │ │ └── update.go
│ │ │ ├── processbar/
│ │ │ │ ├── README.md
│ │ │ │ ├── const.go
│ │ │ │ ├── error.go
│ │ │ │ ├── model.go
│ │ │ │ ├── model_navigation.go
│ │ │ │ ├── model_navigation_test.go
│ │ │ │ ├── model_test.go
│ │ │ │ ├── model_update.go
│ │ │ │ ├── model_update_test.go
│ │ │ │ ├── model_utils.go
│ │ │ │ ├── model_utils_test.go
│ │ │ │ ├── operation.go
│ │ │ │ ├── process.go
│ │ │ │ ├── process_test.go
│ │ │ │ └── process_update_msg.go
│ │ │ ├── prompt/
│ │ │ │ ├── README.md
│ │ │ │ ├── consts.go
│ │ │ │ ├── error.go
│ │ │ │ ├── model.go
│ │ │ │ ├── model_test.go
│ │ │ │ ├── tokenize.go
│ │ │ │ ├── tokenize_test.go
│ │ │ │ ├── type.go
│ │ │ │ ├── utils.go
│ │ │ │ └── utils_test.go
│ │ │ ├── rendering/
│ │ │ │ ├── README.md
│ │ │ │ ├── border.go
│ │ │ │ ├── constants.go
│ │ │ │ ├── content_renderer.go
│ │ │ │ ├── content_renderer_test.go
│ │ │ │ ├── renderer.go
│ │ │ │ ├── renderer_core.go
│ │ │ │ ├── renderer_test.go
│ │ │ │ ├── truncate.go
│ │ │ │ └── truncate_test.go
│ │ │ ├── sidebar/
│ │ │ │ ├── README.md
│ │ │ │ ├── consts.go
│ │ │ │ ├── directory_utils.go
│ │ │ │ ├── disk_utils.go
│ │ │ │ ├── navigation.go
│ │ │ │ ├── navigation_test.go
│ │ │ │ ├── pinned.go
│ │ │ │ ├── pinned_test.go
│ │ │ │ ├── render.go
│ │ │ │ ├── sidebar.go
│ │ │ │ ├── type.go
│ │ │ │ ├── utils.go
│ │ │ │ └── utils_test.go
│ │ │ ├── sortmodel/
│ │ │ │ ├── const.go
│ │ │ │ ├── model.go
│ │ │ │ ├── navigation.go
│ │ │ │ ├── render.go
│ │ │ │ ├── types.go
│ │ │ │ └── utils.go
│ │ │ ├── spf_renderers.go
│ │ │ └── zoxide/
│ │ │ ├── README.md
│ │ │ ├── consts.go
│ │ │ ├── model.go
│ │ │ ├── model_test.go
│ │ │ ├── navigation.go
│ │ │ ├── navigation_test.go
│ │ │ ├── render.go
│ │ │ ├── render_test.go
│ │ │ ├── test_helpers.go
│ │ │ ├── type.go
│ │ │ ├── utils.go
│ │ │ └── utils_test.go
│ │ ├── validation.go
│ │ └── wheel_function.go
│ ├── pkg/
│ │ ├── cache/
│ │ │ └── cache.go
│ │ ├── file_preview/
│ │ │ ├── ansi.go
│ │ │ ├── constants.go
│ │ │ ├── image_preview.go
│ │ │ ├── image_resize.go
│ │ │ ├── kitty.go
│ │ │ ├── thumbnail_generator.go
│ │ │ ├── utils.go
│ │ │ ├── utils_unix.go
│ │ │ └── utils_windows.go
│ │ ├── string_function/
│ │ │ └── overplace.go
│ │ └── utils/
│ │ ├── README.md
│ │ ├── bool_file_store.go
│ │ ├── bool_file_store_test.go
│ │ ├── config_interface.go
│ │ ├── consts.go
│ │ ├── detach_unix.go
│ │ ├── detach_windows.go
│ │ ├── error.go
│ │ ├── file_utils.go
│ │ ├── file_utils_test.go
│ │ ├── fzf_utils.go
│ │ ├── log_utils.go
│ │ ├── shell_utils.go
│ │ ├── tea_utils.go
│ │ ├── test_utils.go
│ │ ├── testdata/
│ │ │ └── load_toml/
│ │ │ ├── default.toml
│ │ │ ├── ignorer/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── default.toml
│ │ │ │ ├── default_extra_fields.toml
│ │ │ │ ├── invalid_format.toml
│ │ │ │ ├── invalid_value_type.toml
│ │ │ │ ├── missing_str2.toml
│ │ │ │ ├── missing_str_ignore.toml
│ │ │ │ ├── missing_str_ignore2.toml
│ │ │ │ └── missing_str_int.toml
│ │ │ └── missing_str.toml
│ │ └── ui_utils.go
│ └── superfile_config/
│ ├── config.toml
│ ├── hotkeys.toml
│ ├── theme/
│ │ ├── 0x96f.toml
│ │ ├── ayu-dark.toml
│ │ ├── blood.toml
│ │ ├── catppuccin-frappe.toml
│ │ ├── catppuccin-latte.toml
│ │ ├── catppuccin-macchiato.toml
│ │ ├── catppuccin-mocha.toml
│ │ ├── dracula.toml
│ │ ├── everforest-dark-hard.toml
│ │ ├── everforest-dark-medium.toml
│ │ ├── gruvbox-dark-hard.toml
│ │ ├── gruvbox.toml
│ │ ├── hacks.toml
│ │ ├── kaolin.toml
│ │ ├── monokai.toml
│ │ ├── nord.toml
│ │ ├── onedark.toml
│ │ ├── poimandres.toml
│ │ ├── rose-pine.toml
│ │ ├── sugarplum.toml
│ │ └── tokyonight.toml
│ └── vimHotkeys.toml
├── testsuite/
│ ├── .gitignore
│ ├── Notes.md
│ ├── README.md
│ ├── core/
│ │ ├── __init__.py
│ │ ├── base_test.py
│ │ ├── environment.py
│ │ ├── fs_manager.py
│ │ ├── keys.py
│ │ ├── pyautogui_manager.py
│ │ ├── runner.py
│ │ ├── spf_manager.py
│ │ ├── test_constants.py
│ │ ├── tmux_manager.py
│ │ └── utils.py
│ ├── docs/
│ │ └── tmux.md
│ ├── main.py
│ ├── requirements.txt
│ └── tests/
│ ├── __init__.py
│ ├── chooser_file_test.py
│ ├── command_test.py
│ ├── compress_extract_test.py
│ ├── copy_dir_test.py
│ ├── copy_test.py
│ ├── copyw_test.py
│ ├── cut_test.py
│ ├── delete_dir_test.py
│ ├── delete_test.py
│ ├── empty_panel_test.py
│ ├── nav_and_copy_path_test.py
│ └── rename_test.py
├── vhs/
│ ├── demo.tape
│ ├── open_spf_and_quit.tape
│ ├── spf_file_panel_movement.tape
│ ├── spf_file_panel_navigation.tape
│ ├── spf_file_panel_selection_mode.tape
│ └── spf_panel_navigation.tape
└── website/
├── README.md
├── astro.config.mjs
├── ec.config.mjs
├── package.json
├── public/
│ ├── _redirects
│ ├── google0fdf22175b8dde4d.html
│ ├── install.ps1
│ ├── install.sh
│ └── uninstall.ps1
├── src/
│ ├── components/
│ │ ├── GithubStar.astro
│ │ ├── LastUpdated.astro
│ │ ├── about.astro
│ │ └── code.astro
│ ├── content/
│ │ ├── config.ts
│ │ └── docs/
│ │ ├── changelog.md
│ │ ├── configure/
│ │ │ ├── config-file-path.md
│ │ │ ├── custom-hotkeys.mdx
│ │ │ ├── custom-theme.mdx
│ │ │ ├── enable-plugin.md
│ │ │ └── superfile-config.mdx
│ │ ├── contribute/
│ │ │ ├── file-struct.md
│ │ │ ├── how-to-contribute.md
│ │ │ └── implementation-info.md
│ │ ├── getting-started/
│ │ │ ├── image-preview.md
│ │ │ ├── installation.md
│ │ │ └── tutorial.md
│ │ ├── index.mdx
│ │ ├── list/
│ │ │ ├── hotkey-list.md
│ │ │ ├── plugin-list.md
│ │ │ └── theme-list.md
│ │ ├── overview.md
│ │ ├── special-thanks.mdx
│ │ └── troubleshooting.md
│ ├── env.d.ts
│ └── styles/
│ └── custom.css
└── tsconfig.json
SYMBOL INDEX (1350 symbols across 208 files)
FILE: main.go
function main (line 14) | func main() {
FILE: src/cmd/debug_info.go
constant keyWidth (line 19) | keyWidth = 20
constant maxVersionLength (line 20) | maxVersionLength = 50
type debugPrinter (line 23) | type debugPrinter struct
method printHeader (line 101) | func (dp *debugPrinter) printHeader(text string) {
method printKeyValue (line 105) | func (dp *debugPrinter) printKeyValue(key, value string) {
method printEnv (line 118) | func (dp *debugPrinter) printEnv(key string) {
method checkDependency (line 126) | func (dp *debugPrinter) checkDependency(name string, flag string) {
function newDebugPrinter (line 30) | func newDebugPrinter() *debugPrinter {
function printDebugInfo (line 39) | func printDebugInfo() {
function getKernelVersion (line 159) | func getKernelVersion() (string, error) {
FILE: src/cmd/help_printer.go
function CustomHelpPrinter (line 15) | func CustomHelpPrinter(w io.Writer, templ string, data interface{}) {
function printUsage (line 48) | func printUsage(w io.Writer, titleColor *color.Color, accentColor *color...
function printCommands (line 68) | func printCommands(w io.Writer, titleColor *color.Color, commandColor *c...
function printFlags (line 86) | func printFlags(w io.Writer, titleColor *color.Color, flagColor *color.C...
FILE: src/cmd/main.go
function Run (line 27) | func Run(content embed.FS) {
function spfAppAction (line 136) | func spfAppAction(_ context.Context, c *cli.Command) error {
function InitConfigFile (line 174) | func InitConfigFile() {
function checkFirstUse (line 207) | func checkFirstUse() bool {
function writeConfigFile (line 220) | func writeConfigFile(path, data string) error {
function writeLastCheckTime (line 229) | func writeLastCheckTime(t time.Time) {
function CheckForUpdates (line 239) | func CheckForUpdates() {
function readLastCheckTime (line 256) | func readLastCheckTime() time.Time {
function shouldCheckForUpdate (line 271) | func shouldCheckForUpdate(now, last time.Time) bool {
function checkAndNotifyUpdate (line 275) | func checkAndNotifyUpdate() {
function fetchLatestRelease (line 307) | func fetchLatestRelease(ctx context.Context) (*http.Response, error) {
function notifyUpdateAvailable (line 315) | func notifyUpdateAvailable(latest string) {
FILE: src/config/fixed_variable.go
constant CurrentVersion (line 15) | CurrentVersion = "v1.5.0"
constant PreReleaseSuffix (line 18) | PreReleaseSuffix = ""
constant LatestVersionURL (line 21) | LatestVersionURL = "https://api.github.com/repos/yorukot/superfile/re...
constant LatestVersionGithub (line 22) | LatestVersionGithub = "github.com/yorukot/superfile/releases/latest"
constant EmbedConfigDir (line 25) | EmbedConfigDir = "src/superfile_config"
constant EmbedConfigFile (line 26) | EmbedConfigFile = EmbedConfigDir + "/config.toml"
constant EmbedHotkeysFile (line 27) | EmbedHotkeysFile = EmbedConfigDir + "/hotkeys.toml"
constant EmbedThemeDir (line 28) | EmbedThemeDir = EmbedConfigDir + "/theme"
constant EmbedThemeCatppuccinFile (line 29) | EmbedThemeCatppuccinFile = EmbedThemeDir + "/catppuccin-mocha.toml"
function SetLastDir (line 82) | func SetLastDir(path string) {
function SetChooserFile (line 86) | func SetChooserFile(path string) {
function UpdateVarFromCliArgs (line 90) | func UpdateVarFromCliArgs(c *cli.Command) {
FILE: src/config/icon/function.go
function InitIcon (line 19) | func InitIcon(nerdfont bool, directoryIconColor string) {
function GetCopyOrCutIcon (line 72) | func GetCopyOrCutIcon(cut bool) string {
FILE: src/config/icon/icon.go
type Style (line 4) | type Style struct
FILE: src/internal/common/config_type.go
type ThemeType (line 4) | type ThemeType struct
type ConfigType (line 66) | type ConfigType struct
method GetIgnoreMissingFields (line 118) | func (c *ConfigType) GetIgnoreMissingFields() bool {
type HotkeysType (line 122) | type HotkeysType struct
FILE: src/internal/common/icon_utils.go
function getFileIcon (line 10) | func getFileIcon(file string, isLink bool) icon.Style {
function GetElementIcon (line 51) | func GetElementIcon(file string, isDir bool, isLink bool, nerdFont bool)...
FILE: src/internal/common/icon_utils_test.go
function TestGetElementIcon (line 9) | func TestGetElementIcon(t *testing.T) {
FILE: src/internal/common/load_config.go
function LoadConfigFile (line 26) | func LoadConfigFile() {
function ValidateConfig (line 55) | func ValidateConfig(c *ConfigType) error {
function validateBorders (line 96) | func validateBorders(c *ConfigType) error {
function LoadHotkeysFile (line 130) | func LoadHotkeysFile(ignoreMissingFields bool) {
function LoadThemeFile (line 190) | func LoadThemeFile() {
function LoadUserTheme (line 211) | func LoadUserTheme(themeFile string, obj *ThemeType) error {
function LoadAllDefaultConfig (line 224) | func LoadAllDefaultConfig(content embed.FS) {
function LoadConfigStringGlobals (line 261) | func LoadConfigStringGlobals(content embed.FS) error {
function WriteThemeFiles (line 282) | func WriteThemeFiles(content embed.FS) error {
function PopulateGlobalConfigs (line 326) | func PopulateGlobalConfigs() error {
function populateFromFile (line 362) | func populateFromFile(filePath string, target interface{}) error {
function PopulateConfigFromFile (line 374) | func PopulateConfigFromFile(configFilePath string) error {
function PopulateHotkeyFromFile (line 378) | func PopulateHotkeyFromFile(hotkeyFilePath string) error {
function PopulateThemeFromFile (line 382) | func PopulateThemeFromFile(themeFilePath string) error {
function InitTrash (line 386) | func InitTrash() bool {
FILE: src/internal/common/predefined_variable.go
constant WheelRunTime (line 12) | WheelRunTime = 5
constant DefaultCommandTimeout (line 13) | DefaultCommandTimeout = 5000 * time.Millisecond
constant DateModifiedOption (line 14) | DateModifiedOption = "Date Modified"
constant InvalidTypeString (line 15) | InvalidTypeString = "InvalidType"
constant SameRenameWarnTitle (line 19) | SameRenameWarnTitle = "There is already a file or directory with that ...
constant SameRenameWarnContent (line 20) | SameRenameWarnContent = "This operation will override the existing file"
constant TrashWarnTitle (line 24) | TrashWarnTitle = "Are you sure you want to move this to tras...
constant TrashWarnContent (line 25) | TrashWarnContent = "This operation will move file or directory...
constant PermanentDeleteWarnTitle (line 26) | PermanentDeleteWarnTitle = "Are you sure you want to completely delete"
constant PermanentDeleteWarnContent (line 27) | PermanentDeleteWarnContent = "This operation cannot be undone and your d...
constant MinimumHeight (line 31) | MinimumHeight = 24
constant MinimumWidth (line 32) | MinimumWidth = 60
constant MinFooterHeight (line 36) | MinFooterHeight = 6
constant ModalWidth (line 37) | ModalWidth = 60
constant ModalHeight (line 38) | ModalHeight = 7
function LoadInitialPrerenderedVariables (line 109) | func LoadInitialPrerenderedVariables() {
function wrapFilePreviewErrorMsg (line 115) | func wrapFilePreviewErrorMsg(msg string) string {
function LoadPrerenderedVariables (line 124) | func LoadPrerenderedVariables() {
FILE: src/internal/common/string_function.go
constant KilobyteSize (line 22) | KilobyteSize = 1000
constant KibibyteSize (line 23) | KibibyteSize = 1024
constant TabWidth (line 24) | TabWidth = 4
constant DefaultBufferSize (line 25) | DefaultBufferSize = 1024
constant NonBreakingSpace (line 26) | NonBreakingSpace = 0xa0
constant EscapeChar (line 27) | EscapeChar = 0x1b
constant ASCIIMax (line 28) | ASCIIMax = 0x7f
function TruncateText (line 37) | func TruncateText(text string, maxChars int, tails string) string {
function TruncateTextBeginning (line 46) | func TruncateTextBeginning(text string, maxChars int, tails string) stri...
function TruncateMiddleText (line 67) | func TruncateMiddleText(text string, maxChars int, tails string) string {
function FilePanelItemRenderWithIcon (line 80) | func FilePanelItemRenderWithIcon(
function FilePanelItemRender (line 100) | func FilePanelItemRender(data string,
function ClipboardPrettierName (line 114) | func ClipboardPrettierName(name string, width int, isDir bool, isLink bo...
function FileNameWithoutExtension (line 128) | func FileNameWithoutExtension(fileName string) string {
function unitsDec (line 139) | func unitsDec() [7]string {
function unitsBin (line 143) | func unitsBin() [7]string {
function formatSizeInternal (line 147) | func formatSizeInternal(size int64, power int, unitlist [7]string) string {
function FormatFileSize (line 159) | func FormatFileSize(size int64) string {
function GetHelpMenuHotkeyString (line 167) | func GetHelpMenuHotkeyString(hotkeys []string) string {
function IsBufferPrintable (line 185) | func IsBufferPrintable(buffer []byte) bool {
function IsExtensionExtractable (line 196) | func IsExtensionExtractable(ext string) bool {
function IsTextFile (line 214) | func IsTextFile(filename string) (bool, error) {
function MakePrintableWithEscCheck (line 238) | func MakePrintableWithEscCheck(line string, allowEsc bool) string { //no...
function MakePrintable (line 280) | func MakePrintable(line string) string {
FILE: src/internal/common/string_function_test.go
function TestStringTruncate (line 11) | func TestStringTruncate(t *testing.T) {
function TestFilenameWithouText (line 42) | func TestFilenameWithouText(t *testing.T) {
function TestHelpHotkeyString (line 64) | func TestHelpHotkeyString(t *testing.T) {
function TestIsBufferPrintable (line 113) | func TestIsBufferPrintable(t *testing.T) {
function TestIsExtensionExtractable (line 141) | func TestIsExtensionExtractable(t *testing.T) {
function TestMakePrintable (line 172) | func TestMakePrintable(t *testing.T) {
function TestFormatSizeInternal (line 214) | func TestFormatSizeInternal(t *testing.T) {
FILE: src/internal/common/style.go
function LoadThemeConfig (line 117) | func LoadThemeConfig() { //nolint: funlen // Variable initialization
function TransparentAllBackgroundColor (line 223) | func TransparentAllBackgroundColor() {
FILE: src/internal/common/style_function.go
function ModalBorderStyle (line 14) | func ModalBorderStyle(height int, width int) lipgloss.Style {
function modalBorderStyleWithAlign (line 19) | func modalBorderStyleWithAlign(height int, width int, horizontalAlignmen...
function FirstUseModal (line 32) | func FirstUseModal(height int, width int) lipgloss.Style {
function SortOptionsModalBorderStyle (line 45) | func SortOptionsModalBorderStyle(height int, width int, borderBottom str...
function FullScreenStyle (line 60) | func FullScreenStyle(height int, width int) lipgloss.Style {
function StringColorRender (line 70) | func StringColorRender(fgColor lipgloss.Color, bgColor lipgloss.Color) l...
function GenerateBorder (line 77) | func GenerateBorder() lipgloss.Border {
function LoadConfigError (line 90) | func LoadConfigError(value string, msg string) string {
function LoadHotkeysError (line 94) | func LoadHotkeysError(value string, msg string) string {
function LoadThemeError (line 98) | func LoadThemeError(value string, msg string) string {
function UserConfigInvalidationErrorString (line 102) | func UserConfigInvalidationErrorString(value string, configType string, ...
function GenerateSearchBar (line 112) | func GenerateSearchBar() textinput.Model {
function GeneratePromptTextInput (line 126) | func GeneratePromptTextInput() textinput.Model {
function GenerateNewFileTextInput (line 139) | func GenerateNewFileTextInput() textinput.Model {
function GenerateRenameTextInput (line 154) | func GenerateRenameTextInput(width int, cursorPos int, defaultValue stri...
function GeneratePinnedRenameTextInput (line 172) | func GeneratePinnedRenameTextInput(cursorPos int, defaultValue string) t...
function GenerateGradientColor (line 189) | func GenerateGradientColor() progress.Option {
function GenerateFooterBorder (line 193) | func GenerateFooterBorder(countString string, width int) string {
FILE: src/internal/common/type.go
type ModelAction (line 5) | type ModelAction interface
type NoAction (line 9) | type NoAction struct
method String (line 12) | func (n NoAction) String() string {
type ShellCommandAction (line 16) | type ShellCommandAction struct
method String (line 20) | func (s ShellCommandAction) String() string {
type SplitPanelAction (line 26) | type SplitPanelAction struct
method String (line 28) | func (s SplitPanelAction) String() string {
type CDCurrentPanelAction (line 32) | type CDCurrentPanelAction struct
method String (line 36) | func (c CDCurrentPanelAction) String() string {
type OpenPanelAction (line 40) | type OpenPanelAction struct
method String (line 44) | func (o OpenPanelAction) String() string {
FILE: src/internal/common/ui_consts.go
constant HelpKeyColumnWidth (line 7) | HelpKeyColumnWidth = 55
constant DefaultCLIContextTimeout (line 8) | DefaultCLIContextTimeout = 5 * time.Second
constant PanelPadding (line 10) | PanelPadding = 3
constant BorderPadding (line 11) | BorderPadding = 2
constant InnerPadding (line 12) | InnerPadding = 4
constant FooterGroupCols (line 13) | FooterGroupCols = 3
constant DefaultFilePanelWidth (line 15) | DefaultFilePanelWidth = 10
constant FilePanelMax (line 16) | FilePanelMax = 10
constant ResponsiveWidthThreshold (line 17) | ResponsiveWidthThreshold = 95
constant HeightBreakA (line 19) | HeightBreakA = 30
constant HeightBreakB (line 20) | HeightBreakB = 35
constant HeightBreakC (line 21) | HeightBreakC = 40
constant HeightBreakD (line 22) | HeightBreakD = 45
constant FilePanelWidthUnit (line 24) | FilePanelWidthUnit = 20
constant DefaultPreviewTimeout (line 25) | DefaultPreviewTimeout = 500 * time.Millisecond
constant FileNameRatioMin (line 27) | FileNameRatioMin = 25
constant FileNameRatioMax (line 28) | FileNameRatioMax = 100
constant RequiredGradientColorCount (line 30) | RequiredGradientColorCount = 2
constant CenterDivisor (line 33) | CenterDivisor = 2
FILE: src/internal/config_function.go
function initialConfig (line 31) | func initialConfig(firstPanelPaths []string) (toggleDotFile bool, //noli...
function updateFirstFilePanelPaths (line 97) | func updateFirstFilePanelPaths(firstPanelPaths []string, cwd string, zCl...
function attemptZoxideForInitPath (line 123) | func attemptZoxideForInitPath(originalPath string, zClient *zoxidelib.Cl...
function printRuntimeInfo (line 138) | func printRuntimeInfo() {
FILE: src/internal/default_config.go
function defaultModelConfig (line 29) | func defaultModelConfig(toggleDotFile, toggleFooter, firstUse bool,
FILE: src/internal/file_operation_compress_test.go
function TestZipSources (line 18) | func TestZipSources(t *testing.T) {
function validateZipExtraction (line 109) | func validateZipExtraction(t *testing.T, zipReader *zip.ReadCloser, expe...
function TestZipSourcesInvalidTarget (line 141) | func TestZipSourcesInvalidTarget(t *testing.T) {
FILE: src/internal/file_operations.go
function isSamePartition (line 22) | func isSamePartition(path1, path2 string) (bool, error) {
function getDriveLetter (line 46) | func getDriveLetter(path string) string {
function moveElement (line 53) | func moveElement(src, dst string) error {
function copyElement (line 83) | func copyElement(src, dst string) error {
function copyDir (line 96) | func copyDir(src, dst string, srcInfo os.FileInfo) error {
function copyFile (line 129) | func copyFile(src, dst string, srcInfo os.FileInfo) error {
function moveToTrash (line 148) | func moveToTrash(src string) error {
function pasteDir (line 169) | func pasteDir(src, dst string, p *processbar.Process, cut bool, processB...
function actualPasteOperation (line 214) | func actualPasteOperation(info os.FileInfo, path string, newPath string,...
function isAncestor (line 252) | func isAncestor(src, dst string) bool {
FILE: src/internal/file_operations_compress.go
function zipSources (line 17) | func zipSources(sources []string, target string, processBar *processbar....
function zipSourcesCore (line 70) | func zipSourcesCore(sources []string, processBar *processbar.Model,
function writeZipFile (line 101) | func writeZipFile(path string, relPath string, info os.FileInfo, writer ...
function getZipArchiveName (line 130) | func getZipArchiveName(base string) (string, error) {
FILE: src/internal/file_operations_extract.go
function extractCompressFile (line 16) | func extractCompressFile(src, dest string, processBar *processbar.Model)...
FILE: src/internal/function.go
function isExternalDiskPath (line 29) | func isExternalDiskPath(path string) bool {
function checkFileNameValidity (line 49) | func checkFileNameValidity(name string) error {
function renameIfDuplicate (line 61) | func renameIfDuplicate(destination string) (string, error) {
function countFiles (line 96) | func countFiles(dirPath string) (int, error) {
function processCmdToTeaCmd (line 112) | func processCmdToTeaCmd(cmd processbar.Cmd) tea.Cmd {
function getCopyOrCutOperationName (line 128) | func getCopyOrCutOperationName(cut bool) string {
FILE: src/internal/function_test.go
function TestCheckFileNameValidity (line 15) | func TestCheckFileNameValidity(t *testing.T) {
function Test_renameIfDuplicate (line 77) | func Test_renameIfDuplicate(t *testing.T) {
function Benchmark_renameIfDuplicate (line 123) | func Benchmark_renameIfDuplicate(b *testing.B) {
FILE: src/internal/handle_file_operation_test.go
function TestCompressSelectedFiles (line 19) | func TestCompressSelectedFiles(t *testing.T) {
function TestPasteItem (line 172) | func TestPasteItem(t *testing.T) {
function setupModelAndPerformOperation (line 372) | func setupModelAndPerformOperation(t *testing.T, startDir string, useSel...
function ensureOneProcessDone (line 390) | func ensureOneProcessDone(t *testing.T, m *model) {
function cleanupWithRetry (line 401) | func cleanupWithRetry(t *testing.T, path, label string) {
FILE: src/internal/handle_file_operations.go
method panelCreateNewFile (line 29) | func (m *model) panelCreateNewFile() {
method IsRenamingConflicting (line 39) | func (m *model) IsRenamingConflicting() bool {
method warnModalForRenaming (line 58) | func (m *model) warnModalForRenaming() tea.Cmd {
method panelItemRename (line 75) | func (m *model) panelItemRename() {
method getDeleteCmd (line 106) | func (m *model) getDeleteCmd(permDelete bool) tea.Cmd {
function deleteOperation (line 130) | func deleteOperation(processBarModel *processbar.Model, items []string, ...
method getDeleteTriggerCmd (line 167) | func (m *model) getDeleteTriggerCmd(deletePermanent bool) tea.Cmd {
method copySingleItem (line 193) | func (m *model) copySingleItem(cut bool) {
method copyMultipleItem (line 205) | func (m *model) copyMultipleItem(cut bool) {
method getPasteItemCmd (line 216) | func (m *model) getPasteItemCmd() tea.Cmd {
function validatePasteOperation (line 241) | func validatePasteOperation(panelLocation string, copyItems []string, cu...
function executePasteOperation (line 267) | func executePasteOperation(processBarModel *processbar.Model,
function getTotalFilesCnt (line 325) | func getTotalFilesCnt(copyItems []string) int {
method getExtractFileCmd (line 352) | func (m *model) getExtractFileCmd() tea.Cmd {
method getCompressSelectedFilesCmd (line 395) | func (m *model) getCompressSelectedFilesCmd() tea.Cmd {
method chooserFileWriteAndQuit (line 430) | func (m *model) chooserFileWriteAndQuit(path string) error {
method openFileWithEditor (line 441) | func (m *model) openFileWithEditor() tea.Cmd {
method openDirectoryWithEditor (line 486) | func (m *model) openDirectoryWithEditor() tea.Cmd {
method copyPath (line 523) | func (m *model) copyPath() {
method copyPWD (line 536) | func (m *model) copyPWD() {
FILE: src/internal/handle_modal.go
method cancelTypingModal (line 14) | func (m *model) cancelTypingModal() {
method createItem (line 20) | func (m *model) createItem() {
method cancelRename (line 57) | func (m *model) cancelRename() {
method confirmRename (line 65) | func (m *model) confirmRename() {
method confirmSortOptions (line 89) | func (m *model) confirmSortOptions() {
method cancelSearch (line 96) | func (m *model) cancelSearch() {
method confirmSearch (line 103) | func (m *model) confirmSearch() {
method getFocusedFilePanel (line 108) | func (m *model) getFocusedFilePanel() *filepanel.Model {
FILE: src/internal/handle_panel_movement.go
method parentDirectory (line 20) | func (m *model) parentDirectory() {
method enterPanel (line 29) | func (m *model) enterPanel() {
method executeOpenCommand (line 70) | func (m *model) executeOpenCommand() {
method sidebarSelectDirectory (line 109) | func (m *model) sidebarSelectDirectory() {
method toggleDotFileController (line 127) | func (m *model) toggleDotFileController() {
method toggleFooterController (line 136) | func (m *model) toggleFooterController() tea.Cmd {
method searchBarFocus (line 147) | func (m *model) searchBarFocus() {
method sidebarSearchBarFocus (line 160) | func (m *model) sidebarSearchBarFocus() {
FILE: src/internal/handle_panel_navigation.go
method pinnedDirectory (line 10) | func (m *model) pinnedDirectory() {
method focusOnSideBar (line 19) | func (m *model) focusOnSideBar() {
method focusOnProcessBar (line 33) | func (m *model) focusOnProcessBar() {
method focusOnMetadata (line 48) | func (m *model) focusOnMetadata() {
FILE: src/internal/key_function.go
method mainKey (line 24) | func (m *model) mainKey(msg string) tea.Cmd { //nolint: gocyclo,cyclop,f...
method normalAndBrowserModeKey (line 150) | func (m *model) normalAndBrowserModeKey(msg string) tea.Cmd {
method typingModalOpenKey (line 213) | func (m *model) typingModalOpenKey(msg string) {
method notifyModelOpenKey (line 223) | func (m *model) notifyModelOpenKey(msg string) tea.Cmd {
method handleNotifyModelCancel (line 239) | func (m *model) handleNotifyModelCancel(action notify.ConfirmActionType)...
method handleNotifyModelConfirm (line 253) | func (m *model) handleNotifyModelConfirm(action notify.ConfirmActionType...
method sortOptionsKey (line 272) | func (m *model) sortOptionsKey(msg string) {
method renamingKey (line 287) | func (m *model) renamingKey(msg string) tea.Cmd {
method sidebarRenamingKey (line 301) | func (m *model) sidebarRenamingKey(msg string) {
method focusOnSearchbarKey (line 311) | func (m *model) focusOnSearchbarKey(msg string) {
FILE: src/internal/model.go
function InitialModel (line 42) | func InitialModel(firstPanelPaths []string, firstUseCheck bool) tea.Model {
method Init (line 52) | func (m *model) Init() tea.Cmd {
method Update (line 62) | func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
method handleMouseMsg (line 114) | func (m *model) handleMouseMsg(msg tea.MouseMsg) {
method updateModelStateAfterMsg (line 123) | func (m *model) updateModelStateAfterMsg() {
method getMetadataCmd (line 141) | func (m *model) getMetadataCmd() tea.Cmd {
method handleWindowResize (line 179) | func (m *model) handleWindowResize(msg tea.WindowSizeMsg) tea.Cmd {
method setHeightValues (line 186) | func (m *model) setHeightValues() {
method updateComponentDimensions (line 208) | func (m *model) updateComponentDimensions() tea.Cmd {
method setMainModelDimensions (line 220) | func (m *model) setMainModelDimensions() tea.Cmd {
method setHelpMenuSize (line 230) | func (m *model) setHelpMenuSize() {
method setPromptModelSize (line 242) | func (m *model) setPromptModelSize() {
method setZoxideModelSize (line 250) | func (m *model) setZoxideModelSize() {
method setFooterComponentSize (line 258) | func (m *model) setFooterComponentSize() {
method handleKeyInput (line 270) | func (m *model) handleKeyInput(msg tea.KeyMsg) tea.Cmd {
method updateComponentState (line 357) | func (m *model) updateComponentState(msg tea.Msg) tea.Cmd {
method applyPromptModalAction (line 383) | func (m *model) applyPromptModalAction(action common.ModelAction) tea.Cmd {
method logAndExecuteAction (line 394) | func (m *model) logAndExecuteAction(action common.ModelAction) (string, ...
method applyZoxideModalAction (line 421) | func (m *model) applyZoxideModalAction(action common.ModelAction) tea.Cmd {
method applyShellCommandAction (line 427) | func (m *model) applyShellCommandAction(shellCommand string) {
method splitPanel (line 441) | func (m *model) splitPanel() (tea.Cmd, error) {
method createNewFilePanelRelativeToCurrent (line 445) | func (m *model) createNewFilePanelRelativeToCurrent(path string) (tea.Cm...
method updateCurrentFilePanelDir (line 451) | func (m *model) updateCurrentFilePanelDir(path string) error {
method trackDirectoryWithZoxide (line 462) | func (m *model) trackDirectoryWithZoxide(path string) {
method warnModalForQuit (line 476) | func (m *model) warnModalForQuit() {
method View (line 483) | func (m *model) View() string {
method updateRenderForOverlay (line 513) | func (m *model) updateRenderForOverlay(finalRender string) string {
method mainComponentsRender (line 566) | func (m *model) mainComponentsRender() string {
method quitSuperfile (line 584) | func (m *model) quitSuperfile(cdOnQuit bool) {
FILE: src/internal/model_file_operations_test.go
function TestCopy (line 27) | func TestCopy(t *testing.T) {
function TestFileCreation (line 68) | func TestFileCreation(t *testing.T) {
function TestFileRename (line 119) | func TestFileRename(t *testing.T) {
function isTrashed (line 194) | func isTrashed(fileAbsPath string) bool {
function TestFileDelete (line 208) | func TestFileDelete(t *testing.T) {
FILE: src/internal/model_layout_test.go
constant ScrollDownCount (line 24) | ScrollDownCount = 10
constant ScrollUpCount (line 25) | ScrollUpCount = 5
function TestLayout (line 27) | func TestLayout(t *testing.T) {
function testWithConfig (line 77) | func testWithConfig(t *testing.T, sidebarWidth int, previewWidth int,
function updateModelDimensionsAndValidate (line 141) | func updateModelDimensionsAndValidate(t *testing.T, p *TeaProg, width in...
function testModelScrolling (line 228) | func testModelScrolling(t *testing.T, p *TeaProg) {
function testModelScrollingCore (line 265) | func testModelScrollingCore(t *testing.T, p *TeaProg) {
function assertLayoutValidity (line 278) | func assertLayoutValidity(t *testing.T, m *model) {
function getLayoutInfoForDebug (line 308) | func getLayoutInfoForDebug(m *model) string {
FILE: src/internal/model_msg.go
type ModelUpdateMessage (line 13) | type ModelUpdateMessage interface
type BaseMessage (line 18) | type BaseMessage struct
method GetReqID (line 22) | func (msg BaseMessage) GetReqID() int {
type PasteOperationMsg (line 26) | type PasteOperationMsg struct
method ApplyToModel (line 41) | func (msg PasteOperationMsg) ApplyToModel(m *model) tea.Cmd {
function NewPasteOperationMsg (line 32) | func NewPasteOperationMsg(state processbar.ProcessState, reqID int) Past...
type DeleteOperationMsg (line 48) | type DeleteOperationMsg struct
method ApplyToModel (line 63) | func (msg DeleteOperationMsg) ApplyToModel(m *model) tea.Cmd {
function NewDeleteOperationMsg (line 54) | func NewDeleteOperationMsg(state processbar.ProcessState, reqID int) Del...
type ProcessBarUpdateMsg (line 69) | type ProcessBarUpdateMsg struct
method ApplyToModel (line 75) | func (msg ProcessBarUpdateMsg) ApplyToModel(m *model) tea.Cmd {
type CompressOperationMsg (line 83) | type CompressOperationMsg struct
method ApplyToModel (line 98) | func (msg CompressOperationMsg) ApplyToModel(_ *model) tea.Cmd {
function NewCompressOperationMsg (line 89) | func NewCompressOperationMsg(state processbar.ProcessState, reqID int) C...
type ExtractOperationMsg (line 102) | type ExtractOperationMsg struct
method ApplyToModel (line 117) | func (msg ExtractOperationMsg) ApplyToModel(_ *model) tea.Cmd {
function NewExtractOperationMsg (line 108) | func NewExtractOperationMsg(state processbar.ProcessState, reqID int) Ex...
type MetadataMsg (line 121) | type MetadataMsg struct
method ApplyToModel (line 138) | func (msg MetadataMsg) ApplyToModel(m *model) tea.Cmd {
function NewMetadataMsg (line 128) | func NewMetadataMsg(meta metadata.Metadata, metadataFocused bool, reqID ...
type NotifyModalUpdateMsg (line 159) | type NotifyModalUpdateMsg struct
method ApplyToModel (line 174) | func (msg NotifyModalUpdateMsg) ApplyToModel(m *model) tea.Cmd {
function NewNotifyModalMsg (line 165) | func NewNotifyModalMsg(m notify.Model, reqID int) NotifyModalUpdateMsg {
FILE: src/internal/model_navigation_test.go
function TestFilePanelNavigation (line 18) | func TestFilePanelNavigation(t *testing.T) {
function TestCursorOutOfBoundsAfterDirectorySwitch (line 161) | func TestCursorOutOfBoundsAfterDirectorySwitch(t *testing.T) {
function TestCursorRemembersParentPosition (line 216) | func TestCursorRemembersParentPosition(t *testing.T) {
FILE: src/internal/model_process_test.go
function TestProcess (line 5) | func TestProcess(_ *testing.T) {
FILE: src/internal/model_prompt_test.go
function TestModel_Update_Prompt (line 22) | func TestModel_Update_Prompt(t *testing.T) {
function testBasicPromptFunctionality (line 78) | func testBasicPromptFunctionality(t *testing.T, dir1 string) {
function testPanelOperations (line 129) | func testPanelOperations(t *testing.T, dir1, dir2, curTestDir string) {
function testDirectoryHandlingWithQuotes (line 254) | func testDirectoryHandlingWithQuotes(t *testing.T, curTestDir, dir1 stri...
function testShellCommandsWithQuotes (line 380) | func testShellCommandsWithQuotes(t *testing.T, curTestDir, dir1 string) {
FILE: src/internal/model_render.go
method sidebarRender (line 16) | func (m *model) sidebarRender() string {
method processBarRender (line 21) | func (m *model) processBarRender() string {
method terminalSizeWarnRender (line 25) | func (m *model) terminalSizeWarnRender() string {
method terminalSizeWarnAfterFirstRender (line 48) | func (m *model) terminalSizeWarnAfterFirstRender() string {
method typineModalRender (line 75) | func (m *model) typineModalRender() string {
method introduceModalRender (line 99) | func (m *model) introduceModalRender() string {
method promptModalRender (line 124) | func (m *model) promptModalRender() string {
method zoxideModalRender (line 128) | func (m *model) zoxideModalRender() string {
FILE: src/internal/model_test.go
function cleanupTestDir (line 38) | func cleanupTestDir() {
function TestMain (line 46) | func TestMain(m *testing.M) {
function TestBasic (line 75) | func TestBasic(t *testing.T) {
function TestInitialFilePathPositionsCursorWindow (line 103) | func TestInitialFilePathPositionsCursorWindow(t *testing.T) {
function TestQuit (line 138) | func TestQuit(t *testing.T) {
function TestChooserFile (line 205) | func TestChooserFile(t *testing.T) {
function eventuallyEnsurePreviewContent (line 289) | func eventuallyEnsurePreviewContent(t *testing.T, m *model, content stri...
function TestAsyncPreviewPanelSync (line 302) | func TestAsyncPreviewPanelSync(t *testing.T) {
FILE: src/internal/model_zoxide_test.go
function setupProgAndOpenZoxide (line 18) | func setupProgAndOpenZoxide(t *testing.T, zClient *zoxidelib.Client, dir...
function updateCurrentFilePanelDirOfTestModel (line 31) | func updateCurrentFilePanelDirOfTestModel(t *testing.T, p *TeaProg, dir ...
function TestZoxide (line 37) | func TestZoxide(t *testing.T) {
FILE: src/internal/test_utils.go
constant DefaultTestTick (line 21) | DefaultTestTick = 10 * time.Millisecond
constant DefaultTestTimeout (line 22) | DefaultTestTimeout = time.Second
constant DefaultTestModelWidth (line 23) | DefaultTestModelWidth = 2 * common.MinimumWidth
constant DefaultTestModelHeight (line 24) | DefaultTestModelHeight = 2 * common.MinimumHeight
function defaultTestModel (line 28) | func defaultTestModel(dirs ...string) *model {
function defaultTestModelWithZClient (line 35) | func defaultTestModelWithZClient(zClient *zoxidelib.Client, dirs ...stri...
function defaultTestModelWithFooterAndFilePreview (line 40) | func defaultTestModelWithFooterAndFilePreview(dirs ...string) *model {
function defaultTestModelWithFilePreview (line 45) | func defaultTestModelWithFilePreview(dirs ...string) *model {
function setModelParamsForTest (line 50) | func setModelParamsForTest(m *model, disablePreview bool) *model {
function setupPanelModeAndSelection (line 62) | func setupPanelModeAndSelection(t *testing.T, m *model, useSelectMode bo...
function TeaUpdate (line 83) | func TeaUpdate(m *model, msg tea.Msg) tea.Cmd {
function IsTeaQuit (line 89) | func IsTeaQuit(cmd tea.Cmd) bool {
function ExecuteTeaCmdWithTimeout (line 110) | func ExecuteTeaCmdWithTimeout(cmd tea.Cmd, timeout time.Duration) tea.Msg {
function performCopyOrCutOperation (line 124) | func performCopyOrCutOperation(t *testing.T, m *model, isCut bool) {
function verifyClipboardState (line 136) | func verifyClipboardState(t *testing.T, m *model, isCut bool, useSelectM...
function verifyPathExists (line 147) | func verifyPathExists(t *testing.T, path, message string) {
function verifyPathNotExistsEventually (line 159) | func verifyPathNotExistsEventually(t *testing.T, path, message string) {
function verifyDestinationFiles (line 168) | func verifyDestinationFiles(t *testing.T, targetDir string, expectedDest...
function verifyPreventedPasteResults (line 180) | func verifyPreventedPasteResults(t *testing.T, m *model, originalPath st...
function verifySuccessfulPasteResults (line 190) | func verifySuccessfulPasteResults(t *testing.T, targetDir string, expect...
function navigateToTargetDir (line 208) | func navigateToTargetDir(t *testing.T, m *model, startDir, targetDir str...
function getOriginalPath (line 218) | func getOriginalPath(useSelectMode bool, itemName, startDir string) stri...
function setFilePanelSelectedItemByLocation (line 225) | func setFilePanelSelectedItemByLocation(t *testing.T, panel *filepanel.M...
function setFilePanelSelectedItemByName (line 232) | func setFilePanelSelectedItemByName(t *testing.T, panel *filepanel.Model...
function splitPanelAsync (line 239) | func splitPanelAsync(p *TeaProg) {
FILE: src/internal/test_utils_teaprog.go
type IgnorerWriter (line 13) | type IgnorerWriter struct
method Write (line 15) | func (w IgnorerWriter) Write(p []byte) (int, error) {
type TeaProg (line 19) | type TeaProg struct
method getModel (line 41) | func (p *TeaProg) getModel() *model {
method StartEventLoop (line 45) | func (p *TeaProg) StartEventLoop() {
method Send (line 58) | func (p *TeaProg) Send(msgs ...tea.Msg) {
method SendKey (line 64) | func (p *TeaProg) SendKey(key string) {
method SendDirectly (line 69) | func (p *TeaProg) SendDirectly(msgs ...tea.Msg) tea.Cmd {
method SendKeyDirectly (line 85) | func (p *TeaProg) SendKeyDirectly(key string) tea.Cmd {
method Close (line 89) | func (p *TeaProg) Close() {
function NewTeaProg (line 25) | func NewTeaProg(m *model, eventLoop bool) *TeaProg {
function NewTestTeaProgWithEventLoop (line 33) | func NewTestTeaProgWithEventLoop(t *testing.T, m *model) *TeaProg {
FILE: src/internal/type.go
type focusPanelType (line 25) | type focusPanelType
type modelQuitStateType (line 27) | type modelQuitStateType
constant nonePanelFocus (line 31) | nonePanelFocus focusPanelType = iota
constant processBarFocus (line 32) | processBarFocus
constant sidebarFocus (line 33) | sidebarFocus
constant metadataFocus (line 34) | metadataFocus
constant notQuitting (line 38) | notQuitting modelQuitStateType = iota
constant quitInitiated (line 39) | quitInitiated
constant quitConfirmationInitiated (line 40) | quitConfirmationInitiated
constant quitConfirmationReceived (line 41) | quitConfirmationReceived
constant quitDone (line 42) | quitDone
type model (line 50) | type model struct
type typingModal (line 94) | type typingModal struct
type editorFinishedMsg (line 101) | type editorFinishedMsg struct
FILE: src/internal/type_utils.go
method String (line 9) | func (f focusPanelType) String() string {
FILE: src/internal/ui/clipboard/model.go
type Model (line 14) | type Model struct
method SetDimensions (line 26) | func (m *Model) SetDimensions(width int, height int) {
method Render (line 31) | func (m *Model) Render() string {
method IsCut (line 61) | func (m *Model) IsCut() bool {
method Reset (line 65) | func (m *Model) Reset(cut bool) {
method Add (line 70) | func (m *Model) Add(location string) {
method SetItems (line 74) | func (m *Model) SetItems(items []string) {
method pruneInaccessibleItems (line 79) | func (m *Model) pruneInaccessibleItems() {
method GetItems (line 86) | func (m *Model) GetItems() []string {
method PruneInaccessibleItemsAndGet (line 94) | func (m *Model) PruneInaccessibleItemsAndGet() []string {
method Len (line 101) | func (m *Model) Len() int {
method GetWidth (line 105) | func (m *Model) GetWidth() int {
method GetHeight (line 109) | func (m *Model) GetHeight() int {
method GetFirstItem (line 113) | func (m *Model) GetFirstItem() string {
type copyItems (line 21) | type copyItems struct
FILE: src/internal/ui/clipboard/model_test.go
function TestMain (line 20) | func TestMain(m *testing.M) {
function TestClipboardRender_Empty (line 32) | func TestClipboardRender_Empty(t *testing.T) {
function TestPruneInaccessibleItemsAndGet (line 79) | func TestPruneInaccessibleItemsAndGet(t *testing.T) {
FILE: src/internal/ui/filemodel/consts.go
constant FileModelMinHeight (line 13) | FileModelMinHeight = filepanel.MinHeight
constant FileModelMinWidth (line 14) | FileModelMinWidth = filepanel.MinWidth
constant FilePreviewResizingText (line 15) | FilePreviewResizingText = "Resizing..."
constant FilePreviewLoadingText (line 16) | FilePreviewLoadingText = "Loading..."
FILE: src/internal/ui/filemodel/dimensions.go
method SetDimensions (line 14) | func (m *Model) SetDimensions(width int, height int) tea.Cmd {
method SetHeight (line 21) | func (m *Model) SetHeight(height int) tea.Cmd {
method SetWidth (line 27) | func (m *Model) SetWidth(width int) tea.Cmd {
method PanelCount (line 33) | func (m *Model) PanelCount() int {
method updateChildComponentHeight (line 37) | func (m *Model) updateChildComponentHeight() {
method updateChildComponentWidth (line 43) | func (m *Model) updateChildComponentWidth() {
method ensurePreviewDimensionsSync (line 82) | func (m *Model) ensurePreviewDimensionsSync() tea.Cmd {
FILE: src/internal/ui/filemodel/navigation.go
method NextFilePanel (line 5) | func (m *Model) NextFilePanel() {
method PreviousFilePanel (line 9) | func (m *Model) PreviousFilePanel() {
method MoveFocusedPanelBy (line 13) | func (m *Model) MoveFocusedPanelBy(delta int) {
FILE: src/internal/ui/filemodel/render.go
method Render (line 5) | func (m *Model) Render() string {
method GetFilePreviewRender (line 14) | func (m *Model) GetFilePreviewRender() string {
FILE: src/internal/ui/filemodel/type.go
type Model (line 11) | type Model struct
FILE: src/internal/ui/filemodel/update.go
method CreateNewFilePanel (line 15) | func (m *Model) CreateNewFilePanel(location string) (tea.Cmd, error) {
method CloseFilePanel (line 39) | func (m *Model) CloseFilePanel() (tea.Cmd, error) {
method ToggleFilePreviewPanel (line 56) | func (m *Model) ToggleFilePreviewPanel() tea.Cmd {
method UpdatePreviewPanel (line 62) | func (m *Model) UpdatePreviewPanel(msg preview.UpdateMsg) {
method GetFilePreviewCmd (line 84) | func (m *Model) GetFilePreviewCmd(forcePreviewRender bool) tea.Cmd {
method ToggleDotFile (line 125) | func (m *Model) ToggleDotFile() {
method UpdateFilePanelsIfNeeded (line 130) | func (m *Model) UpdateFilePanelsIfNeeded(force bool) {
FILE: src/internal/ui/filemodel/utils.go
method GetFocusedFilePanel (line 9) | func (m *Model) GetFocusedFilePanel() *filepanel.Model {
function New (line 13) | func New(firstPanelPaths []string, toggleDotFile bool) Model {
FILE: src/internal/ui/filepanel/columns.go
method renderFileName (line 15) | func (m *Model) renderFileName(indexElement int, columnWidth int) string {
method renderDelimiter (line 41) | func (m *Model) renderDelimiter(indexElement int, columnWidth int) string {
method renderFileSize (line 52) | func (m *Model) renderFileSize(indexElement int, columnWidth int) string {
method renderModifyTime (line 69) | func (m *Model) renderModifyTime(indexElement int, columnWidth int) stri...
method renderPermissions (line 82) | func (m *Model) renderPermissions(indexElement int, columnWidth int) str...
method Render (line 94) | func (cd *columnDefinition) Render(index int) string {
method RenderHeader (line 98) | func (cd *columnDefinition) RenderHeader() string {
method makeColumns (line 108) | func (m *Model) makeColumns(columnThreshold int, fileNameRatio int) []co...
FILE: src/internal/ui/filepanel/consts.go
constant contentPadding (line 10) | contentPadding = 3
constant MinHeight (line 11) | MinHeight = contentPadding + common.BorderPadding + 1
constant MinWidth (line 12) | MinWidth = 18
constant FileSizeColumnWidth (line 14) | FileSizeColumnWidth = 15
constant ModifyTimeSizeColumnWidth (line 15) | ModifyTimeSizeColumnWidth = 18
constant PermissionsColumnWidth (line 16) | PermissionsColumnWidth = 12
constant ColumnHeaderHeight (line 17) | ColumnHeaderHeight = 1
constant ColumnDelimiter (line 20) | ColumnDelimiter = " "
constant ReRenderChunkDivisor (line 21) | ReRenderChunkDivisor = 100
constant ReRenderMaxDelay (line 22) | ReRenderMaxDelay = 3
constant nonFocussedPanelReRenderTime (line 24) | nonFocussedPanelReRenderTime = 3 * time.Second
constant emptyCursor (line 26) | emptyCursor = " "
FILE: src/internal/ui/filepanel/dimension.go
method UpdateDimensions (line 7) | func (m *Model) UpdateDimensions(width, height int) {
method SetWidth (line 12) | func (m *Model) SetWidth(width int) {
method SetHeight (line 21) | func (m *Model) SetHeight(height int) {
method GetWidth (line 30) | func (m *Model) GetWidth() int {
method GetHeight (line 34) | func (m *Model) GetHeight() int {
method GetMainPanelHeight (line 38) | func (m *Model) GetMainPanelHeight() int {
method GetContentWidth (line 42) | func (m *Model) GetContentWidth() int {
method NeedRenderHeaders (line 46) | func (m *Model) NeedRenderHeaders() bool {
method PanelElementHeight (line 51) | func (m *Model) PanelElementHeight() int {
FILE: src/internal/ui/filepanel/get_elements.go
method getDirectoryElements (line 17) | func (m *Model) getDirectoryElements(displayDotFile bool) []Element {
method getDirectoryElementsBySearch (line 38) | func (m *Model) getDirectoryElementsBySearch(displayDotFile bool) []Elem...
method shouldSkipPanelUpdate (line 78) | func (m *Model) shouldSkipPanelUpdate(nowTime time.Time) bool {
method UpdateElementsIfNeeded (line 89) | func (m *Model) UpdateElementsIfNeeded(force bool, displayDotFile bool) {
method getElements (line 110) | func (m *Model) getElements(displayDotFile bool) []Element {
FILE: src/internal/ui/filepanel/get_elements_test.go
function TestReturnDirElement (line 15) | func TestReturnDirElement(t *testing.T) {
function TestSingleItemSelect (line 222) | func TestSingleItemSelect(t *testing.T) {
FILE: src/internal/ui/filepanel/misc.go
method String (line 5) | func (p PanelMode) String() string {
FILE: src/internal/ui/filepanel/model.go
function FilePanelSlice (line 12) | func FilePanelSlice(paths []string) []Model {
function defaultFilePanel (line 23) | func defaultFilePanel(path string, focused bool) Model {
function New (line 35) | func New(location string, focused bool, targetFile string, sortKind sort...
FILE: src/internal/ui/filepanel/navigation.go
method scrollToCursor (line 7) | func (m *Model) scrollToCursor(cursor int) {
method moveCursorBy (line 25) | func (m *Model) moveCursorBy(delta int) {
method ListUp (line 35) | func (m *Model) ListUp() {
method ListDown (line 40) | func (m *Model) ListDown() {
method PgUp (line 44) | func (m *Model) PgUp() {
method PgDown (line 48) | func (m *Model) PgDown() {
method ItemSelectUp (line 56) | func (m *Model) ItemSelectUp() {
method ItemSelectDown (line 62) | func (m *Model) ItemSelectDown() {
method applyTargetFileCursor (line 68) | func (m *Model) applyTargetFileCursor() {
method ValidateCursorAndRenderIndex (line 76) | func (m *Model) ValidateCursorAndRenderIndex() error {
FILE: src/internal/ui/filepanel/navigation_test.go
function testModelWithElemCount (line 11) | func testModelWithElemCount(cursor int, renderIndex int, height int, ele...
function testModel (line 15) | func testModel(cursor int, renderIndex int, height int, mode PanelMode,
function Test_filePanelUpDown (line 27) | func Test_filePanelUpDown(t *testing.T) {
function TestPgUpDown (line 106) | func TestPgUpDown(t *testing.T) {
function TestItemSelectUpDown (line 171) | func TestItemSelectUpDown(t *testing.T) {
function TestScrollToCursor (line 271) | func TestScrollToCursor(t *testing.T) {
function TestApplyTargetFileCursor (line 332) | func TestApplyTargetFileCursor(t *testing.T) {
function TestPageScrollSizeConfig (line 357) | func TestPageScrollSizeConfig(t *testing.T) {
FILE: src/internal/ui/filepanel/render.go
method Render (line 23) | func (m *Model) Render(focused bool) string {
method renderTopBar (line 36) | func (m *Model) renderTopBar(r *rendering.Renderer) {
method renderSearchBar (line 43) | func (m *Model) renderSearchBar(r *rendering.Renderer) {
method renderFooter (line 48) | func (m *Model) renderFooter(r *rendering.Renderer, selectedCount uint) {
method renderColumnHeaders (line 72) | func (m *Model) renderColumnHeaders(r *rendering.Renderer) {
method renderFileEntries (line 80) | func (m *Model) renderFileEntries(r *rendering.Renderer) {
method getSortInfo (line 101) | func (m *Model) getSortInfo() (string, string) {
method getPanelModeInfo (line 109) | func (m *Model) getPanelModeInfo(selectedCount uint) (string, string) {
method getCursorString (line 120) | func (m *Model) getCursorString() string {
method renderSelectBox (line 128) | func (m *Model) renderSelectBox(isSelected bool) string {
method NeedsReRender (line 146) | func (m *Model) NeedsReRender() bool {
FILE: src/internal/ui/filepanel/selection_test.go
function TestPanelSelectionLifeCycle (line 9) | func TestPanelSelectionLifeCycle(t *testing.T) {
FILE: src/internal/ui/filepanel/sort.go
function getOrderingFunc (line 16) | func getOrderingFunc(elements []Element, reversed bool, sortKind sortmod...
function getSizeOrderingFunc (line 56) | func getSizeOrderingFunc(elements []Element, reversed bool) sliceOrderFu...
function getTypeOrderingFunc (line 85) | func getTypeOrderingFunc(elements []Element, reversed bool) sliceOrderFu...
function sortFileElement (line 113) | func sortFileElement(sortKind sortmodel.SortKind, reversed bool, dirEntr...
function isSymlinkToDir (line 137) | func isSymlinkToDir(location string, info os.FileInfo, name string) bool {
method getPageScrollSize (line 145) | func (m *Model) getPageScrollSize() int {
FILE: src/internal/ui/filepanel/types.go
type Model (line 16) | type Model struct
type directoryRecord (line 47) | type directoryRecord struct
type Element (line 53) | type Element struct
type PanelMode (line 61) | type PanelMode
constant SelectMode (line 65) | SelectMode PanelMode = iota
constant BrowserMode (line 66) | BrowserMode
type sliceOrderFunc (line 69) | type sliceOrderFunc
type columnRenderer (line 71) | type columnRenderer
type columnDefinition (line 73) | type columnDefinition struct
FILE: src/internal/ui/filepanel/update.go
method ChangeFilePanelMode (line 12) | func (m *Model) ChangeFilePanelMode() {
method UpdateCurrentFilePanelDir (line 25) | func (m *Model) UpdateCurrentFilePanelDir(path string) error {
method ParentDirectory (line 79) | func (m *Model) ParentDirectory() error {
method SelectAllItem (line 84) | func (m *Model) SelectAllItem() {
FILE: src/internal/ui/filepanel/utils.go
method GetCursor (line 5) | func (m *Model) GetCursor() int {
method GetRenderIndex (line 9) | func (m *Model) GetRenderIndex() int {
method GetFocusedItem (line 13) | func (m *Model) GetFocusedItem() Element {
method GetElementAtIdx (line 17) | func (m *Model) GetElementAtIdx(idx int) Element {
method GetFirstElement (line 24) | func (m *Model) GetFirstElement() Element {
method ResetSelected (line 28) | func (m *Model) ResetSelected() {
method GetFocusedItemPtr (line 34) | func (m *Model) GetFocusedItemPtr() *Element {
method SetSelected (line 43) | func (m *Model) SetSelected(location string) {
method SetUnSelected (line 48) | func (m *Model) SetUnSelected(location string) {
method ToggleSelected (line 54) | func (m *Model) ToggleSelected(location string) {
method SetSelectedAll (line 63) | func (m *Model) SetSelectedAll(locations []string) {
method CheckSelected (line 69) | func (m *Model) CheckSelected(location string) bool {
method GetSelectedLocations (line 75) | func (m *Model) GetSelectedLocations() []string {
method GetFirstSelectedLocation (line 83) | func (m *Model) GetFirstSelectedLocation() string {
method SingleItemSelect (line 99) | func (m *Model) SingleItemSelect() {
method ElemCount (line 105) | func (m *Model) ElemCount() int {
method SelectedCount (line 109) | func (m *Model) SelectedCount() uint {
method Empty (line 113) | func (m *Model) Empty() bool {
method EmptyOrInvalid (line 117) | func (m *Model) EmptyOrInvalid() bool {
method ToggleReverseSort (line 121) | func (m *Model) ToggleReverseSort() {
method SetCursorPosition (line 127) | func (m *Model) SetCursorPosition(cursor int) {
method FindElementIndexByName (line 131) | func (m *Model) FindElementIndexByName(name string) int {
method FindElementIndexByLocation (line 140) | func (m *Model) FindElementIndexByLocation(location string) int {
FILE: src/internal/ui/helpmenu/data.go
function getData (line 12) | func getData() []hotkeydata { //nolint: funlen // This should be self co...
function removeOrphanSections (line 266) | func removeOrphanSections(items []hotkeydata) []hotkeydata {
method filter (line 286) | func (m *Model) filter(query string) {
function fuzzySearch (line 301) | func fuzzySearch(query string, data []hotkeydata) []hotkeydata {
FILE: src/internal/ui/helpmenu/model_state.go
function New (line 11) | func New() Model {
method Open (line 25) | func (m *Model) Open() {
method Close (line 38) | func (m *Model) Close() {
method HandleKey (line 45) | func (m *Model) HandleKey(msg string) {
method handleNavKeys (line 58) | func (m *Model) handleNavKeys(msg string) {
method HandleTeaMsg (line 71) | func (m *Model) HandleTeaMsg(msg tea.Msg) tea.Cmd {
method SetDimensions (line 79) | func (m *Model) SetDimensions(width int, height int) {
FILE: src/internal/ui/helpmenu/navigation.go
method ListUp (line 6) | func (m *Model) ListUp() {
method ListDown (line 30) | func (m *Model) ListDown() {
FILE: src/internal/ui/helpmenu/render.go
method Render (line 13) | func (m *Model) Render() string {
method getRenderHotkeyLength (line 63) | func (m *Model) getRenderHotkeyLength() int {
method getContent (line 77) | func (m *Model) getContent(r *rendering.Renderer, renderHotkeyLength int...
FILE: src/internal/ui/helpmenu/type.go
type hotkeyType (line 5) | type hotkeyType
constant globalType (line 8) | globalType hotkeyType = iota
constant normalType (line 9) | normalType
constant selectType (line 10) | selectType
type Model (line 14) | type Model struct
type hotkeydata (line 25) | type hotkeydata struct
FILE: src/internal/ui/helpmenu/utils.go
method IsOpen (line 3) | func (m *Model) IsOpen() bool {
method GetHeight (line 7) | func (m *Model) GetHeight() int {
method GetWidth (line 11) | func (m *Model) GetWidth() int {
FILE: src/internal/ui/metadata/architecture.go
constant archI386 (line 13) | archI386 = "i386"
constant archX8664 (line 14) | archX8664 = "x86-64"
constant archARM (line 15) | archARM = "ARM"
constant archARM64 (line 16) | archARM64 = "ARM64"
constant archPPC (line 17) | archPPC = "PowerPC"
constant archPPC64 (line 18) | archPPC64 = "PowerPC64"
constant archRISCV (line 19) | archRISCV = "RISC-V"
constant archS390x (line 20) | archS390x = "s390x"
constant archSPARC64 (line 21) | archSPARC64 = "SPARC64"
constant archMIPS (line 22) | archMIPS = "MIPS"
function GetBinaryArchitecture (line 27) | func GetBinaryArchitecture(filePath string) (string, error) {
function getELFArchitecture (line 43) | func getELFArchitecture(filePath string) (string, error) {
function getPEArchitecture (line 54) | func getPEArchitecture(filePath string) (string, error) {
function getMachOArchitecture (line 65) | func getMachOArchitecture(filePath string) (string, error) {
function elfMachineToString (line 91) | func elfMachineToString(machine elf.Machine) string {
function peArchitectureToString (line 118) | func peArchitectureToString(machine uint16) string {
function machoCPUToString (line 133) | func machoCPUToString(cpu macho.Cpu) string {
FILE: src/internal/ui/metadata/architecture_test.go
function TestGetBinaryArchitecture_NonBinaryFile (line 13) | func TestGetBinaryArchitecture_NonBinaryFile(t *testing.T) {
function TestGetBinaryArchitecture_NonExistentFile (line 24) | func TestGetBinaryArchitecture_NonExistentFile(t *testing.T) {
function TestGetBinaryArchitecture_CurrentBinary (line 30) | func TestGetBinaryArchitecture_CurrentBinary(t *testing.T) {
function TestElfMachineToString (line 47) | func TestElfMachineToString(t *testing.T) {
function TestPeArchitectureToString (line 64) | func TestPeArchitectureToString(t *testing.T) {
FILE: src/internal/ui/metadata/const.go
constant keyValueSpacing (line 6) | keyValueSpacing = " "
constant keyValueSpacingLen (line 7) | keyValueSpacingLen = 1
constant fileStatErrorMsg (line 9) | fileStatErrorMsg = "Cannot load file stats"
constant linkFileBrokenMsg (line 10) | linkFileBrokenMsg = "Link file is broken!"
constant etFetchErrorMsg (line 11) | etFetchErrorMsg = "Errors while fetching metadata via exiftool"
constant keyName (line 13) | keyName = "Name"
constant keySize (line 14) | keySize = "Size"
constant keyDataModified (line 15) | keyDataModified = "Date Modified"
constant keyDataAccessed (line 16) | keyDataAccessed = "Date Accessed"
constant keyPermissions (line 17) | keyPermissions = "Permissions"
constant keyMd5Checksum (line 18) | keyMd5Checksum = "MD5Checksum"
constant keyOwner (line 19) | keyOwner = "Owner"
constant keyGroup (line 20) | keyGroup = "Group"
constant keyPath (line 21) | keyPath = "Path"
constant keyArchitecture (line 22) | keyArchitecture = "Architecture"
constant borderSize (line 23) | borderSize = 2
constant defaultCacheSize (line 26) | defaultCacheSize = 300
constant defaultCacheExpiration (line 27) | defaultCacheExpiration = 5 * time.Minute
FILE: src/internal/ui/metadata/metadata.go
type Metadata (line 17) | type Metadata struct
method GetPath (line 32) | func (m Metadata) GetPath() string {
method GetData (line 36) | func (m Metadata) GetData() [][2]string {
method GetValue (line 40) | func (m Metadata) GetValue(key string) (string, error) {
function NewMetadata (line 24) | func NewMetadata(data [][2]string, filepath string, infoMsg string) Meta...
function sortMetadata (line 54) | func sortMetadata(meta [][2]string) {
function GetMetadata (line 78) | func GetMetadata(filePath string, metadataFocused bool, et *exiftool.Exi...
function getSymLinkMetaData (line 84) | func getSymLinkMetaData(filePath string) Metadata {
function getMetaDataUnsorted (line 98) | func getMetaDataUnsorted(filePath string, metadataFocused bool, et *exif...
function updateExiftoolMetadata (line 152) | func updateExiftoolMetadata(filePath string, et *exiftool.Exiftool, res ...
FILE: src/internal/ui/metadata/metadata_test.go
function TestGetMetadata (line 15) | func TestGetMetadata(t *testing.T) {
FILE: src/internal/ui/metadata/metadata_unix.go
function getOwnerAndGroup (line 12) | func getOwnerAndGroup(fileInfo os.FileInfo) (string, string) {
FILE: src/internal/ui/metadata/metadata_windows.go
function getOwnerAndGroup (line 9) | func getOwnerAndGroup(_ os.FileInfo) (string, string) {
FILE: src/internal/ui/metadata/model.go
type Model (line 10) | type Model struct
method SetDimensions (line 35) | func (m *Model) SetDimensions(width int, height int) {
method GetHeight (line 40) | func (m *Model) GetHeight() int {
method GetWidth (line 44) | func (m *Model) GetWidth() int {
method ResetRenderIfInvalid (line 48) | func (m *Model) ResetRenderIfInvalid() {
method ResetRender (line 54) | func (m *Model) ResetRender() {
method MetadataLen (line 58) | func (m *Model) MetadataLen() int {
method ListUp (line 63) | func (m *Model) ListUp() {
method ListDown (line 75) | func (m *Model) ListDown() {
method SetBlank (line 83) | func (m *Model) SetBlank() {
method IsBlank (line 89) | func (m *Model) IsBlank() bool {
method SetInfoMsg (line 93) | func (m *Model) SetInfoMsg(msg string) {
method Render (line 97) | func (m *Model) Render(metadataFocused bool) string {
function New (line 27) | func New() Model {
FILE: src/internal/ui/metadata/model_test.go
function TestUpDown (line 9) | func TestUpDown(t *testing.T) {
FILE: src/internal/ui/metadata/update.go
method SetMetadataCache (line 5) | func (m *Model) SetMetadataCache(metadata Metadata, metadataFocused bool) {
method SetMetadata (line 9) | func (m *Model) SetMetadata(metadata Metadata, metadataFocused bool) {
method GetMetadataLocation (line 17) | func (m *Model) GetMetadataLocation() string {
method GetMetadataExpectedFocused (line 21) | func (m *Model) GetMetadataExpectedFocused() bool {
method SetMetadataLocationAndFocused (line 25) | func (m *Model) SetMetadataLocationAndFocused(filepath string, metadataF...
function cacheKey (line 30) | func cacheKey(filePath string, metadataFocused bool) string {
method UpdateMetadataIfExistsInCache (line 34) | func (m *Model) UpdateMetadataIfExistsInCache(filepath string, metadataF...
FILE: src/internal/ui/metadata/utils.go
function getMaxKeyLength (line 13) | func getMaxKeyLength(meta [][2]string) int {
function computeMetadataWidths (line 23) | func computeMetadataWidths(viewWidth, maxKeyLen int) (int, int) {
function formatMetadataLines (line 37) | func formatMetadataLines(meta [][2]string, startIdx, height, keyLen, val...
function computeRenderDimensions (line 49) | func computeRenderDimensions(metadata [][2]string, viewWidth int) (int, ...
function calculateMD5Checksum (line 56) | func calculateMD5Checksum(filePath string) (string, error) {
FILE: src/internal/ui/notify/model.go
type Model (line 7) | type Model struct
method GetTitle (line 23) | func (m *Model) GetTitle() string {
method GetContent (line 27) | func (m *Model) GetContent() string {
method IsOpen (line 31) | func (m *Model) IsOpen() bool {
method Open (line 35) | func (m *Model) Open() {
method Close (line 39) | func (m *Model) Close() {
method GetConfirmAction (line 43) | func (m *Model) GetConfirmAction() ConfirmActionType {
method Render (line 48) | func (m *Model) Render() string {
function New (line 14) | func New(open bool, title string, content string, confirmAction ConfirmA...
FILE: src/internal/ui/notify/type.go
type ConfirmActionType (line 3) | type ConfirmActionType
constant RenameAction (line 6) | RenameAction ConfirmActionType = iota
constant DeleteAction (line 7) | DeleteAction
constant QuitAction (line 8) | QuitAction
constant NoAction (line 9) | NoAction
constant PermanentDeleteAction (line 10) | PermanentDeleteAction
FILE: src/internal/ui/preview/model.go
type Model (line 11) | type Model struct
function New (line 27) | func New() Model {
FILE: src/internal/ui/preview/model_utils.go
method GetContent (line 5) | func (m *Model) GetContent() string {
method GetContentWidth (line 9) | func (m *Model) GetContentWidth() int {
method GetContentHeight (line 13) | func (m *Model) GetContentHeight() int {
method GetLocation (line 17) | func (m *Model) GetLocation() string {
method SetOpen (line 21) | func (m *Model) SetOpen(open bool) {
method SetLocation (line 25) | func (m *Model) SetLocation(location string) {
method SetLoading (line 29) | func (m *Model) SetLoading() {
method setContent (line 35) | func (m *Model) setContent(content string, width int, height int, locati...
method SetEmptyWithDimensions (line 43) | func (m *Model) SetEmptyWithDimensions(width int, height int) {
method IsLoading (line 47) | func (m *Model) IsLoading() bool {
method ToggleOpen (line 51) | func (m *Model) ToggleOpen() {
method CleanUp (line 55) | func (m *Model) CleanUp() {
method IsOpen (line 64) | func (m *Model) IsOpen() bool {
method Open (line 68) | func (m *Model) Open() {
method Close (line 72) | func (m *Model) Close() {
FILE: src/internal/ui/preview/render.go
function renderDirectoryPreview (line 25) | func renderDirectoryPreview(r *rendering.Renderer, itemPath string, prev...
method renderImagePreview (line 62) | func (m *Model) renderImagePreview(r *rendering.Renderer, itemPath strin...
method renderTextPreview (line 98) | func (m *Model) renderTextPreview(r *rendering.Renderer, itemPath string,
method RenderText (line 147) | func (m *Model) RenderText(text string) string {
method RenderTextWithDimension (line 151) | func (m *Model) RenderTextWithDimension(text string, height int, width i...
method RenderWithPath (line 163) | func (m *Model) RenderWithPath(itemPath string, previewWidth int, previe...
FILE: src/internal/ui/preview/render_test.go
function TestFilePreviewRenderWithDimensions (line 25) | func TestFilePreviewRenderWithDimensions(t *testing.T) {
FILE: src/internal/ui/preview/render_unix_test.go
function TestFilePreviewWithInvalidMode (line 16) | func TestFilePreviewWithInvalidMode(t *testing.T) {
FILE: src/internal/ui/preview/render_utils.go
function getBatSyntaxHighlightedContent (line 16) | func getBatSyntaxHighlightedContent(
function setBatBackground (line 46) | func setBatBackground(input string, background string) string {
function checkBatCmd (line 56) | func checkBatCmd() string {
function isImageFile (line 67) | func isImageFile(filename string) bool {
FILE: src/internal/ui/preview/update.go
type UpdateMsg (line 5) | type UpdateMsg struct
method GetReqID (line 29) | func (msg UpdateMsg) GetReqID() int {
method GetLocation (line 37) | func (msg UpdateMsg) GetLocation() string {
method GetContentWidth (line 41) | func (msg UpdateMsg) GetContentWidth() int {
method GetContentHeight (line 45) | func (msg UpdateMsg) GetContentHeight() int {
function NewUpdateMsg (line 19) | func NewUpdateMsg(location string, content string, width int, height int...
method Apply (line 33) | func (m *Model) Apply(msg UpdateMsg) {
FILE: src/internal/ui/processbar/const.go
constant minHeight (line 5) | minHeight = 2
constant minWidth (line 6) | minWidth = 2
constant msgChannelSize (line 10) | msgChannelSize = 50
constant borderSize (line 14) | borderSize = 2
constant progressBarRightPadding (line 17) | progressBarRightPadding = 3
constant processNameTruncatePadding (line 20) | processNameTruncatePadding = 7
constant linesPerProcess (line 23) | linesPerProcess = 3
FILE: src/internal/ui/processbar/error.go
type ProcessChannelFullError (line 3) | type ProcessChannelFullError struct
method Error (line 6) | func (p *ProcessChannelFullError) Error() string {
type NoProcessFoundError (line 10) | type NoProcessFoundError struct
method Error (line 14) | func (p *NoProcessFoundError) Error() string {
type ProcessAlreadyExistsError (line 18) | type ProcessAlreadyExistsError struct
method Error (line 22) | func (p *ProcessAlreadyExistsError) Error() string {
FILE: src/internal/ui/processbar/model.go
type Model (line 12) | type Model struct
method SetDimensions (line 46) | func (m *Model) SetDimensions(width int, height int) {
method AddProcess (line 59) | func (m *Model) AddProcess(p Process) error {
method AddOrUpdateProcess (line 67) | func (m *Model) AddOrUpdateProcess(p Process) {
method UpdateExistingProcess (line 71) | func (m *Model) UpdateExistingProcess(p Process) error {
method GetByID (line 79) | func (m *Model) GetByID(id string) (Process, bool) {
method HasRunningProcesses (line 84) | func (m *Model) HasRunningProcesses() bool {
method Render (line 93) | func (m *Model) Render(processBarFocused bool) string {
function New (line 28) | func New() Model {
function NewModelWithOptions (line 34) | func NewModelWithOptions(width int, height int) Model {
FILE: src/internal/ui/processbar/model_navigation.go
method ListUp (line 10) | func (m *Model) ListUp() {
method ListDown (line 29) | func (m *Model) ListDown() {
method cntRenderableProcess (line 45) | func (m *Model) cntRenderableProcess() int {
function cntRenderableProcess (line 50) | func cntRenderableProcess(footerHeight int) int {
FILE: src/internal/ui/processbar/model_navigation_test.go
function Test_cntRenderableProcess (line 10) | func Test_cntRenderableProcess(t *testing.T) {
function genProcessBarModel (line 21) | func genProcessBarModel(count int, cursor int, render int, viewHeight in...
function Test_processBarModelUpDown (line 39) | func Test_processBarModelUpDown(t *testing.T) {
FILE: src/internal/ui/processbar/model_test.go
function initGlobals (line 21) | func initGlobals() {
function TestMain (line 34) | func TestMain(m *testing.M) {
function TestModelProcessUtils (line 45) | func TestModelProcessUtils(t *testing.T) {
function TestModelSetDimenstions (line 96) | func TestModelSetDimenstions(t *testing.T) {
FILE: src/internal/ui/processbar/model_update.go
method ListenForChannelUpdates (line 8) | func (m *Model) ListenForChannelUpdates() {
method GetListenCmd (line 29) | func (m *Model) GetListenCmd() Cmd {
method trySendMsgToChannel (line 36) | func (m *Model) trySendMsgToChannel(msg UpdateMsg) error {
method sendMsgToChannelBlocking (line 47) | func (m *Model) sendMsgToChannelBlocking(msg UpdateMsg) {
method sendMsgToChannel (line 51) | func (m *Model) sendMsgToChannel(msg UpdateMsg, blocking bool) error {
method SendAddProcessMsg (line 59) | func (m *Model) SendAddProcessMsg(
method SendUpdateProcessMsg (line 76) | func (m *Model) SendUpdateProcessMsg(p Process, blockingSend bool) error {
method TrySendingUpdateProcessMsg (line 82) | func (m *Model) TrySendingUpdateProcessMsg(p Process) {
method SendStopListeningMsgBlocking (line 90) | func (m *Model) SendStopListeningMsgBlocking() {
FILE: src/internal/ui/processbar/model_update_test.go
function TestUpdateMsg (line 5) | func TestUpdateMsg(_ *testing.T) {
FILE: src/internal/ui/processbar/model_utils.go
method cntProcesses (line 9) | func (m *Model) cntProcesses() int {
method isValid (line 13) | func (m *Model) isValid() bool {
method viewHeight (line 18) | func (m *Model) viewHeight() int {
method viewWidth (line 22) | func (m *Model) viewWidth() int {
method GetHeight (line 26) | func (m *Model) GetHeight() int {
method GetWidth (line 30) | func (m *Model) GetWidth() int {
method getSortedProcesses (line 34) | func (m *Model) getSortedProcesses() []Process {
method newReqCnt (line 71) | func (m *Model) newReqCnt() int {
method newUUIDForProcess (line 77) | func (m *Model) newUUIDForProcess() string {
method GetProcessesSlice (line 82) | func (m *Model) GetProcessesSlice() []Process {
FILE: src/internal/ui/processbar/model_utils_test.go
function TestModelUtils (line 9) | func TestModelUtils(t *testing.T) {
FILE: src/internal/ui/processbar/operation.go
type OperationType (line 5) | type OperationType
method GetIcon (line 16) | func (op OperationType) GetIcon() string {
method GetVerb (line 34) | func (op OperationType) GetVerb() string {
method GetPastVerb (line 52) | func (op OperationType) GetPastVerb() string {
constant OpCopy (line 8) | OpCopy OperationType = iota
constant OpCut (line 9) | OpCut
constant OpDelete (line 10) | OpDelete
constant OpCompress (line 11) | OpCompress
constant OpExtract (line 12) | OpExtract
FILE: src/internal/ui/processbar/process.go
type Process (line 15) | type Process struct
method GetDisplayName (line 71) | func (p *Process) GetDisplayName() string {
method displayNameWithoutIcon (line 75) | func (p *Process) displayNameWithoutIcon() string {
function NewProcess (line 30) | func NewProcess(id string, currentFile string, operation OperationType, ...
type ProcessState (line 44) | type ProcessState
method Icon (line 55) | func (p ProcessState) Icon() string {
constant InOperation (line 47) | InOperation ProcessState = iota
constant Successful (line 48) | Successful
constant Cancelled (line 49) | Cancelled
constant Failed (line 50) | Failed
FILE: src/internal/ui/processbar/process_test.go
function TestGetDisplayName (line 11) | func TestGetDisplayName(t *testing.T) {
FILE: src/internal/ui/processbar/process_update_msg.go
type Cmd (line 3) | type Cmd
type UpdateMsg (line 5) | type UpdateMsg interface
type BaseMsg (line 11) | type BaseMsg struct
method GetReqID (line 15) | func (msg BaseMsg) GetReqID() int {
type newProcessMsg (line 19) | type newProcessMsg struct
method Apply (line 25) | func (msg newProcessMsg) Apply(m *Model) (Cmd, error) {
type updateProcessMsg (line 29) | type updateProcessMsg struct
method Apply (line 35) | func (msg updateProcessMsg) Apply(m *Model) (Cmd, error) {
type stopListeningMsg (line 41) | type stopListeningMsg struct
method Apply (line 45) | func (msg stopListeningMsg) Apply(_ *Model) (Cmd, error) {
FILE: src/internal/ui/prompt/consts.go
constant promptHeadlineText (line 8) | promptHeadlineText = "superfile Prompt"
constant OpenCommand (line 10) | OpenCommand = "open"
constant SplitCommand (line 11) | SplitCommand = "split"
constant CdCommand (line 12) | CdCommand = "cd"
constant spfPromptChar (line 15) | spfPromptChar = ">"
constant shellPromptChar (line 16) | shellPromptChar = ":"
constant successMessagePrefix (line 18) | successMessagePrefix = "Success"
constant failureMessagePrefix (line 19) | failureMessagePrefix = "Error"
constant shellModeString (line 21) | shellModeString = "(Shell Mode)"
constant spfModeString (line 22) | spfModeString = "(SPF Mode)"
constant tokenizationError (line 25) | tokenizationError = "Failed during tokenization"
constant splitCommandArgError (line 26) | splitCommandArgError = "split command should not be given arguments"
constant shellSubTimeout (line 29) | shellSubTimeout = 1000 * time.Millisecond
constant shellSubTimeoutInTests (line 30) | shellSubTimeoutInTests = 100 * time.Millisecond
constant defaultTestCwd (line 32) | defaultTestCwd = "/"
constant PromptMinWidth (line 34) | PromptMinWidth = 10
constant PromptMinHeight (line 35) | PromptMinHeight = 3
constant defaultTestWidth (line 37) | defaultTestWidth = 100
constant defaultTestMaxHeight (line 38) | defaultTestMaxHeight = 100
constant promptInputPadding (line 42) | promptInputPadding = 6
constant expectedArgCount (line 45) | expectedArgCount = 2
function modeString (line 48) | func modeString(shellMode bool) string {
function shellPrompt (line 55) | func shellPrompt(shellMode bool) string {
function defaultCommandSlice (line 62) | func defaultCommandSlice() []promptCommand {
FILE: src/internal/ui/prompt/error.go
type invalidCmdError (line 6) | type invalidCmdError struct
method Error (line 11) | func (e invalidCmdError) Error() string {
method Unwrap (line 18) | func (e invalidCmdError) Unwrap() error {
method uiMessage (line 22) | func (e invalidCmdError) uiMessage() string {
type envVarNotFoundError (line 26) | type envVarNotFoundError struct
method Error (line 30) | func (e envVarNotFoundError) Error() string {
type bracketMatchError (line 34) | type bracketMatchError struct
method Error (line 39) | func (p bracketMatchError) Error() string {
function roundBracketMatchError (line 43) | func roundBracketMatchError() bracketMatchError {
function curlyBracketMatchError (line 47) | func curlyBracketMatchError() bracketMatchError {
FILE: src/internal/ui/prompt/model.go
function DefaultModel (line 17) | func DefaultModel(maxHeight int, width int) Model {
function GenerateModel (line 22) | func GenerateModel(spfPromptHotkey string, shellPromptHotkey string, clo...
method HandleUpdate (line 40) | func (m *Model) HandleUpdate(msg tea.Msg, cwdLocation string) (common.Mo...
method handleConfirm (line 66) | func (m *Model) handleConfirm(cwdLocation string) common.ModelAction {
method handleNormalKeyInput (line 91) | func (m *Model) handleNormalKeyInput(msg tea.KeyMsg) tea.Cmd {
method HandleShellCommandResults (line 107) | func (m *Model) HandleShellCommandResults(retCode int, output string) {
method HandleSPFActionResults (line 122) | func (m *Model) HandleSPFActionResults(success bool, msg string) {
method Render (line 128) | func (m *Model) Render() string {
method Open (line 171) | func (m *Model) Open(shellMode bool) {
method setShellMode (line 177) | func (m *Model) setShellMode(shellMode bool) {
method Close (line 182) | func (m *Model) Close() {
method IsOpen (line 188) | func (m *Model) IsOpen() bool {
method IsShellMode (line 192) | func (m *Model) IsShellMode() bool {
method LastActionSucceeded (line 196) | func (m *Model) LastActionSucceeded() bool {
method GetWidth (line 200) | func (m *Model) GetWidth() int {
method GetMaxHeight (line 204) | func (m *Model) GetMaxHeight() int {
method SetWidth (line 208) | func (m *Model) SetWidth(width int) {
method SetMaxHeight (line 219) | func (m *Model) SetMaxHeight(maxHeight int) {
method validate (line 227) | func (m *Model) validate() bool {
method CloseOnSuccessIfNeeded (line 235) | func (m *Model) CloseOnSuccessIfNeeded() {
FILE: src/internal/ui/prompt/model_test.go
function initGlobals (line 22) | func initGlobals() {
function TestMain (line 35) | func TestMain(m *testing.M) {
function defaultTestModel (line 54) | func defaultTestModel() Model {
function TestModel_HandleUpdate (line 58) | func TestModel_HandleUpdate(t *testing.T) {
function TestModel_HandleResults (line 178) | func TestModel_HandleResults(t *testing.T) {
function TestModel_Render (line 246) | func TestModel_Render(t *testing.T) {
FILE: src/internal/ui/prompt/tokenize.go
function tokenizePromptCommand (line 16) | func tokenizePromptCommand(command string, cwdLocation string) ([]string...
function resolveShellSubstitution (line 25) | func resolveShellSubstitution(subCmdTimeout time.Duration, command strin...
function updateResCommand (line 61) | func updateResCommand(resCommand *strings.Builder, openChar rune, token ...
function findEndingBracket (line 92) | func findEndingBracket(r []rune, openIdx int, openParan rune, closeParan...
function isOpenBracket (line 113) | func isOpenBracket(r rune) bool {
function getClosingBracket (line 122) | func getClosingBracket(r rune) rune {
function tokenizeWithQuotes (line 134) | func tokenizeWithQuotes(command string) ([]string, error) {
FILE: src/internal/ui/prompt/tokenize_test.go
constant spfTestEnvVar1 (line 15) | spfTestEnvVar1 = "SPF_TEST_ENV_VAR1"
constant spfTestEnvVar2 (line 16) | spfTestEnvVar2 = "SPF_TEST_ENV_VAR2"
constant spfTestEnvVar3 (line 17) | spfTestEnvVar3 = "SPF_TEST_ENV_VAR3"
constant spfTestEnvVar4 (line 18) | spfTestEnvVar4 = "SPF_TEST_ENV_VAR4"
function Test_tokenizePromptCommand (line 27) | func Test_tokenizePromptCommand(t *testing.T) {
function Test_resolveShellSubstitution (line 88) | func Test_resolveShellSubstitution(t *testing.T) {
function Test_findEndingParenthesis (line 205) | func Test_findEndingParenthesis(t *testing.T) {
function Test_tokenizeWithQuotes (line 302) | func Test_tokenizeWithQuotes(t *testing.T) {
FILE: src/internal/ui/prompt/type.go
type Model (line 6) | type Model struct
type promptCommand (line 34) | type promptCommand struct
FILE: src/internal/ui/prompt/utils.go
function getPromptAction (line 10) | func getPromptAction(shellMode bool, value string, cwdLocation string) (...
function getFirstToken (line 68) | func getFirstToken(command string) string {
FILE: src/internal/ui/prompt/utils_test.go
function TestModel_getPromptAction (line 11) | func TestModel_getPromptAction(t *testing.T) {
function Test_getFirstToken (line 126) | func Test_getFirstToken(t *testing.T) {
FILE: src/internal/ui/rendering/border.go
type BorderConfig (line 11) | type BorderConfig struct
method SetTitle (line 39) | func (b *BorderConfig) SetTitle(title string) {
method SetInfoItems (line 43) | func (b *BorderConfig) SetInfoItems(infoItems ...string) {
method AreInfoItemsTruncated (line 50) | func (b *BorderConfig) AreInfoItemsTruncated() bool {
method AddDivider (line 67) | func (b *BorderConfig) AddDivider(idx int) {
method GetBorder (line 76) | func (b *BorderConfig) GetBorder(borderStrings lipgloss.Border) lipglo...
function NewBorderConfig (line 31) | func NewBorderConfig(height int, width int) BorderConfig {
FILE: src/internal/ui/rendering/constants.go
constant borderCornerWidth (line 6) | borderCornerWidth = 2
constant borderPaddingWidth (line 9) | borderPaddingWidth = 2
constant borderDividerWidth (line 12) | borderDividerWidth = 3
constant minTitleWidth (line 15) | minTitleWidth = 5
constant minInfoItemWidth (line 18) | minInfoItemWidth = 4
constant rendererNameMax (line 20) | rendererNameMax = 1000
constant MinWidthForBorder (line 22) | MinWidthForBorder = 2
constant MinHeightForBorder (line 23) | MinHeightForBorder = 2
FILE: src/internal/ui/rendering/content_renderer.go
type ContentRenderer (line 10) | type ContentRenderer struct
method CntLines (line 36) | func (r *ContentRenderer) CntLines() int {
method AddLines (line 40) | func (r *ContentRenderer) AddLines(lines ...string) {
method ClearLines (line 46) | func (r *ContentRenderer) ClearLines() {
method AddLineWithCustomTruncate (line 53) | func (r *ContentRenderer) AddLineWithCustomTruncate(lineStr string, tr...
method Render (line 73) | func (r *ContentRenderer) Render() string {
function NewContentRenderer (line 25) | func NewContentRenderer(maxLines int, maxLineWidth int, truncateStyle Tr...
FILE: src/internal/ui/rendering/content_renderer_test.go
function TestContentRendererBasic (line 9) | func TestContentRendererBasic(t *testing.T) {
FILE: src/internal/ui/rendering/renderer.go
type StyleModifier (line 13) | type StyleModifier
type Renderer (line 20) | type Renderer struct
type RendererConfig (line 73) | type RendererConfig struct
function DefaultRendererConfig (line 91) | func DefaultRendererConfig(totalHeight int, totalWidth int) RendererConf...
function NewRenderer (line 107) | func NewRenderer(cfg RendererConfig) (*Renderer, error) {
function NewRendererWithAutoFixConfig (line 114) | func NewRendererWithAutoFixConfig(cfg RendererConfig) *Renderer {
function createRendererWithValidatedConfig (line 119) | func createRendererWithValidatedConfig(cfg RendererConfig) *Renderer {
function validateAndAutoFix (line 160) | func validateAndAutoFix(cfg *RendererConfig) {
function validate (line 175) | func validate(cfg RendererConfig) error {
FILE: src/internal/ui/rendering/renderer_core.go
method AddLines (line 12) | func (r *Renderer) AddLines(lines ...string) *Renderer {
method AddSection (line 19) | func (r *Renderer) AddSection() {
method AddLineWithCustomTruncate (line 48) | func (r *Renderer) AddLineWithCustomTruncate(line string, truncateStyle ...
method AddStyleModifier (line 52) | func (r *Renderer) AddStyleModifier(modifier StyleModifier) *Renderer {
method SetBorderTitle (line 57) | func (r *Renderer) SetBorderTitle(title string) {
method SetBorderInfoItems (line 61) | func (r *Renderer) SetBorderInfoItems(infoItems ...string) {
method AreInfoItemsTruncated (line 65) | func (r *Renderer) AreInfoItemsTruncated() bool {
method Render (line 70) | func (r *Renderer) Render() string {
method Style (line 132) | func (r *Renderer) Style() lipgloss.Style {
FILE: src/internal/ui/rendering/renderer_test.go
constant sectionStr (line 15) | sectionStr = "<SECTION>"
function TestMain (line 18) | func TestMain(m *testing.M) {
function getDefaultTestRendererConfig (line 28) | func getDefaultTestRendererConfig(totalHeight int, totalWidth int, borde...
function getDefaultTestRenderer (line 53) | func getDefaultTestRenderer(totalHeight int, totalWidth int, borderRequi...
function TestRendererBasic (line 58) | func TestRendererBasic(t *testing.T) {
function TestSections (line 91) | func TestSections(t *testing.T) {
function TestDynamicHeight (line 230) | func TestDynamicHeight(t *testing.T) {
function TestBorders (line 293) | func TestBorders(t *testing.T) {
FILE: src/internal/ui/rendering/truncate.go
type TruncateStyle (line 9) | type TruncateStyle
constant PlainTruncateRight (line 14) | PlainTruncateRight = iota
constant TailsTruncateRight (line 15) | TailsTruncateRight
function TruncateBasedOnStyle (line 18) | func TruncateBasedOnStyle(line string, maxWidth int, truncateStyle Trunc...
FILE: src/internal/ui/rendering/truncate_test.go
function TestTruncate (line 11) | func TestTruncate(t *testing.T) {
FILE: src/internal/ui/sidebar/consts.go
constant sideBarInitialHeight (line 29) | sideBarInitialHeight = 3
constant searchBarPadding (line 34) | searchBarPadding = 5
constant directoryCapacityForDividers (line 36) | directoryCapacityForDividers = 2
constant dividerDirHeight (line 39) | dividerDirHeight = 3
constant minHeight (line 41) | minHeight = 5
constant minWidth (line 42) | minWidth = 7
FILE: src/internal/ui/sidebar/directory_utils.go
function fuzzySearch (line 18) | func fuzzySearch(query string, dirs []directory) []directory {
function getDirectories (line 44) | func getDirectories(pinnedMgr *PinnedManager, sections []string) []direc...
function getWellKnownDirectories (line 54) | func getWellKnownDirectories() []directory {
function getPinnedDirectoriesWithIcon (line 80) | func getPinnedDirectoriesWithIcon(pinnedMgr *PinnedManager) []directory {
function getFilteredDirectories (line 90) | func getFilteredDirectories(query string, pinnedMgr *PinnedManager, sect...
function formDirctorySlice (line 99) | func formDirctorySlice(homeDirectories []directory, pinnedDirectories []...
FILE: src/internal/ui/sidebar/disk_utils.go
function getExternalMediaFolders (line 15) | func getExternalMediaFolders() []directory {
function shouldListDisk (line 37) | func shouldListDisk(mountPoint string) bool {
function diskName (line 71) | func diskName(mountPoint string) string {
function diskLocation (line 85) | func diskLocation(mountPoint string) string {
FILE: src/internal/ui/sidebar/navigation.go
method ListUp (line 9) | func (s *Model) ListUp() {
method ListDown (line 32) | func (s *Model) ListDown() {
method lastRenderedIndex (line 62) | func (s *Model) lastRenderedIndex(startIndex int) int {
method firstRenderedIndex (line 78) | func (s *Model) firstRenderedIndex(endIndex int) int {
method updateRenderIndex (line 98) | func (s *Model) updateRenderIndex() {
FILE: src/internal/ui/sidebar/navigation_test.go
function Test_lastRenderIndex (line 11) | func Test_lastRenderIndex(t *testing.T) {
function Test_firstRenderIndex (line 85) | func Test_firstRenderIndex(t *testing.T) {
function Test_updateRenderIndex (line 226) | func Test_updateRenderIndex(t *testing.T) {
function Test_listUp (line 319) | func Test_listUp(t *testing.T) {
function Test_listDown (line 397) | func Test_listDown(t *testing.T) {
FILE: src/internal/ui/sidebar/pinned.go
type PinnedManager (line 13) | type PinnedManager struct
method Load (line 28) | func (mgr *PinnedManager) Load() []directory {
method Save (line 50) | func (mgr *PinnedManager) Save(dirs []directory) error {
method Toggle (line 64) | func (mgr *PinnedManager) Toggle(dir string) error {
method Clean (line 91) | func (mgr *PinnedManager) Clean(dirs []directory) []directory {
function NewPinnedFileManager (line 17) | func NewPinnedFileManager(filePath string) PinnedManager {
FILE: src/internal/ui/sidebar/pinned_test.go
function Test_Load (line 15) | func Test_Load(t *testing.T) {
function Test_Save (line 101) | func Test_Save(t *testing.T) {
function Test_Toggle (line 159) | func Test_Toggle(t *testing.T) {
function Test_Clean (line 215) | func Test_Clean(t *testing.T) {
FILE: src/internal/ui/sidebar/render.go
method Render (line 14) | func (s *Model) Render(sidebarFocused bool, currentFilePanelLocation str...
method directoriesRender (line 36) | func (s *Model) directoriesRender(curFilePanelFileLocation string,
FILE: src/internal/ui/sidebar/sidebar.go
method PinnedItemRename (line 14) | func (s *Model) PinnedItemRename() {
method CancelSidebarRename (line 29) | func (s *Model) CancelSidebarRename() {
method ConfirmSidebarRename (line 35) | func (s *Model) ConfirmSidebarRename() {
method UpdateState (line 60) | func (s *Model) UpdateState(msg tea.Msg) tea.Cmd {
method HandleSearchBarKey (line 75) | func (s *Model) HandleSearchBarKey(msg string) {
method UpdateDirectories (line 87) | func (s *Model) UpdateDirectories() {
method TogglePinnedDirectory (line 103) | func (s *Model) TogglePinnedDirectory(dir string) error {
function New (line 108) | func New() Model {
FILE: src/internal/ui/sidebar/type.go
type directory (line 5) | type directory struct
type Model (line 10) | type Model struct
FILE: src/internal/ui/sidebar/utils.go
method isDivider (line 6) | func (d directory) isDivider() bool {
method requiredHeight (line 11) | func (d directory) requiredHeight() int {
method NoActualDir (line 19) | func (s *Model) NoActualDir() bool {
method isCursorInvalid (line 29) | func (s *Model) isCursorInvalid() bool {
method resetCursor (line 34) | func (s *Model) resetCursor() {
method SearchBarFocused (line 48) | func (s *Model) SearchBarFocused() bool {
method SearchBarBlur (line 53) | func (s *Model) SearchBarBlur() {
method SearchBarFocus (line 58) | func (s *Model) SearchBarFocus() {
method IsRenaming (line 63) | func (s *Model) IsRenaming() bool {
method GetCurrentDirectoryLocation (line 68) | func (s *Model) GetCurrentDirectoryLocation() string {
method pinnedIndexRange (line 77) | func (s *Model) pinnedIndexRange() (int, int) {
method GetWidth (line 112) | func (m *Model) GetWidth() int {
method GetHeight (line 117) | func (m *Model) GetHeight() int {
method SetHeight (line 122) | func (m *Model) SetHeight(height int) {
method Disabled (line 131) | func (m *Model) Disabled() bool {
FILE: src/internal/ui/sidebar/utils_test.go
function defaultTestModel (line 12) | func defaultTestModel(cursor int, renderIndex int, height int,
function testModel (line 18) | func testModel(cursor int, renderIndex int, height int, sections []string,
function dirSlice (line 29) | func dirSlice(count int) []directory {
function Test_noActualDir (line 37) | func Test_noActualDir(t *testing.T) {
function Test_isCursorInvalid (line 71) | func Test_isCursorInvalid(t *testing.T) {
function Test_resetCursor (line 106) | func Test_resetCursor(t *testing.T) {
function TestSidebarSectionsVisibility (line 142) | func TestSidebarSectionsVisibility(t *testing.T) {
FILE: src/internal/ui/sortmodel/const.go
constant sortOptionsDefaultWidth (line 4) | sortOptionsDefaultWidth = 20
constant sortOptionsDefaultHeight (line 5) | sortOptionsDefaultHeight = 4
constant SortTypeCount (line 6) | SortTypeCount = 4
FILE: src/internal/ui/sortmodel/model.go
function New (line 3) | func New() Model {
FILE: src/internal/ui/sortmodel/navigation.go
method ListUp (line 3) | func (m *Model) ListUp() {
method ListDown (line 7) | func (m *Model) ListDown() {
FILE: src/internal/ui/sortmodel/render.go
method Render (line 12) | func (m *Model) Render() string {
FILE: src/internal/ui/sortmodel/types.go
type SortKind (line 3) | type SortKind
constant SortByName (line 7) | SortByName SortKind = iota
constant SortBySize (line 8) | SortBySize
constant SortByDate (line 9) | SortByDate
constant SortByType (line 10) | SortByType
constant SortByNatural (line 11) | SortByNatural
type Model (line 23) | type Model struct
FILE: src/internal/ui/sortmodel/utils.go
method IsOpen (line 3) | func (m *Model) IsOpen() bool {
method Open (line 7) | func (m *Model) Open(curSortKind SortKind) {
method Close (line 12) | func (m *Model) Close() {
method GetSelectedKind (line 17) | func (m *Model) GetSelectedKind() SortKind {
FILE: src/internal/ui/spf_renderers.go
function SidebarRenderer (line 10) | func SidebarRenderer(totalHeight int, totalWidth int, sidebarFocused boo...
function FilePanelRenderer (line 30) | func FilePanelRenderer(totalHeight int, totalWidth int, filePanelFocused...
function FilePreviewPanelRenderer (line 49) | func FilePreviewPanelRenderer(totalHeight int, totalWidth int) *renderin...
function PromptRenderer (line 66) | func PromptRenderer(totalHeight int, totalWidth int) *rendering.Renderer {
function ZoxideRenderer (line 82) | func ZoxideRenderer(totalHeight int, totalWidth int) *rendering.Renderer {
function HelpMenuRenderer (line 86) | func HelpMenuRenderer(totalHeight int, totalWidth int) *rendering.Render...
function DefaultFooterRenderer (line 101) | func DefaultFooterRenderer(totalHeight int, totalWidth int, focused bool...
function ProcessBarRenderer (line 122) | func ProcessBarRenderer(totalHeight int, totalWidth int, processBarFocus...
function MetadataRenderer (line 126) | func MetadataRenderer(totalHeight int, totalWidth int, metadataFocused b...
function ClipboardRenderer (line 130) | func ClipboardRenderer(totalHeight int, totalWidth int) *rendering.Rende...
function DefaultLipglossBorder (line 134) | func DefaultLipglossBorder() lipgloss.Border {
FILE: src/internal/ui/zoxide/consts.go
constant zoxideHeadlineText (line 4) | zoxideHeadlineText = "Zoxide Navigation"
constant ZoxideMinWidth (line 6) | ZoxideMinWidth = 15
constant ZoxideMinHeight (line 7) | ZoxideMinHeight = 3
constant maxVisibleResults (line 9) | maxVisibleResults = 5
constant scoreColumnWidth (line 13) | scoreColumnWidth = 13
constant modalInputPadding (line 16) | modalInputPadding = 6
FILE: src/internal/ui/zoxide/model.go
function DefaultModel (line 16) | func DefaultModel(maxHeight int, width int, zClient *zoxidelib.Client) M...
function GenerateModel (line 20) | func GenerateModel(zClient *zoxidelib.Client, maxHeight int, width int) ...
method HandleUpdate (line 34) | func (m *Model) HandleUpdate(msg tea.Msg) (common.ModelAction, tea.Cmd) {
method handleConfirm (line 90) | func (m *Model) handleConfirm() common.ModelAction {
method handleNormalKeyInput (line 103) | func (m *Model) handleNormalKeyInput(msg tea.KeyMsg) tea.Cmd {
method GetQueryCmd (line 109) | func (m *Model) GetQueryCmd(query string) tea.Cmd {
method Apply (line 131) | func (msg UpdateMsg) Apply(m *Model) tea.Cmd {
FILE: src/internal/ui/zoxide/model_test.go
function TestMain (line 16) | func TestMain(m *testing.M) {
function TestHandleConfirmWithValidSelection (line 25) | func TestHandleConfirmWithValidSelection(t *testing.T) {
function TestHandleConfirmWithNoResults (line 36) | func TestHandleConfirmWithNoResults(t *testing.T) {
function TestHandleConfirmWithInvalidCursor (line 45) | func TestHandleConfirmWithInvalidCursor(t *testing.T) {
function TestJKKeyHandling (line 55) | func TestJKKeyHandling(t *testing.T) {
function TestApplyWithMatchingQuery (line 94) | func TestApplyWithMatchingQuery(t *testing.T) {
function TestApplyWithStaleQuery (line 115) | func TestApplyWithStaleQuery(t *testing.T) {
FILE: src/internal/ui/zoxide/navigation.go
method navigateUp (line 3) | func (m *Model) navigateUp() {
method navigateDown (line 15) | func (m *Model) navigateDown() {
method updateRenderIndex (line 27) | func (m *Model) updateRenderIndex() {
FILE: src/internal/ui/zoxide/navigation_test.go
function TestNavigation (line 9) | func TestNavigation(t *testing.T) {
function TestUpdateRenderIndex (line 75) | func TestUpdateRenderIndex(t *testing.T) {
FILE: src/internal/ui/zoxide/render.go
method Render (line 11) | func (m *Model) Render() string {
method renderResultList (line 31) | func (m *Model) renderResultList(r *rendering.Renderer) {
method renderVisibleResults (line 44) | func (m *Model) renderVisibleResults(r *rendering.Renderer, endIndex int) {
method renderScrollIndicators (line 67) | func (m *Model) renderScrollIndicators(r *rendering.Renderer, endIndex i...
FILE: src/internal/ui/zoxide/render_test.go
function TestRenderWithNilZClient (line 10) | func TestRenderWithNilZClient(t *testing.T) {
function TestRenderWithEmptyResults (line 18) | func TestRenderWithEmptyResults(t *testing.T) {
function TestRenderWithResults (line 26) | func TestRenderWithResults(t *testing.T) {
function TestRenderWithTextInput (line 44) | func TestRenderWithTextInput(t *testing.T) {
function TestRenderScrollIndicator (line 53) | func TestRenderScrollIndicator(t *testing.T) {
FILE: src/internal/ui/zoxide/test_helpers.go
function setupTestModel (line 12) | func setupTestModel() Model {
function setupTestModelWithClient (line 16) | func setupTestModelWithClient(t *testing.T) Model {
function setupTestModelWithResults (line 29) | func setupTestModelWithResults(resultCount int) Model {
FILE: src/internal/ui/zoxide/type.go
type Model (line 9) | type Model struct
type UpdateMsg (line 33) | type UpdateMsg struct
method GetReqID (line 47) | func (msg UpdateMsg) GetReqID() int {
function NewUpdateMsg (line 39) | func NewUpdateMsg(query string, results []zoxidelib.Result, reqID int) U...
FILE: src/internal/ui/zoxide/utils.go
method Open (line 11) | func (m *Model) Open() tea.Cmd {
method Close (line 21) | func (m *Model) Close() {
method IsOpen (line 30) | func (m *Model) IsOpen() bool {
method GetWidth (line 34) | func (m *Model) GetWidth() int {
method GetMaxHeight (line 38) | func (m *Model) GetMaxHeight() int {
method SetWidth (line 42) | func (m *Model) SetWidth(width int) {
method SetMaxHeight (line 53) | func (m *Model) SetMaxHeight(maxHeight int) {
method GetResults (line 61) | func (m *Model) GetResults() []zoxidelib.Result {
method GetTextInputValue (line 67) | func (m *Model) GetTextInputValue() string {
function isKeyAlphaNum (line 71) | func isKeyAlphaNum(msg tea.KeyMsg) bool {
FILE: src/internal/ui/zoxide/utils_test.go
function TestIsKeyAlphaNum (line 10) | func TestIsKeyAlphaNum(t *testing.T) {
function TestOpenResetsState (line 24) | func TestOpenResetsState(t *testing.T) {
function TestCloseClearsState (line 38) | func TestCloseClearsState(t *testing.T) {
function TestGetResultsReturnsCopy (line 54) | func TestGetResultsReturnsCopy(t *testing.T) {
function TestSetWidthBoundsChecking (line 69) | func TestSetWidthBoundsChecking(t *testing.T) {
function TestSetMaxHeightBoundsChecking (line 79) | func TestSetMaxHeightBoundsChecking(t *testing.T) {
FILE: src/internal/validation.go
constant minLinesForBorder (line 15) | minLinesForBorder = 3
method validateLayout (line 18) | func (m *model) validateLayout() error { //nolint:gocognit // cumilation...
function validateRender (line 128) | func validateRender(out string, height int, width int, border bool) error {
function validateRenderBorderValidations (line 168) | func validateRenderBorderValidations(lines []string) error {
method validateComponentRender (line 215) | func (m *model) validateComponentRender() error {
method validateFinalRender (line 282) | func (m *model) validateFinalRender() error { //nolint:gocognit // cumil...
method validateComponentPlacement (line 383) | func (m *model) validateComponentPlacement(lines []string, pos compPosit...
method extractComponent (line 399) | func (m *model) extractComponent(lines []string, pos compPosition) ([]st...
type compPosition (line 419) | type compPosition struct
method IsOverlayModelOpen (line 426) | func (m *model) IsOverlayModelOpen() bool {
FILE: src/internal/wheel_function.go
function wheelMainAction (line 9) | func wheelMainAction(msg string, m *model) {
FILE: src/pkg/cache/cache.go
type cacheItemInternal (line 8) | type cacheItemInternal struct
type Cache (line 13) | type Cache struct
function New (line 20) | func New[T any](maxEntries int, expiration time.Duration) *Cache[T] {
method periodicCleanup (line 34) | func (c *Cache[T]) periodicCleanup() {
method cleanupExpired (line 45) | func (c *Cache[T]) cleanupExpired() {
method Get (line 57) | func (c *Cache[T]) Get(key string) (T, bool) {
method Set (line 68) | func (c *Cache[T]) Set(key string, obj T) {
method evictOldest (line 84) | func (c *Cache[T]) evictOldest() {
FILE: src/pkg/file_preview/ansi.go
function ConvertImageToANSI (line 13) | func ConvertImageToANSI(img image.Image, defaultBGColor color.Color) str...
method ANSIRenderer (line 45) | func (p *ImagePreviewer) ANSIRenderer(img image.Image, defaultBGColor st...
type colorCache (line 57) | type colorCache struct
method getTermenvColor (line 67) | func (c *colorCache) getTermenvColor(col color.Color, fallbackColor st...
function newColorCache (line 61) | func newColorCache() *colorCache {
FILE: src/pkg/file_preview/constants.go
constant defaultImagePreviewCacheSize (line 8) | defaultImagePreviewCacheSize = 100
constant defaultCacheExpiration (line 9) | defaultCacheExpiration = 5 * time.Minute
constant heightScaleFactor (line 12) | heightScaleFactor = 2
constant rgbShift16 (line 13) | rgbShift16 = 16
constant rgbShift8 (line 14) | rgbShift8 = 8
constant kittyHashSeed (line 17) | kittyHashSeed = 42
constant kittyHashPrime (line 18) | kittyHashPrime = 31
constant kittyMaxID (line 19) | kittyMaxID = 0xFFFF
constant kittyNonZeroOffset (line 20) | kittyNonZeroOffset = 1000
constant rgbMask (line 23) | rgbMask = 0xFF
constant alphaOpaque (line 24) | alphaOpaque = 255
constant maxVideoFileSizeForThumb (line 26) | maxVideoFileSizeForThumb = "104857600"
constant thumbOutputExt (line 27) | thumbOutputExt = ".jpg"
constant thumbGenerationTimeout (line 28) | thumbGenerationTimeout = 30 * time.Second
FILE: src/pkg/file_preview/image_preview.go
type ImageRenderer (line 18) | type ImageRenderer
method String (line 25) | func (f ImageRenderer) String() string {
constant RendererANSI (line 21) | RendererANSI ImageRenderer = iota
constant RendererKitty (line 22) | RendererKitty
function getPreviewObjKey (line 36) | func getPreviewObjKey(path string, dim string, renderer ImageRenderer) s...
type ImagePreviewer (line 41) | type ImagePreviewer struct
method ImagePreview (line 65) | func (p *ImagePreviewer) ImagePreview(path string, maxWidth int, maxHe...
method ImagePreviewWithRenderer (line 115) | func (p *ImagePreviewer) ImagePreviewWithRenderer(path string, maxWidt...
function NewImagePreviewer (line 47) | func NewImagePreviewer() *ImagePreviewer {
function NewImagePreviewerWithConfig (line 52) | func NewImagePreviewerWithConfig(maxEntries int, expiration time.Duratio...
FILE: src/pkg/file_preview/image_resize.go
function prepareImageForPreview (line 13) | func prepareImageForPreview(data []byte) (image.Image, int, int, error) {
function limitImageResolution (line 36) | func limitImageResolution(img image.Image, originalWidth, originalHeight...
function adjustImageOrientation (line 50) | func adjustImageOrientation(r *bytes.Reader, img image.Image) image.Image {
function adjustOrientation (line 70) | func adjustOrientation(img image.Image, orientation int) image.Image {
function resizeForANSI (line 95) | func resizeForANSI(img image.Image, maxWidth, maxHeight int) image.Image {
FILE: src/pkg/file_preview/kitty.go
function isKittyCapable (line 17) | func isKittyCapable() bool {
function ClearKittyImages (line 48) | func ClearKittyImages() string {
method ClearKittyImages (line 57) | func (p *ImagePreviewer) ClearKittyImages() string {
function generateKittyClearCommands (line 66) | func generateKittyClearCommands() string {
function generatePlacementID (line 84) | func generatePlacementID(path string) uint32 {
method renderWithKittyUsingTermCap (line 98) | func (p *ImagePreviewer) renderWithKittyUsingTermCap(img image.Image, pa...
method IsKittyCapable (line 166) | func (p *ImagePreviewer) IsKittyCapable() bool {
FILE: src/pkg/file_preview/thumbnail_generator.go
type thumbnailGeneratorInterface (line 18) | type thumbnailGeneratorInterface interface
type VideoGenerator (line 23) | type VideoGenerator struct
method supportsExt (line 33) | func (g *VideoGenerator) supportsExt(ext string) bool {
method generateThumbnail (line 37) | func (g *VideoGenerator) generateThumbnail(inputPath string, outputPat...
function newVideoGenerator (line 25) | func newVideoGenerator() (*VideoGenerator, error) {
type pdfGenerator (line 67) | type pdfGenerator struct
method supportsExt (line 77) | func (g *pdfGenerator) supportsExt(ext string) bool {
method generateThumbnail (line 81) | func (g *pdfGenerator) generateThumbnail(inputPath string, outputPathW...
function newPdfGenerator (line 69) | func newPdfGenerator() (*pdfGenerator, error) {
type ThumbnailGenerator (line 103) | type ThumbnailGenerator struct
method SupportsExt (line 144) | func (g *ThumbnailGenerator) SupportsExt(ext string) bool {
method GetThumbnailOrGenerate (line 154) | func (g *ThumbnailGenerator) GetThumbnailOrGenerate(path string) (stri...
method generateThumbnail (line 182) | func (g *ThumbnailGenerator) generateThumbnail(path string) (string, e...
method CleanUp (line 207) | func (g *ThumbnailGenerator) CleanUp() error {
function NewThumbnailGenerator (line 113) | func NewThumbnailGenerator() (*ThumbnailGenerator, error) {
function isPopplerInstalled (line 211) | func isPopplerInstalled() bool {
function isFFmpegInstalled (line 216) | func isFFmpegInstalled() bool {
FILE: src/pkg/file_preview/utils.go
constant DefaultPixelsPerColumn (line 16) | DefaultPixelsPerColumn = 10
constant DefaultPixelsPerRow (line 17) | DefaultPixelsPerRow = 20
constant WindowsPixelsPerColumn (line 18) | WindowsPixelsPerColumn = 8
constant WindowsPixelsPerRow (line 19) | WindowsPixelsPerRow = 16
type TerminalCellSize (line 23) | type TerminalCellSize struct
type TerminalCapabilities (line 29) | type TerminalCapabilities struct
method InitTerminalCapabilities (line 48) | func (tc *TerminalCapabilities) InitTerminalCapabilities() {
method GetTerminalCellSize (line 63) | func (tc *TerminalCapabilities) GetTerminalCellSize() TerminalCellSize {
method detectTerminalCellSize (line 84) | func (tc *TerminalCapabilities) detectTerminalCellSize() TerminalCellS...
function NewTerminalCapabilities (line 36) | func NewTerminalCapabilities() *TerminalCapabilities {
type winsize (line 75) | type winsize struct
function getDefaultCellSize (line 112) | func getDefaultCellSize() TerminalCellSize {
method InitTerminalCapabilities (line 120) | func (p *ImagePreviewer) InitTerminalCapabilities() {
function getTerminalCellSizeWindows (line 126) | func getTerminalCellSizeWindows() (TerminalCellSize, bool) {
function getWindowsDefaultCellSize (line 140) | func getWindowsDefaultCellSize() TerminalCellSize {
function hexToColor (line 147) | func hexToColor(hex string) (color.RGBA, error) {
function colorToHex (line 163) | func colorToHex(color color.Color) string {
FILE: src/pkg/file_preview/utils_unix.go
function getTerminalCellSizeViaIoctl (line 12) | func getTerminalCellSizeViaIoctl() (TerminalCellSize, bool) {
function getTerminalSizeFromFd (line 30) | func getTerminalSizeFromFd(fd uintptr) (TerminalCellSize, bool) {
FILE: src/pkg/file_preview/utils_windows.go
function getTerminalCellSizeViaIoctl (line 7) | func getTerminalCellSizeViaIoctl() (TerminalCellSize, bool) {
FILE: src/pkg/string_function/overplace.go
type whitespace (line 22) | type whitespace struct
method render (line 30) | func (w whitespace) render(width int) string {
type WhitespaceOption (line 27) | type WhitespaceOption
function PlaceOverlay (line 60) | func PlaceOverlay(x, y int, fg, bg string, opts ...WhitespaceOption) str...
function clamp (line 117) | func clamp(v, lower, upper int) int {
function getLines (line 123) | func getLines(s string) ([]string, int) {
FILE: src/pkg/utils/bool_file_store.go
function ReadBoolFile (line 12) | func ReadBoolFile(path string, defaultValue bool) bool {
function WriteBoolFile (line 33) | func WriteBoolFile(path string, value bool) error {
FILE: src/pkg/utils/bool_file_store_test.go
function TestReadBoolFile (line 13) | func TestReadBoolFile(t *testing.T) {
function TestWriteBoolFile (line 101) | func TestWriteBoolFile(t *testing.T) {
function TestWriteBoolFileError (line 148) | func TestWriteBoolFileError(t *testing.T) {
function TestReadBoolFilePermissionDenied (line 156) | func TestReadBoolFilePermissionDenied(t *testing.T) {
function TestWriteBoolFilePermissionDenied (line 187) | func TestWriteBoolFilePermissionDenied(t *testing.T) {
function TestReadBoolFile_CornerCases (line 210) | func TestReadBoolFile_CornerCases(t *testing.T) {
FILE: src/pkg/utils/config_interface.go
type MissingFieldIgnorer (line 6) | type MissingFieldIgnorer interface
FILE: src/pkg/utils/consts.go
constant TrueString (line 4) | TrueString = "true"
constant FalseString (line 5) | FalseString = "false"
constant OsWindows (line 8) | OsWindows = "windows"
constant OsDarwin (line 10) | OsDarwin = "darwin"
constant OsLinux (line 11) | OsLinux = "linux"
constant ConfigFilePerm (line 14) | ConfigFilePerm = 0600
constant UserFilePerm (line 15) | UserFilePerm = 0644
constant LogFilePerm (line 16) | LogFilePerm = 0600
constant ConfigDirPerm (line 19) | ConfigDirPerm = 0700
constant UserDirPerm (line 20) | UserDirPerm = 0755
constant ExtractedFileMode (line 23) | ExtractedFileMode = 0644
constant ExtractedDirMode (line 24) | ExtractedDirMode = 0755
constant SidebarSectionHome (line 27) | SidebarSectionHome = "home"
constant SidebarSectionPinned (line 28) | SidebarSectionPinned = "pinned"
constant SidebarSectionDisks (line 29) | SidebarSectionDisks = "disks"
FILE: src/pkg/utils/detach_unix.go
function DetachFromTerminal (line 10) | func DetachFromTerminal(cmd *exec.Cmd) {
FILE: src/pkg/utils/detach_windows.go
function DetachFromTerminal (line 7) | func DetachFromTerminal(cmd *exec.Cmd) {
FILE: src/pkg/utils/error.go
type TomlLoadError (line 7) | type TomlLoadError struct
method Error (line 14) | func (t *TomlLoadError) Error() string {
method IsFatal (line 22) | func (t *TomlLoadError) IsFatal() bool {
method MissingFields (line 26) | func (t *TomlLoadError) MissingFields() bool {
method Unwrap (line 30) | func (t *TomlLoadError) Unwrap() error {
method UpdateMessageAndError (line 34) | func (t *TomlLoadError) UpdateMessageAndError(msg string, err error) {
method AddMessageAndError (line 40) | func (t *TomlLoadError) AddMessageAndError(msg string, err error) {
FILE: src/pkg/utils/file_utils.go
function WriteTomlData (line 25) | func WriteTomlData(filePath string, data interface{}) error {
function LoadTomlFile (line 40) | func LoadTomlFile(filePath string, defaultData string, target interface{},
function fixTomlFile (line 131) | func fixTomlFile(resultErr *TomlLoadError, filePath string, target inter...
function ResolveAbsPath (line 195) | func ResolveAbsPath(currentDir string, path string) string {
function DirSize (line 212) | func DirSize(path string) int64 {
function CreateDirectories (line 235) | func CreateDirectories(dirs ...string) error {
function CreateFiles (line 248) | func CreateFiles(files ...string) error {
function ReadFileContent (line 259) | func ReadFileContent(filepath string, maxLineLength int, previewLine int...
function InitJSONFile (line 284) | func InitJSONFile(path string) error {
FILE: src/pkg/utils/file_utils_test.go
function TestResolveAbsPath (line 17) | func TestResolveAbsPath(t *testing.T) {
function TestLoadTomlFile (line 80) | func TestLoadTomlFile(t *testing.T) {
function TestLoadTomlFileIgnorer (line 149) | func TestLoadTomlFileIgnorer(t *testing.T) {
function TestReadFileContent (line 331) | func TestReadFileContent(t *testing.T) {
function TestReadFileContentBOMHandling (line 378) | func TestReadFileContentBOMHandling(t *testing.T) {
FILE: src/pkg/utils/fzf_utils.go
function FzfSearch (line 6) | func FzfSearch(query string, source []string) []fzf.MatchResult {
FILE: src/pkg/utils/log_utils.go
function PrintlnAndExit (line 12) | func PrintlnAndExit(args ...any) {
function PrintfAndExitf (line 20) | func PrintfAndExitf(format string, args ...any) {
function SetRootLoggerToStdout (line 26) | func SetRootLoggerToStdout(debug bool) {
function SetRootLoggerToDiscarded (line 36) | func SetRootLoggerToDiscarded() {
FILE: src/pkg/utils/shell_utils.go
function ExecuteCommandInShell (line 14) | func ExecuteCommandInShell(timeLimit time.Duration, cmdDir string, shell...
function ExecuteCommand (line 27) | func ExecuteCommand(timeLimit time.Duration, cmdDir string, baseCmd stri...
FILE: src/pkg/utils/tea_utils.go
function TeaRuneKeyMsg (line 5) | func TeaRuneKeyMsg(msg string) tea.KeyMsg {
FILE: src/pkg/utils/test_utils.go
type TestTOMLType (line 12) | type TestTOMLType struct
type TestTOMLMissingIgnorerType (line 19) | type TestTOMLMissingIgnorerType struct
method GetIgnoreMissingFields (line 27) | func (t TestTOMLMissingIgnorerType) GetIgnoreMissingFields() bool {
method WithIgnoreMissing (line 31) | func (t TestTOMLMissingIgnorerType) WithIgnoreMissing(val bool) TestTO...
function SetupDirectories (line 36) | func SetupDirectories(t *testing.T, dirs ...string) {
function SetupFilesWithData (line 47) | func SetupFilesWithData(t *testing.T, data []byte, files ...string) {
function SetupFiles (line 55) | func SetupFiles(t *testing.T, files ...string) {
FILE: src/pkg/utils/ui_utils.go
constant CntFooterPanels (line 3) | CntFooterPanels = 3
constant BorderPaddingForFooter (line 5) | BorderPaddingForFooter = 2
function FullFooterHeight (line 8) | func FullFooterHeight(footerHeight int, toggleFooter bool) int {
FILE: testsuite/core/base_test.py
class BaseTest (line 11) | class BaseTest(ABC):
method __init__ (line 16) | def __init__(self, test_env : Environment):
method setup (line 21) | def setup(self) -> None:
method test_execute (line 26) | def test_execute(self) -> None:
method validate (line 31) | def validate(self) -> bool:
method cleanup (line 37) | def cleanup(self) -> None:
class GenericTestImpl (line 42) | class GenericTestImpl(BaseTest):
method __init__ (line 43) | def __init__(self, *, # Barrier to explicitly require keyword arguemen...
method setup (line 82) | def setup(self) -> None:
method start_spf (line 94) | def start_spf(self) -> None:
method end_execution (line 99) | def end_execution(self) -> None:
method send_input (line 104) | def send_input(self) -> None:
method test_execute (line 114) | def test_execute(self) -> None:
method validate (line 123) | def validate(self) -> bool:
method cleanup (line 149) | def cleanup(self) -> None:
method __repr__ (line 154) | def __repr__(self) -> str:
FILE: testsuite/core/environment.py
class Environment (line 4) | class Environment:
method __init__ (line 8) | def __init__(self, spf_manager : BaseSPFManager, fs_manager : TestFSMa...
method cleanup (line 12) | def cleanup(self) -> None:
FILE: testsuite/core/fs_manager.py
class TestFSManager (line 7) | class TestFSManager:
method __init__ (line 10) | def __init__(self):
method abspath (line 16) | def abspath(self, relative_path : Path) -> Path:
method check_exists (line 19) | def check_exists(self, relative_path : Path) -> bool:
method read_file (line 22) | def read_file(self, relative_path: Path) -> str:
method makedirs (line 33) | def makedirs(self, relative_path : Path) -> None:
method create_file (line 37) | def create_file(self, relative_path : Path, data : str = "") -> None:
method tree (line 46) | def tree(self, relative_root : Path = None) -> str:
method cleanup (line 60) | def cleanup(self) -> None:
method __repr__ (line 66) | def __repr__(self) -> str:
FILE: testsuite/core/keys.py
class Keys (line 4) | class Keys(ABC):
method __init__ (line 5) | def __init__(self, ascii_code : int):
method __repr__ (line 8) | def __repr__(self) -> str:
class CtrlKeys (line 12) | class CtrlKeys(Keys):
method __init__ (line 13) | def __init__(self, char : str):
class SpecialKeys (line 23) | class SpecialKeys(Keys):
method __init__ (line 24) | def __init__(self, ascii_code : int, key_name : str):
FILE: testsuite/core/pyautogui_manager.py
class PyAutoGuiSPFManager (line 7) | class PyAutoGuiSPFManager(BaseSPFManager):
method __init__ (line 13) | def __init__(self, spf_path : str):
method start_spf (line 18) | def start_spf(self, start_dir : str = None, args : list[str] = None) -...
method send_text_input (line 32) | def send_text_input(self, text : str, all_at_once : bool = False) -> N...
method send_special_input (line 39) | def send_special_input(self, key : keys.Keys) -> None:
method get_rendered_output (line 47) | def get_rendered_output(self) -> str:
method is_spf_running (line 51) | def is_spf_running(self) -> bool:
method close_spf (line 55) | def close_spf(self) -> None:
method runtime_info (line 60) | def runtime_info(self) -> str:
FILE: testsuite/core/runner.py
function get_testcases (line 23) | def get_testcases(test_env : Environment, only_run_tests : List[str] = N...
function run_tests (line 40) | def run_tests(spf_path : Path, stop_on_fail : bool = True, only_run_test...
FILE: testsuite/core/spf_manager.py
class BaseSPFManager (line 4) | class BaseSPFManager(ABC):
method __init__ (line 6) | def __init__(self, spf_path : str):
method start_spf (line 12) | def start_spf(self, start_dir : str = None, args : list[str] = None) -...
method send_text_input (line 16) | def send_text_input(self, text : str, all_at_once : bool = False) -> N...
method send_special_input (line 20) | def send_special_input(self, key : keys.Keys) -> None:
method get_rendered_output (line 24) | def get_rendered_output(self) -> str:
method is_spf_running (line 29) | def is_spf_running(self) -> bool:
method close_spf (line 37) | def close_spf(self) -> None:
method runtime_info (line 42) | def runtime_info(self) -> str:
FILE: testsuite/core/tmux_manager.py
class TmuxSPFManager (line 7) | class TmuxSPFManager(BaseSPFManager):
method __init__ (line 19) | def __init__(self, spf_path : str):
method start_spf (line 45) | def start_spf(self, start_dir : str = None, args : list[str] = None) -...
method _send_key (line 63) | def _send_key(self, key : str) -> None:
method send_text_input (line 67) | def send_text_input(self, text : str, all_at_once : bool = True) -> None:
method send_special_input (line 74) | def send_special_input(self, key : keys.Keys) -> str:
method get_rendered_output (line 82) | def get_rendered_output(self) -> str:
method is_spf_running (line 85) | def is_spf_running(self) -> bool:
method close_spf (line 91) | def close_spf(self) -> None:
method runtime_info (line 96) | def runtime_info(self) -> str:
method __repr__ (line 99) | def __repr__(self) -> str:
FILE: testsuite/core/utils.py
function get_sys_clipboard_text (line 7) | def get_sys_clipboard_text() -> str :
FILE: testsuite/main.py
function configure_logging (line 10) | def configure_logging(debug : bool = False) -> None:
function main (line 31) | def main():
FILE: testsuite/tests/chooser_file_test.py
class ChooserFileTest (line 16) | class ChooserFileTest(GenericTestImpl):
method __init__ (line 18) | def __init__(self, test_env : Environment):
method end_execution (line 33) | def end_execution(self) -> None:
method validate (line 38) | def validate(self) -> bool:
FILE: testsuite/tests/command_test.py
class CommandTest (line 12) | class CommandTest(GenericTestImpl):
method __init__ (line 15) | def __init__(self, test_env : Environment):
FILE: testsuite/tests/compress_extract_test.py
class CompressExtractTest (line 20) | class CompressExtractTest(GenericTestImpl):
method __init__ (line 26) | def __init__(self, test_env : Environment):
FILE: testsuite/tests/copy_dir_test.py
class CopyDirTest (line 21) | class CopyDirTest(GenericTestImpl):
method __init__ (line 23) | def __init__(self, test_env : Environment):
FILE: testsuite/tests/copy_test.py
class CopyTest (line 17) | class CopyTest(GenericTestImpl):
method __init__ (line 19) | def __init__(self, test_env : Environment):
FILE: testsuite/tests/copyw_test.py
class CopyWTest (line 12) | class CopyWTest(GenericTestImpl):
method __init__ (line 15) | def __init__(self, test_env : Environment):
FILE: testsuite/tests/cut_test.py
class CutTest (line 16) | class CutTest(GenericTestImpl):
method __init__ (line 18) | def __init__(self, test_env : Environment):
FILE: testsuite/tests/delete_dir_test.py
class DeleteDirTest (line 15) | class DeleteDirTest(GenericTestImpl):
method __init__ (line 17) | def __init__(self, test_env : Environment):
FILE: testsuite/tests/delete_test.py
class DeleteTest (line 13) | class DeleteTest(GenericTestImpl):
method __init__ (line 15) | def __init__(self, test_env : Environment):
FILE: testsuite/tests/empty_panel_test.py
class EmptyPanelTest (line 13) | class EmptyPanelTest(GenericTestImpl):
method __init__ (line 18) | def __init__(self, test_env : Environment):
method test_execute (line 48) | def test_execute(self) -> None:
FILE: testsuite/tests/nav_and_copy_path_test.py
class NavCopyPathTest_Disabled (line 17) | class NavCopyPathTest_Disabled(GenericTestImpl):
method __init__ (line 20) | def __init__(self, test_env : Environment):
method test_execute (line 30) | def test_execute(self) -> None:
FILE: testsuite/tests/rename_test.py
class RenameTest (line 18) | class RenameTest(GenericTestImpl):
method __init__ (line 20) | def __init__(self, test_env : Environment):
Condensed preview — 338 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,152K chars).
[
{
"path": ".envrc",
"chars": 10,
"preview": "use flake\n"
},
{
"path": ".github/FUNDING.yml",
"chars": 873,
"preview": "# These are supported funding model platforms\n\ngithub: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [u"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.md",
"chars": 608,
"preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n\n**Describe the "
},
{
"path": ".github/ISSUE_TEMPLATE/enhancement-suggestion.md",
"chars": 436,
"preview": "---\nname: Enhancement suggestion\nabout: Enhance existing designs\ntitle: ''\nlabels: enhancement\nassignees: ''\n\n---\n\n**The"
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.md",
"chars": 597,
"preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: idea\nassignees: ''\n\n---\n\n**Is your f"
},
{
"path": ".github/PULL_REQUEST_TEMPLATE/pull_request_template.md",
"chars": 945,
"preview": "# Description\n\nBriefly summarize what this PR changes. \nInclude any context or motivation behind the change. If it depe"
},
{
"path": ".github/renovate.json",
"chars": 422,
"preview": "{\n \"$schema\": \"https://docs.renovatebot.com/renovate-schema.json\",\n \"extends\": [\"config:recommended\", \":dependencyDash"
},
{
"path": ".github/workflows/first-interaction.yml",
"chars": 1502,
"preview": "name: \"Welcome First-Time Contributor\"\n\non:\n issues:\n types: [opened]\n pull_request:\n types: [opened]\n\npermissio"
},
{
"path": ".github/workflows/lint-pr-title.yml",
"chars": 1634,
"preview": "name: \"Lint PR Title\"\n\non:\n pull_request_target:\n types:\n - opened\n - edited\n - reopened\n - sync"
},
{
"path": ".github/workflows/mirror.yml",
"chars": 476,
"preview": "name: Mirror to Codeberg\npermissions:\n contents: read\n\non: [push] # Trigger on push to ANY branch\n\njobs:\n mirror:\n "
},
{
"path": ".github/workflows/superfile-build-test.yml",
"chars": 1748,
"preview": "name: Go CI\n\non:\n push:\n branches: [main]\n pull_request:\n branches: [main, develop]\n\npermissions:\n contents: re"
},
{
"path": ".github/workflows/testsuite-run.yml",
"chars": 1242,
"preview": "name: Python Testsuite Run\n\non:\n push:\n branches: [ main ]\n pull_request:\n branches: [ main, develop ]\n\npermissi"
},
{
"path": ".github/workflows/update-gomod2nix.yml",
"chars": 953,
"preview": "name: Update gomod2nix.toml\non:\n push:\n paths:\n - 'go.mod'\n - 'go.sum'\n\npermissions:\n contents: write\n\njob"
},
{
"path": ".github/workflows/winget.yml",
"chars": 537,
"preview": "name: Publish to WinGet\n\non:\n release:\n types: [released]\n\njobs:\n publish:\n name: Publish WinGet package\n run"
},
{
"path": ".gitignore",
"chars": 399,
"preview": "*.log\nbin/\ndist/\n.idea/\n\n# generated types\n.astro/\n\n# dependencies\nnode_modules/\n\n# logs\nnpm-debug.log*\nyarn-debug.log*\n"
},
{
"path": ".golangci.yaml",
"chars": 23262,
"preview": "# Based on https://gist.github.com/maratori/47a4d00457a92aa426dbd48a18776322\n# Version used - \n# https://gist.githubuser"
},
{
"path": "CONTRIBUTING.md",
"chars": 4240,
"preview": "# Contributing to superfile\n\nWelcome to **superfile**! This guide will help you get started contributing to the project,"
},
{
"path": "LICENSE",
"chars": 1066,
"preview": "MIT License\n\nCopyright (c) 2024 - Yorukot\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
},
{
"path": "Makefile",
"chars": 892,
"preview": ".PHONY: all build test lint clean dev testsuite help\n\n# Default target\nall: dev\n\n# Development workflow (equivalent to ."
},
{
"path": "README.md",
"chars": 7322,
"preview": "<div align=\"center\">\n\n<p>\n <h4>\n <a href=\"https://ko-fi.com/yorukot\">superfile is supported by the community.</a>\n "
},
{
"path": "asset/spf.desktop",
"chars": 300,
"preview": "[Desktop Entry]\nName=spf\nGenericName=superfile\nComment=fancy and modern terminal file manager\nType=Application\nMimeType="
},
{
"path": "build.sh",
"chars": 73,
"preview": "#!/usr/bin/env bash\n\n# build the app\nCGO_ENABLED=0 go build -o ./bin/spf\n"
},
{
"path": "cd_on_quit/cd_on_quit.fish",
"chars": 398,
"preview": "function spf\n set os $(uname -s)\n\n if test \"$os\" = \"Linux\"\n set spf_last_dir \"$HOME/.local/state/superfile/"
},
{
"path": "cd_on_quit/cd_on_quit.ps1",
"chars": 492,
"preview": "function spf() {\n param (\n [string[]]$Params\n )\n $spf_location = [Environment]::GetFolderPath(\"LocalAppl"
},
{
"path": "cd_on_quit/cd_on_quit.sh",
"chars": 444,
"preview": "spf() {\n os=$(uname -s)\n\n # Linux\n if [[ \"$os\" == \"Linux\" ]]; then\n export SPF_LAST_DIR=\"${XDG_STATE_HOM"
},
{
"path": "dev.sh",
"chars": 8652,
"preview": "#!/usr/bin/env bash\n\nset -e # Exit on any error\n\n# Colors for output\nRED='\\033[0;31m'\nGREEN='\\033[0;32m'\nYELLOW='\\033[1"
},
{
"path": "flake.nix",
"chars": 1695,
"preview": "{\n description = \"A fancy, pretty terminal file manager\";\n inputs = {\n nixpkgs.url = \"github:nixos/nixpkgs/nixos-un"
},
{
"path": "go.mod",
"chars": 3497,
"preview": "module github.com/yorukot/superfile\n\ngo 1.25.5\n\nrequire (\n\tgithub.com/adrg/xdg v0.5.3\n\tgithub.com/alecthomas/chroma/v2 v"
},
{
"path": "go.sum",
"chars": 40116,
"preview": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.34.0/go.mod h1"
},
{
"path": "gomod2nix.toml",
"chars": 9372,
"preview": "schema = 3\n\n[mod]\n [mod.'github.com/BourgeoisBear/rasterm']\n version = 'v1.1.2'\n hash = 'sha256-fYV85hVcIAT01xriE"
},
{
"path": "main.go",
"chars": 172,
"preview": "package main\n\nimport (\n\t\"embed\"\n\n\t\"github.com/yorukot/superfile/src/cmd\"\n)\n\nvar (\n\t//go:embed src/superfile_config/*\n\tco"
},
{
"path": "release/release.sh",
"chars": 1239,
"preview": "#!/usr/bin/env -S bash -euo pipefail\n\nprojectName=\"superfile\"\nversion=\"v1.5.0\"\nosList=(\"darwin\" \"linux\" \"windows\")\narchL"
},
{
"path": "release/release_check.md",
"chars": 74,
"preview": "- [ ] check all plugins is disable\n- [ ] check update version and zip file"
},
{
"path": "release/remove_all_spf_config.sh",
"chars": 126,
"preview": "#!/usr/bin/env bash\n\nrm -r \"$HOME/.config/superfile\"\nrm -r \"$HOME/.local/state/superfile\"\nrm -r \"$HOME/.local/share/supe"
},
{
"path": "src/cmd/debug_info.go",
"chars": 4257,
"preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\n\t\"github.com/fatih/color\"\n\n\t\"githu"
},
{
"path": "src/cmd/help_printer.go",
"chars": 3723,
"preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/fatih/color\"\n\t\"github.com/urfave/cli/"
},
{
"path": "src/cmd/main.go",
"chars": 9663,
"preview": "package cmd\n\nimport (\n\t\"context\"\n\t\"embed\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"log/slog\"\n\t\"net/http\"\n\t\"os\"\n\t\"time\"\n\n\t\"github."
},
{
"path": "src/config/fixed_variable.go",
"chars": 3848,
"preview": "package variable\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"github.com/urfave/cli/v3\"\n\n\t\"github.com/yorukot/superfile/src/pkg/u"
},
{
"path": "src/config/icon/function.go",
"chars": 2055,
"preview": "package icon\n\n// InitIcon initializes the icon configuration for the application.\n// It sets up different icons based on"
},
{
"path": "src/config/icon/icon.go",
"chars": 19574,
"preview": "package icon\n\n// Style for icons\ntype Style struct {\n\tIcon string\n\tColor string\n}\n\nvar (\n\tSpace = \" \"\n\tSuperfil"
},
{
"path": "src/internal/backend/README.md",
"chars": 630,
"preview": "# Backend Package\nHandles operations on the User's OS.\nFor example, executing shell commands, performing file operations"
},
{
"path": "src/internal/common/README.md",
"chars": 304,
"preview": "# common package\nDefines common utilities for ui and file operations package\neveryone can use common package, but common"
},
{
"path": "src/internal/common/config_type.go",
"chars": 11453,
"preview": "package common\n\n// Theme configuration\ntype ThemeType struct {\n\t// Code syntax highlight theme\n\tCodeSyntaxHighlightTheme"
},
{
"path": "src/internal/common/default_config.go",
"chars": 237,
"preview": "package common\n\n// Variables for holding default configurations of each settings\nvar (\n\tHotkeysTomlString string\n\tConfi"
},
{
"path": "src/internal/common/icon_utils.go",
"chars": 1534,
"preview": "package common\n\nimport (\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/yorukot/superfile/src/config/icon\"\n)\n\nfunc getFileIco"
},
{
"path": "src/internal/common/icon_utils_test.go",
"chars": 2593,
"preview": "package common\n\nimport (\n\t\"testing\"\n\n\t\"github.com/yorukot/superfile/src/config/icon\"\n)\n\nfunc TestGetElementIcon(t *testi"
},
{
"path": "src/internal/common/load_config.go",
"chars": 12186,
"preview": "package common\n\nimport (\n\t\"embed\"\n\t\"errors\"\n\t\"fmt\"\n\t\"log/slog\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"runtime\"\n\n\t\"github.co"
},
{
"path": "src/internal/common/predefined_variable.go",
"chars": 6482,
"preview": "package common\n\nimport (\n\t\"time\"\n\n\t\"github.com/charmbracelet/lipgloss\"\n\n\t\"github.com/yorukot/superfile/src/config/icon\"\n"
},
{
"path": "src/internal/common/string_function.go",
"chars": 8329,
"preview": "package common\n\nimport (\n\t\"bufio\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"log/slog\"\n\t\"math\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"unicode"
},
{
"path": "src/internal/common/string_function_test.go",
"chars": 6996,
"preview": "package common\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestStringTruncate(t *"
},
{
"path": "src/internal/common/style.go",
"chars": 8863,
"preview": "package common\n\nimport (\n\t\"github.com/charmbracelet/lipgloss\"\n)\n\nvar (\n\tBottomMiddleBorderSplit string\n)\nvar (\n\tTerminal"
},
{
"path": "src/internal/common/style_function.go",
"chars": 5999,
"preview": "package common\n\nimport (\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/charmbracelet/bubbles/progress\"\n\t\"github.com/charmbra"
},
{
"path": "src/internal/common/type.go",
"chars": 942,
"preview": "package common\n\n// Placeholder inteface for now, might later move 'model' type to commons and have\n// and add an execute"
},
{
"path": "src/internal/common/ui_consts.go",
"chars": 1198,
"preview": "package common\n\nimport \"time\"\n\n// Shared UI/layout constants to replace magic numbers flagged by mnd.\nconst (\n\tHelpKeyCo"
},
{
"path": "src/internal/config_function.go",
"chars": 5046,
"preview": "package internal\n\nimport (\n\t\"errors\"\n\t\"log/slog\"\n\t\"os\"\n\t\"reflect\"\n\t\"runtime\"\n\n\tzoxidelib \"github.com/lazysegtree/go-zoxi"
},
{
"path": "src/internal/default_config.go",
"chars": 1950,
"preview": "package internal\n\nimport (\n\tzoxidelib \"github.com/lazysegtree/go-zoxide\"\n\n\t\"github.com/yorukot/superfile/src/internal/ui"
},
{
"path": "src/internal/file_operation_compress_test.go",
"chars": 4909,
"preview": "package internal\n\nimport (\n\t\"archive/zip\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/test"
},
{
"path": "src/internal/file_operations.go",
"chars": 7969,
"preview": "package internal\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"log/slog\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\n\t\"github.com/yorukot/s"
},
{
"path": "src/internal/file_operations_compress.go",
"chars": 3056,
"preview": "package internal\n\nimport (\n\t\"archive/zip\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"log/slog\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n"
},
{
"path": "src/internal/file_operations_extract.go",
"chars": 979,
"preview": "package internal\n\nimport (\n\t\"fmt\"\n\t\"log/slog\"\n\t\"path/filepath\"\n\t\"time\"\n\n\t\"golift.io/xtractr\"\n\n\t\"github.com/yorukot/super"
},
{
"path": "src/internal/function.go",
"chars": 3604,
"preview": "package internal\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\n\ttea \"git"
},
{
"path": "src/internal/function_test.go",
"chars": 3653,
"preview": "package internal\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/"
},
{
"path": "src/internal/handle_file_operation_test.go",
"chars": 15072,
"preview": "package internal\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretch"
},
{
"path": "src/internal/handle_file_operations.go",
"chars": 15825,
"preview": "package internal\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"log/slog\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"time\"\n"
},
{
"path": "src/internal/handle_modal.go",
"chars": 2905,
"preview": "package internal\n\nimport (\n\t\"log/slog\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/yorukot/superfile/src/internal/ui"
},
{
"path": "src/internal/handle_panel_movement.go",
"chars": 4725,
"preview": "package internal\n\nimport (\n\t\"log/slog\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\n\ttea \"github.com/charmbr"
},
{
"path": "src/internal/handle_panel_navigation.go",
"chars": 1237,
"preview": "package internal\n\nimport (\n\t\"log/slog\"\n\n\t\"github.com/yorukot/superfile/src/internal/common\"\n)\n\n// Pinned directory\nfunc "
},
{
"path": "src/internal/key_function.go",
"chars": 10049,
"preview": "package internal\n\nimport (\n\t\"errors\"\n\t\"log/slog\"\n\t\"slices\"\n\n\t\"github.com/yorukot/superfile/src/internal/common\"\n\t\"github"
},
{
"path": "src/internal/model.go",
"chars": 21724,
"preview": "package internal\n\nimport (\n\t\"errors\"\n\t\"log/slog\"\n\t\"os\"\n\t\"reflect\"\n\t\"slices\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/yorukot/sup"
},
{
"path": "src/internal/model_file_operations_test.go",
"chars": 8384,
"preview": "package internal\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"testing\"\n\n\ttea \"github.com/charmbracelet/bubbletea"
},
{
"path": "src/internal/model_layout_test.go",
"chars": 9649,
"preview": "package internal\n\n// TODO add two new tests for sidebar, a - with only one section, and b - without any sections.\n// not"
},
{
"path": "src/internal/model_msg.go",
"chars": 3770,
"preview": "package internal\n\nimport (\n\t\"log/slog\"\n\n\ttea \"github.com/charmbracelet/bubbletea\"\n\n\t\"github.com/yorukot/superfile/src/in"
},
{
"path": "src/internal/model_navigation_test.go",
"chars": 8803,
"preview": "package internal\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"testing\"\n\n\ttea \"github.com/charmbracelet/bubbletea\"\n\t\"git"
},
{
"path": "src/internal/model_process_test.go",
"chars": 435,
"preview": "package internal\n\nimport \"testing\"\n\nfunc TestProcess(_ *testing.T) {\n\t// TODO :\n\t// We need to test - We could implement"
},
{
"path": "src/internal/model_prompt_test.go",
"chars": 17005,
"preview": "package internal\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/adrg/xdg\"\n\ttea \""
},
{
"path": "src/internal/model_render.go",
"chars": 5547,
"preview": "package internal\n\nimport (\n\t\"path/filepath\"\n\t\"strconv\"\n\n\tfilepreview \"github.com/yorukot/superfile/src/pkg/file_preview\""
},
{
"path": "src/internal/model_test.go",
"chars": 11110,
"preview": "package internal\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\ttea \"github.com/charmbracelet/b"
},
{
"path": "src/internal/model_zoxide_test.go",
"chars": 5505,
"preview": "package internal\n\nimport (\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"testing\"\n\n\ttea \"github.com/charmbracelet/bubbletea\"\n\tzoxidelib "
},
{
"path": "src/internal/test_utils.go",
"chars": 7479,
"preview": "package internal\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\t\"time\"\n\n\ttea \"github.com/charmbracelet/bubbletea\"\n\tzoxidel"
},
{
"path": "src/internal/test_utils_teaprog.go",
"chars": 1937,
"preview": "package internal\n\nimport (\n\t\"errors\"\n\t\"log/slog\"\n\t\"testing\"\n\n\ttea \"github.com/charmbracelet/bubbletea\"\n\n\t\"github.com/yor"
},
{
"path": "src/internal/type.go",
"chars": 2618,
"preview": "package internal\n\nimport (\n\tzoxidelib \"github.com/lazysegtree/go-zoxide\"\n\n\t\"github.com/yorukot/superfile/src/internal/ui"
},
{
"path": "src/internal/type_utils.go",
"chars": 447,
"preview": "package internal\n\nimport (\n\t\"github.com/yorukot/superfile/src/internal/common\"\n)\n\n// ================ String method for "
},
{
"path": "src/internal/ui/README.md",
"chars": 96,
"preview": "# ui package\n\n# To-dos\n- Put model, filePanel, sidebarModel, etc. in separate packages like this"
},
{
"path": "src/internal/ui/clipboard/model.go",
"chars": 2802,
"preview": "package clipboard\n\nimport (\n\t\"log/slog\"\n\t\"os\"\n\t\"slices\"\n\t\"strconv\"\n\n\t\"github.com/yorukot/superfile/src/internal/common\"\n"
},
{
"path": "src/internal/ui/clipboard/model_test.go",
"chars": 2345,
"preview": "package clipboard\n\nimport (\n\t\"flag\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/charmbracelet/x/ansi\"\n\t\"g"
},
{
"path": "src/internal/ui/filemodel/consts.go",
"chars": 600,
"preview": "package filemodel\n\nimport (\n\t\"errors\"\n\n\t\"github.com/yorukot/superfile/src/internal/ui/filepanel\"\n)\n\n// Now they are same"
},
{
"path": "src/internal/ui/filemodel/dimensions.go",
"chars": 2391,
"preview": "package filemodel\n\nimport (\n\t\"log/slog\"\n\n\ttea \"github.com/charmbracelet/bubbletea\"\n\n\t\"github.com/yorukot/superfile/src/i"
},
{
"path": "src/internal/ui/filemodel/navigation.go",
"chars": 495,
"preview": "package filemodel\n\nimport \"log/slog\"\n\nfunc (m *Model) NextFilePanel() {\n\tm.MoveFocusedPanelBy(1)\n}\n\nfunc (m *Model) Prev"
},
{
"path": "src/internal/ui/filemodel/render.go",
"chars": 884,
"preview": "package filemodel\n\nimport \"github.com/charmbracelet/lipgloss\"\n\nfunc (m *Model) Render() string {\n\tf := make([]string, m."
},
{
"path": "src/internal/ui/filemodel/type.go",
"chars": 657,
"preview": "package filemodel\n\nimport (\n\t\"github.com/yorukot/superfile/src/internal/ui/filepanel\"\n\t\"github.com/yorukot/superfile/src"
},
{
"path": "src/internal/ui/filemodel/update.go",
"chars": 3891,
"preview": "package filemodel\n\nimport (\n\t\"fmt\"\n\t\"log/slog\"\n\t\"os\"\n\n\ttea \"github.com/charmbracelet/bubbletea\"\n\n\t\"github.com/yorukot/su"
},
{
"path": "src/internal/ui/filemodel/utils.go",
"chars": 566,
"preview": "package filemodel\n\nimport (\n\t\"github.com/yorukot/superfile/src/internal/common\"\n\t\"github.com/yorukot/superfile/src/inter"
},
{
"path": "src/internal/ui/filepanel/columns.go",
"chars": 4721,
"preview": "package filepanel\n\nimport (\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/charmbracelet/lipgloss\"\n\t\"github.com/charmbracelet/x/ansi\"\n\n\t"
},
{
"path": "src/internal/ui/filepanel/consts.go",
"chars": 619,
"preview": "package filepanel\n\nimport (\n\t\"time\"\n\n\t\"github.com/yorukot/superfile/src/internal/common\"\n)\n\nconst (\n\tcontentPadding = 3 "
},
{
"path": "src/internal/ui/filepanel/dimension.go",
"chars": 1270,
"preview": "package filepanel\n\nimport (\n\t\"github.com/yorukot/superfile/src/internal/common\"\n)\n\nfunc (m *Model) UpdateDimensions(widt"
},
{
"path": "src/internal/ui/filepanel/get_elements.go",
"chars": 3518,
"preview": "package filepanel\n\nimport (\n\t\"log/slog\"\n\t\"os\"\n\t\"slices\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/yorukot/superfile/src/pkg/utils"
},
{
"path": "src/internal/ui/filepanel/get_elements_test.go",
"chars": 8247,
"preview": "package filepanel\n\nimport (\n\t\"path/filepath\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/yor"
},
{
"path": "src/internal/ui/filepanel/misc.go",
"chars": 258,
"preview": "package filepanel\n\nimport \"github.com/yorukot/superfile/src/internal/common\"\n\nfunc (p PanelMode) String() string {\n\tswit"
},
{
"path": "src/internal/ui/filepanel/model.go",
"chars": 1558,
"preview": "package filepanel\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"github.com/yorukot/superfile/src/internal/common\"\n\t\"github.com/yor"
},
{
"path": "src/internal/ui/filepanel/navigation.go",
"chars": 2247,
"preview": "package filepanel\n\nimport (\n\t\"fmt\"\n)\n\nfunc (m *Model) scrollToCursor(cursor int) {\n\tif cursor < 0 || cursor >= m.ElemCou"
},
{
"path": "src/internal/ui/filepanel/navigation_test.go",
"chars": 11339,
"preview": "package filepanel\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/yorukot/superfile/src/intern"
},
{
"path": "src/internal/ui/filepanel/render.go",
"chars": 4096,
"preview": "package filepanel\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/yorukot/superfile/src/config/icon\"\n\t\"github"
},
{
"path": "src/internal/ui/filepanel/selection_test.go",
"chars": 1984,
"preview": "package filepanel\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestPanelSelectionLifeCycle(t *tes"
},
{
"path": "src/internal/ui/filepanel/sort.go",
"chars": 4639,
"preview": "package filepanel\n\nimport (\n\t\"log/slog\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/fvbommel/sortorder\"\n\n\t\"g"
},
{
"path": "src/internal/ui/filepanel/types.go",
"chars": 1947,
"preview": "package filepanel\n\nimport (\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/charmbracelet/bubbles/textinput\"\n\t\"github.com/charmbracelet/lipg"
},
{
"path": "src/internal/ui/filepanel/update.go",
"chars": 2734,
"preview": "package filepanel\n\nimport (\n\t\"fmt\"\n\t\"log/slog\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"github.com/yorukot/superfile/src/pkg/utils\"\n)\n\n"
},
{
"path": "src/internal/ui/filepanel/utils.go",
"chars": 3120,
"preview": "package filepanel\n\nimport \"math\"\n\nfunc (m *Model) GetCursor() int {\n\treturn m.cursor\n}\n\nfunc (m *Model) GetRenderIndex()"
},
{
"path": "src/internal/ui/helpmenu/data.go",
"chars": 8953,
"preview": "package helpmenu\n\nimport (\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/yorukot/superfile/src/internal/common\"\n\t\"github.com"
},
{
"path": "src/internal/ui/helpmenu/model_state.go",
"chars": 1874,
"preview": "package helpmenu\n\nimport (\n\t\"slices\"\n\n\ttea \"github.com/charmbracelet/bubbletea\"\n\n\t\"github.com/yorukot/superfile/src/inte"
},
{
"path": "src/internal/ui/helpmenu/navigation.go",
"chars": 1701,
"preview": "package helpmenu\n\nimport \"github.com/yorukot/superfile/src/internal/common\"\n\n// Help menu panel list up\nfunc (m *Model) "
},
{
"path": "src/internal/ui/helpmenu/render.go",
"chars": 2870,
"preview": "package helpmenu\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n\n\t\"github.com/yorukot/superfile/src/config/icon\"\n\t\"github.com/yorukot/super"
},
{
"path": "src/internal/ui/helpmenu/type.go",
"chars": 489,
"preview": "package helpmenu\n\nimport \"github.com/charmbracelet/bubbles/textinput\"\n\ntype hotkeyType int\n\nconst (\n\tglobalType hotkeyTy"
},
{
"path": "src/internal/ui/helpmenu/utils.go",
"chars": 175,
"preview": "package helpmenu\n\nfunc (m *Model) IsOpen() bool {\n\treturn m.opened\n}\n\nfunc (m *Model) GetHeight() int {\n\treturn m.height"
},
{
"path": "src/internal/ui/metadata/README.md",
"chars": 347,
"preview": "# metadata package\nThis is for the metadata panel, fetching and rendering metadata.\nSince metadata fetching is not fully"
},
{
"path": "src/internal/ui/metadata/architecture.go",
"chars": 3023,
"preview": "package metadata\n\nimport (\n\t\"debug/elf\"\n\t\"debug/macho\"\n\t\"debug/pe\"\n\t\"errors\"\n\t\"fmt\"\n\t\"strings\"\n)\n\nconst (\n\tarchI386 ="
},
{
"path": "src/internal/ui/metadata/architecture_test.go",
"chars": 1803,
"preview": "package metadata\n\nimport (\n\t\"debug/elf\"\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/"
},
{
"path": "src/internal/ui/metadata/const.go",
"chars": 1336,
"preview": "package metadata\n\nimport \"time\"\n\n// Spacing between Key and Value while rendering\nconst keyValueSpacing = \" \"\nconst keyV"
},
{
"path": "src/internal/ui/metadata/metadata.go",
"chars": 4338,
"preview": "package metadata\n\nimport (\n\t\"fmt\"\n\t\"log/slog\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\n\t\"github.com/barasher/go-exiftool\"\n\n\t\"gith"
},
{
"path": "src/internal/ui/metadata/metadata_test.go",
"chars": 1209,
"preview": "package metadata\n\nimport (\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"testing\"\n\n\t\"github.com/barasher/go-exiftool\"\n\t\"github.com/stret"
},
{
"path": "src/internal/ui/metadata/metadata_unix.go",
"chars": 527,
"preview": "//go:build !windows\n\npackage metadata\n\nimport (\n\t\"os\"\n\t\"os/user\"\n\t\"strconv\"\n\t\"syscall\"\n)\n\nfunc getOwnerAndGroup(fileInfo"
},
{
"path": "src/internal/ui/metadata/metadata_windows.go",
"chars": 129,
"preview": "//go:build windows\n\npackage metadata\n\nimport (\n\t\"os\"\n)\n\nfunc getOwnerAndGroup(_ os.FileInfo) (string, string) {\n\treturn "
},
{
"path": "src/internal/ui/metadata/model.go",
"chars": 2254,
"preview": "package metadata\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/yorukot/superfile/src/internal/ui\"\n\t\"github.com/yorukot/superfile/src/pk"
},
{
"path": "src/internal/ui/metadata/model_test.go",
"chars": 1250,
"preview": "package metadata\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestUpDown(t *testing.T) {\n\tdefault"
},
{
"path": "src/internal/ui/metadata/testdata/file1.txt",
"chars": 8,
"preview": "12345678"
},
{
"path": "src/internal/ui/metadata/update.go",
"chars": 1177,
"preview": "package metadata\n\nimport \"strconv\"\n\nfunc (m *Model) SetMetadataCache(metadata Metadata, metadataFocused bool) {\n\tm.cache"
},
{
"path": "src/internal/ui/metadata/utils.go",
"chars": 1944,
"preview": "package metadata\n\nimport (\n\t\"crypto/md5\" //nolint:gosec // MD5 used for file checksum display only, not for security\n\t\"e"
},
{
"path": "src/internal/ui/notify/model.go",
"chars": 1204,
"preview": "package notify\n\nimport (\n\t\"github.com/yorukot/superfile/src/internal/common\"\n)\n\ntype Model struct {\n\topen bool\n"
},
{
"path": "src/internal/ui/notify/type.go",
"chars": 152,
"preview": "package notify\n\ntype ConfirmActionType int\n\nconst (\n\tRenameAction ConfirmActionType = iota\n\tDeleteAction\n\tQuitAction\n\tNo"
},
{
"path": "src/internal/ui/preview/model.go",
"chars": 1371,
"preview": "package preview\n\nimport (\n\t\"log/slog\"\n\n\t\"github.com/yorukot/superfile/src/internal/common\"\n\n\tfilepreview \"github.com/yor"
},
{
"path": "src/internal/ui/preview/model_utils.go",
"chars": 1394,
"preview": "package preview\n\nimport \"log/slog\"\n\nfunc (m *Model) GetContent() string {\n\treturn m.content\n}\n\nfunc (m *Model) GetConten"
},
{
"path": "src/internal/ui/preview/render.go",
"chars": 7181,
"preview": "package preview\n\nimport (\n\t\"errors\"\n\t\"image\"\n\t\"io/fs\"\n\t\"log/slog\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\n\t"
},
{
"path": "src/internal/ui/preview/render_test.go",
"chars": 3942,
"preview": "package preview\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/charmbracelet/x/ansi\"\n\t\"github.com/"
},
{
"path": "src/internal/ui/preview/render_unix_test.go",
"chars": 526,
"preview": "//go:build !windows\n\npackage preview\n\nimport (\n\t\"path/filepath\"\n\t\"syscall\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/ass"
},
{
"path": "src/internal/ui/preview/render_utils.go",
"chars": 1910,
"preview": "package preview\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log/slog\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/charmbracel"
},
{
"path": "src/internal/ui/preview/update.go",
"chars": 1120,
"preview": "package preview\n\n// UpdateMsg represents an async query result\n\ntype UpdateMsg struct {\n\t// location can contain either "
},
{
"path": "src/internal/ui/processbar/README.md",
"chars": 254,
"preview": "# processbar package\nThis package is for processbar. \nThis should not import internal package, and should not be aware o"
},
{
"path": "src/internal/ui/processbar/const.go",
"chars": 689,
"preview": "package processbar\n\nconst (\n\t// Min width and height for borders\n\tminHeight = 2\n\tminWidth = 2\n\n\t// This should allow sm"
},
{
"path": "src/internal/ui/processbar/error.go",
"chars": 446,
"preview": "package processbar\n\ntype ProcessChannelFullError struct {\n}\n\nfunc (p *ProcessChannelFullError) Error() string {\n\treturn "
},
{
"path": "src/internal/ui/processbar/model.go",
"chars": 4109,
"preview": "package processbar\n\nimport (\n\t\"fmt\"\n\t\"log/slog\"\n\n\t\"github.com/yorukot/superfile/src/internal/common\"\n\t\"github.com/yoruko"
},
{
"path": "src/internal/ui/processbar/model_navigation.go",
"chars": 1232,
"preview": "package processbar\n\nimport (\n\t\"github.com/yorukot/superfile/src/internal/common\"\n)\n\n// Control processbar panel list up\n"
},
{
"path": "src/internal/ui/processbar/model_navigation_test.go",
"chars": 4246,
"preview": "package processbar\n\nimport (\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc Test_cntRenderableProc"
},
{
"path": "src/internal/ui/processbar/model_test.go",
"chars": 3071,
"preview": "package processbar\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretch"
},
{
"path": "src/internal/ui/processbar/model_update.go",
"chars": 2359,
"preview": "package processbar\n\nimport (\n\t\"log/slog\"\n)\n\n// Only used in tests, to have processbar used in a standalone way without m"
},
{
"path": "src/internal/ui/processbar/model_update_test.go",
"chars": 586,
"preview": "package processbar\n\nimport \"testing\"\n\nfunc TestUpdateMsg(_ *testing.T) {\n\t// TODO\n\t// Test these\n\t// 1 - Sending message"
},
{
"path": "src/internal/ui/processbar/model_utils.go",
"chars": 2464,
"preview": "package processbar\n\nimport (\n\t\"sort\"\n\n\t\"github.com/lithammer/shortuuid\"\n)\n\nfunc (m *Model) cntProcesses() int {\n\treturn "
},
{
"path": "src/internal/ui/processbar/model_utils_test.go",
"chars": 677,
"preview": "package processbar\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestModelUtils(t *testing.T) {\n\tm"
},
{
"path": "src/internal/ui/processbar/operation.go",
"chars": 1195,
"preview": "package processbar\n\nimport \"github.com/yorukot/superfile/src/config/icon\"\n\ntype OperationType int\n\nconst (\n\tOpCopy Opera"
},
{
"path": "src/internal/ui/processbar/process.go",
"chars": 2310,
"preview": "package processbar\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/charmbracelet/bubbles/progress\"\n\n\t\"github.com/yorukot/superfil"
},
{
"path": "src/internal/ui/processbar/process_test.go",
"chars": 2204,
"preview": "package processbar\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/yorukot/superfile/src/confi"
},
{
"path": "src/internal/ui/processbar/process_update_msg.go",
"chars": 871,
"preview": "package processbar\n\ntype Cmd func() UpdateMsg\n\ntype UpdateMsg interface {\n\tApply(m *Model) (Cmd, error)\n\tGetReqID() int\n"
},
{
"path": "src/internal/ui/prompt/README.md",
"chars": 355,
"preview": "# prompt package\nThis is for the Prompt modal of superfile\n\nHandles user input updates, spf model updates, and returns a"
},
{
"path": "src/internal/ui/prompt/consts.go",
"chars": 1870,
"preview": "package prompt\n\nimport \"time\"\n\n// These could as well be property of prompt Model vs being global consts\n// But its fine"
},
{
"path": "src/internal/ui/prompt/error.go",
"chars": 1003,
"preview": "package prompt\n\nimport \"fmt\"\n\n// This is to generate error objects that can be nicely printed to UI\ntype invalidCmdError"
},
{
"path": "src/internal/ui/prompt/model.go",
"chars": 6330,
"preview": "package prompt\n\nimport (\n\t\"fmt\"\n\t\"log/slog\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"github.com/yorukot/superfile/src/internal/ui\"\n\n\ttea "
},
{
"path": "src/internal/ui/prompt/model_test.go",
"chars": 14585,
"preview": "package prompt\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n\n\ttea \"github.com/charmbracelet/bubbletea\"\n\t\"github."
},
{
"path": "src/internal/ui/prompt/tokenize.go",
"chars": 4479,
"preview": "package prompt\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"log/slog\"\n\t\"os\"\n\t\"strings\"\n\t\"time\"\n\t\"unicode\"\n\n\t\"github.com/yorukot/superfil"
},
{
"path": "src/internal/ui/prompt/tokenize_test.go",
"chars": 13307,
"preview": "package prompt\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"runtime\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github"
},
{
"path": "src/internal/ui/prompt/type.go",
"chars": 865,
"preview": "package prompt\n\nimport \"github.com/charmbracelet/bubbles/textinput\"\n\n// No need to name it as PromptModel. It will me im"
},
{
"path": "src/internal/ui/prompt/utils.go",
"chars": 1807,
"preview": "package prompt\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/yorukot/superfile/src/internal/common\"\n)\n\nfunc getPromptAction("
},
{
"path": "src/internal/ui/prompt/utils_test.go",
"chars": 3613,
"preview": "package prompt\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/yorukot/superfile/src/internal/"
},
{
"path": "src/internal/ui/rendering/README.md",
"chars": 705,
"preview": "# renderer package\nResponsible for rendering\n\n# Dependencies\nThis package should not not import any other UI package, an"
},
{
"path": "src/internal/ui/rendering/border.go",
"chars": 4399,
"preview": "package rendering\n\nimport (\n\t\"strings\"\n\n\t\"github.com/charmbracelet/x/ansi\"\n\n\t\"github.com/charmbracelet/lipgloss\"\n)\n\ntype"
},
{
"path": "src/internal/ui/rendering/constants.go",
"chars": 621,
"preview": "package rendering\n\n// Border rendering constants\nconst (\n\t// borderCornerWidth is the width occupied by border corners\n\t"
},
{
"path": "src/internal/ui/rendering/content_renderer.go",
"chars": 2141,
"preview": "package rendering\n\nimport (\n\t\"log/slog\"\n\t\"strings\"\n\n\t\"github.com/yorukot/superfile/src/internal/common\"\n)\n\ntype ContentR"
},
{
"path": "src/internal/ui/rendering/content_renderer_test.go",
"chars": 1055,
"preview": "package rendering\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestContentRendererBasic(t *testin"
},
{
"path": "src/internal/ui/rendering/renderer.go",
"chars": 5788,
"preview": "package rendering\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"log/slog\"\n\t\"math/rand/v2\"\n\t\"strconv\"\n\n\t\"github.com/charmbracelet/lipgloss"
},
{
"path": "src/internal/ui/rendering/renderer_core.go",
"chars": 4315,
"preview": "package rendering\n\nimport (\n\t\"log/slog\"\n\t\"strings\"\n\n\t\"github.com/charmbracelet/lipgloss\"\n\t\"github.com/charmbracelet/x/an"
},
{
"path": "src/internal/ui/rendering/renderer_test.go",
"chars": 9602,
"preview": "package rendering\n\nimport (\n\t\"flag\"\n\t\"testing\"\n\n\t\"github.com/charmbracelet/lipgloss\"\n\t\"github.com/stretchr/testify/asser"
},
{
"path": "src/internal/ui/rendering/truncate.go",
"chars": 620,
"preview": "package rendering\n\nimport (\n\t\"log/slog\"\n\n\t\"github.com/charmbracelet/x/ansi\"\n)\n\ntype TruncateStyle int\n\n// These truncate"
},
{
"path": "src/internal/ui/rendering/truncate_test.go",
"chars": 1948,
"preview": "package rendering\n\nimport (\n\t\"testing\"\n\n\t\"github.com/charmbracelet/lipgloss\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nf"
},
{
"path": "src/internal/ui/sidebar/README.md",
"chars": 542,
"preview": "# sidebar package\nThis is for the sidebar UI, and for fetching and updating sidebar directories\n\n# To-dos\n- Add missing "
},
{
"path": "src/internal/ui/sidebar/consts.go",
"chars": 1181,
"preview": "package sidebar\n\nimport (\n\t\"github.com/yorukot/superfile/src/pkg/utils\"\n)\n\n// These are effectively consts\n// Had to use"
},
{
"path": "src/internal/ui/sidebar/directory_utils.go",
"chars": 3986,
"preview": "package sidebar\n\nimport (\n\t\"os\"\n\t\"runtime\"\n\t\"slices\"\n\n\t\"github.com/adrg/xdg\"\n\n\t\"github.com/yorukot/superfile/src/pkg/uti"
},
{
"path": "src/internal/ui/sidebar/disk_utils.go",
"chars": 2900,
"preview": "package sidebar\n\nimport (\n\t\"log/slog\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\n\t\"github.com/shirou/gopsutil/v4/disk\"\n\n\t\"g"
},
{
"path": "src/internal/ui/sidebar/navigation.go",
"chars": 3458,
"preview": "package sidebar\n\nimport (\n\t\"log/slog\"\n\n\t\"github.com/yorukot/superfile/src/internal/common\"\n)\n\nfunc (s *Model) ListUp() {"
},
{
"path": "src/internal/ui/sidebar/navigation_test.go",
"chars": 18223,
"preview": "package sidebar\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/yorukot/superfile/src/internal"
},
{
"path": "src/internal/ui/sidebar/pinned.go",
"chars": 2629,
"preview": "package sidebar\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log/slog\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"github.com/yorukot/superfile/src"
},
{
"path": "src/internal/ui/sidebar/pinned_test.go",
"chars": 6607,
"preview": "package sidebar\n\nimport (\n\t\"encoding/json\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"gi"
},
{
"path": "src/internal/ui/sidebar/render.go",
"chars": 2535,
"preview": "package sidebar\n\nimport (\n\t\"log/slog\"\n\n\t\"github.com/yorukot/superfile/src/internal/ui\"\n\n\t\"github.com/yorukot/superfile/s"
},
{
"path": "src/internal/ui/sidebar/sidebar.go",
"chars": 3899,
"preview": "package sidebar\n\nimport (\n\t\"log/slog\"\n\t\"slices\"\n\n\ttea \"github.com/charmbracelet/bubbletea\"\n\n\tvariable \"github.com/yoruko"
},
{
"path": "src/internal/ui/sidebar/type.go",
"chars": 422,
"preview": "package sidebar\n\nimport \"github.com/charmbracelet/bubbles/textinput\"\n\ntype directory struct {\n\tLocation string `json:\"lo"
},
{
"path": "src/internal/ui/sidebar/utils.go",
"chars": 3576,
"preview": "package sidebar\n\nimport \"log/slog\"\n\n// isDivider returns true if the directory is one of the section dividers.\nfunc (d d"
},
{
"path": "src/internal/ui/sidebar/utils_test.go",
"chars": 4447,
"preview": "package sidebar\n\nimport (\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/yorukot/superfile/s"
},
{
"path": "src/internal/ui/sortmodel/const.go",
"chars": 120,
"preview": "package sortmodel\n\nconst (\n\tsortOptionsDefaultWidth = 20\n\tsortOptionsDefaultHeight = 4\n\tSortTypeCount = 4\n)\n"
},
{
"path": "src/internal/ui/sortmodel/model.go",
"chars": 159,
"preview": "package sortmodel\n\nfunc New() Model {\n\treturn Model{\n\t\tHeight: sortOptionsDefaultHeight,\n\t\tWidth: sortOptionsDefaultWid"
},
{
"path": "src/internal/ui/sortmodel/navigation.go",
"chars": 198,
"preview": "package sortmodel\n\nfunc (m *Model) ListUp() {\n\tm.Cursor = (m.Cursor - 1 + SortTypeCount) % SortTypeCount\n}\n\nfunc (m *Mod"
},
{
"path": "src/internal/ui/sortmodel/render.go",
"chars": 837,
"preview": "package sortmodel\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/yorukot/superfile/src/config/icon\"\n\t\"github.com/y"
},
{
"path": "src/internal/ui/sortmodel/types.go",
"chars": 629,
"preview": "package sortmodel\n\ntype SortKind int\n\n// NOTE: Update the validation of DefaultSortType config if you make changes here\n"
},
{
"path": "src/internal/ui/sortmodel/utils.go",
"chars": 294,
"preview": "package sortmodel\n\nfunc (m *Model) IsOpen() bool {\n\treturn m.open\n}\n\nfunc (m *Model) Open(curSortKind SortKind) {\n\tm.Cur"
},
{
"path": "src/internal/ui/spf_renderers.go",
"chars": 4607,
"preview": "package ui\n\nimport (\n\t\"github.com/charmbracelet/lipgloss\"\n\n\t\"github.com/yorukot/superfile/src/internal/common\"\n\t\"github."
},
{
"path": "src/internal/ui/zoxide/README.md",
"chars": 1371,
"preview": "# zoxide package\nThis is for the Zoxide navigation modal of superfile\n\nHandles user input for zoxide queries, integrates"
},
{
"path": "src/internal/ui/zoxide/consts.go",
"chars": 518,
"preview": "package zoxide\n\nconst (\n\tzoxideHeadlineText = \"Zoxide Navigation\"\n\n\tZoxideMinWidth = 15\n\tZoxideMinHeight = 3\n\n\tmaxVisib"
},
{
"path": "src/internal/ui/zoxide/model.go",
"chars": 4230,
"preview": "package zoxide\n\nimport (\n\t\"log/slog\"\n\t\"reflect\"\n\t\"slices\"\n\t\"strings\"\n\n\ttea \"github.com/charmbracelet/bubbletea\"\n\tzoxidel"
},
{
"path": "src/internal/ui/zoxide/model_test.go",
"chars": 4138,
"preview": "package zoxide\n\nimport (\n\t\"testing\"\n\n\ttea \"github.com/charmbracelet/bubbletea\"\n\tzoxidelib \"github.com/lazysegtree/go-zox"
},
{
"path": "src/internal/ui/zoxide/navigation.go",
"chars": 1020,
"preview": "package zoxide\n\nfunc (m *Model) navigateUp() {\n\tif len(m.results) == 0 {\n\t\treturn\n\t}\n\tif m.cursor > 0 {\n\t\tm.cursor--\n\t} "
},
{
"path": "src/internal/ui/zoxide/navigation_test.go",
"chars": 3042,
"preview": "package zoxide\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestNavigation(t *testing.T) {\n\ttestd"
},
{
"path": "src/internal/ui/zoxide/render.go",
"chars": 2020,
"preview": "package zoxide\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/yorukot/superfile/src/internal/common\"\n\t\"github.com/yorukot/superfile/src/"
},
{
"path": "src/internal/ui/zoxide/render_test.go",
"chars": 2631,
"preview": "package zoxide\n\nimport (\n\t\"testing\"\n\n\tzoxidelib \"github.com/lazysegtree/go-zoxide\"\n\t\"github.com/stretchr/testify/assert\""
},
{
"path": "src/internal/ui/zoxide/test_helpers.go",
"chars": 977,
"preview": "package zoxide\n\nimport (\n\t\"runtime\"\n\t\"testing\"\n\n\tzoxidelib \"github.com/lazysegtree/go-zoxide\"\n\n\t\"github.com/yorukot/supe"
},
{
"path": "src/internal/ui/zoxide/type.go",
"chars": 1134,
"preview": "package zoxide\n\nimport (\n\t\"github.com/charmbracelet/bubbles/textinput\"\n\tzoxidelib \"github.com/lazysegtree/go-zoxide\"\n)\n\n"
}
]
// ... and 138 more files (download for full content)
About this extraction
This page contains the full source code of the yorukot/superfile GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 338 files (1023.9 KB), approximately 305.1k tokens, and a symbol index with 1350 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.