├── .devcontainer ├── Dockerfile ├── devcontainer.json └── website │ └── devcontainer.json ├── .editorconfig ├── .gitattributes ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── feature_request.yml │ └── new_language.yml ├── dependabot.yml ├── release.yml └── workflows │ ├── cd.yml │ ├── ci.yml │ ├── msrv-badge.yml │ ├── web-ci.yml │ ├── wiki.yml │ └── windows-installer.iss ├── .gitignore ├── .mailmap ├── .rustfmt.toml ├── .tokeignore ├── .vscode └── settings.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE.md ├── Makefile ├── README.md ├── ascii ├── Cargo.toml ├── LICENSE.md ├── README.md └── src │ └── lib.rs ├── assets ├── msrv-badge.svg ├── onefetch.ico ├── onefetch.svg ├── screenshot-1.png └── screenshot-2.png ├── benches └── repo.rs ├── build.rs ├── docs ├── README.ar.md ├── README.cn.md ├── README.cs.md ├── README.de.md ├── README.es.md ├── README.fa.md ├── README.fr.md ├── README.it.md ├── README.ja.md ├── README.kr.md ├── README.pl.md ├── README.ru.md ├── README.tr.md ├── onefetch.1 ├── vercel │ ├── .gitignore │ ├── .npmrc │ ├── .prettierignore │ ├── .prettierrc │ ├── README.md │ ├── eslint.config.js │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── app.css │ │ ├── app.d.ts │ │ ├── app.html │ │ ├── lib │ │ │ └── utils.ts │ │ └── routes │ │ │ ├── +page.svelte │ │ │ ├── +page.ts │ │ │ ├── AsciiPreview.svelte │ │ │ └── TitleLink.svelte │ ├── static │ │ ├── onefetch.ico │ │ └── robots.txt │ ├── svelte.config.js │ ├── tsconfig.json │ ├── vercel.json │ └── vite.config.ts └── wiki │ ├── _Footer.md │ ├── _Sidebar.md │ ├── ascii-art.md │ ├── command-line-options.md │ ├── getting-started.md │ ├── home.md │ ├── images-in-the-terminal.md │ ├── installation.md │ └── nix-local-setup.md ├── image ├── Cargo.toml ├── LICENSE.md ├── README.md └── src │ ├── iterm.rs │ ├── kitty.rs │ ├── lib.rs │ └── sixel.rs ├── languages.yaml ├── manifest ├── Cargo.toml ├── LICENSE.md ├── README.md ├── src │ └── lib.rs └── tests │ ├── cargo.rs │ ├── fixtures │ ├── cargo │ │ └── Cargo.toml │ └── npm │ │ └── package.json │ └── npm.rs ├── resources └── license.cache.zstd ├── scripts └── nf-preview.rb ├── snap └── snapcraft.yaml ├── src ├── cli.rs ├── info │ ├── authors.rs │ ├── churn.rs │ ├── commits.rs │ ├── contributors.rs │ ├── created.rs │ ├── dependencies.rs │ ├── description.rs │ ├── git │ │ ├── metrics.rs │ │ ├── mod.rs │ │ └── sig.rs │ ├── head.rs │ ├── langs │ │ ├── language.rs │ │ ├── language.tera │ │ └── mod.rs │ ├── last_change.rs │ ├── license.rs │ ├── loc.rs │ ├── mod.rs │ ├── pending.rs │ ├── project.rs │ ├── size.rs │ ├── snapshots │ │ ├── onefetch__info__authors__test__author_info_alignment_with_three_authors.snap │ │ ├── onefetch__info__authors__test__author_info_with_one_author.snap │ │ └── onefetch__info__authors__test__author_info_with_two_authors.snap │ ├── title.rs │ ├── url.rs │ ├── utils │ │ ├── info_field.rs │ │ ├── mod.rs │ │ └── snapshots │ │ │ └── onefetch__info__utils__info_field__test__write_styled.snap │ └── version.rs ├── lib.rs ├── main.rs └── ui │ ├── mod.rs │ ├── printer.rs │ └── text_colors.rs └── tests ├── fixtures ├── make_bare_repo.sh ├── make_partial_repo.sh ├── make_pre_epoch_repo.sh ├── make_repo.sh └── make_repo_without_remote.sh ├── repo.rs └── snapshots └── repo__repo.snap /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG VARIANT="bookworm" 2 | FROM mcr.microsoft.com/devcontainers/rust:1-${VARIANT} 3 | RUN sudo apt update && sudo apt install -y cmake 4 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "onefetch", 3 | "build": { 4 | "dockerfile": "Dockerfile", 5 | "args": { "VARIANT": "bookworm" } 6 | }, 7 | "customizations": { 8 | "vscode": { 9 | "extensions": ["EditorConfig.EditorConfig"] 10 | } 11 | }, 12 | "remoteUser": "vscode" 13 | } 14 | -------------------------------------------------------------------------------- /.devcontainer/website/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "onefetch.dev", 3 | "image": "mcr.microsoft.com/devcontainers/typescript-node:22-bullseye", 4 | "customizations": { 5 | "vscode": { 6 | "extensions": ["esbenp.prettier-vscode", "svelte.svelte-vscode"] 7 | } 8 | }, 9 | "postCreateCommand": "npm install" 10 | } 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = LF 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.{yml,yaml,md}] 12 | indent_size = 2 13 | 14 | [{Makefile,.SRCINFO}] 15 | indent_style = tab 16 | 17 | [*.json] 18 | indent_style = space 19 | indent_size = 2 20 | 21 | [*.rb] 22 | indent_style = space 23 | indent_size = 2 24 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | docs/vercel/** linguist-documentation 2 | **.snap linguist-language=Plain-Text 3 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | /.github/ @spenserblack @o2sh 2 | /image/src/ @cephalonRho @yoichi 3 | /src/info/ @o2sh 4 | /src/info/utils/git.rs @byron 5 | /src/info/langs/language.tera @spenserblack 6 | /languages.yaml @spenserblack @o2sh 7 | /src/cli.rs @spenserblack @o2sh 8 | /vercel/ @spenserblack 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug report 🐛 2 | description: Create a bug report to help us improve 3 | labels: ["bug"] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: Thanks for contributing by creating an issue! ❤️ 8 | - type: checkboxes 9 | attributes: 10 | label: Duplicates 11 | description: | 12 | Please [search the history](https://github.com/o2sh/onefetch/issues) to see if an issue already exists for the same problem. 13 | 14 | 📌 If your issue refers to an incorrect language detection, please have a look [here](https://github.com/o2sh/onefetch/issues/26). 15 | options: 16 | - label: I have searched the existing issues 17 | required: true 18 | - type: textarea 19 | attributes: 20 | label: Current behavior 😯 21 | description: Describe what happens instead of the expected behavior. 22 | - type: textarea 23 | attributes: 24 | label: Expected behavior 🤔 25 | description: Describe what should happen. 26 | - type: textarea 27 | attributes: 28 | label: Steps to reproduce 🕹 29 | description: Describe how we can reproduce this bug. 30 | placeholder: | 31 | 1. 32 | 2. 33 | 3. 34 | - type: textarea 35 | attributes: 36 | label: Additional context/Screenshots 🔦 37 | description: Add any other context about the problem here. If applicable, add screenshots to help explain. 38 | - type: textarea 39 | attributes: 40 | label: Possible Solution 💡 41 | description: Only if you have suggestions on a fix for the bug. 42 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 💄 2 | description: Suggest an improvement 3 | labels: ["enhancement"] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: Thanks for contributing by creating an issue! ❤️ 8 | - type: textarea 9 | attributes: 10 | label: Summary 💡 11 | description: Describe how it should work. 12 | - type: textarea 13 | attributes: 14 | label: Motivation 🔦 15 | description: > 16 | What are you trying to accomplish? 17 | How has the lack of this feature affected you? 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/new_language.yml: -------------------------------------------------------------------------------- 1 | name: New Language Request 📢 2 | description: Request for a new language to be supported 3 | labels: ["enhancement, good first issue"] 4 | 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: Thanks for contributing by creating an issue! ❤️ 9 | - type: textarea 10 | attributes: 11 | label: Language Name 🖊 12 | description: Provide the name of the language and any additional details that we should know. 13 | - type: textarea 14 | attributes: 15 | label: Logo 📷 16 | description: Is there a logo that can be used as a source of inspiration for the ASCII art? 17 | - type: checkboxes 18 | attributes: 19 | label: Upstream support ✅ 20 | description: | 21 | Onefetch relies on [tokei](https://github.com/XAMPPRocky/tokei) for language detection. 22 | options: 23 | - label: Does tokei already support the language in question? 24 | required: true 25 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | groups: 6 | clap: 7 | patterns: 8 | - "clap" 9 | - "clap_*" 10 | gix: 11 | patterns: 12 | - "gix" 13 | - "gix-*" 14 | schedule: 15 | interval: "weekly" 16 | open-pull-requests-limit: 10 17 | - package-ecosystem: "github-actions" 18 | directory: "/" 19 | schedule: 20 | interval: "weekly" 21 | - package-ecosystem: npm 22 | directory: /docs/vercel 23 | groups: 24 | site: 25 | patterns: 26 | - "*" 27 | schedule: 28 | interval: monthly 29 | -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | changelog: 2 | exclude: 3 | labels: 4 | - ignore-for-release 5 | categories: 6 | - title: New Features 7 | labels: 8 | - feat 9 | - title: Bug Fixes 10 | labels: 11 | - fix 12 | - title: Chores 13 | labels: 14 | - chore 15 | - refactor 16 | - doc 17 | - title: Dependencies 18 | labels: 19 | - dependencies 20 | - title: Other Changes 21 | labels: 22 | - "*" 23 | -------------------------------------------------------------------------------- /.github/workflows/cd.yml: -------------------------------------------------------------------------------- 1 | name: CD 2 | on: 3 | release: 4 | types: [published] 5 | env: 6 | CARGO_TERM_COLOR: always 7 | 8 | jobs: 9 | deploy: 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | os: [ubuntu-latest, macos-latest, windows-latest] 14 | runs-on: ${{ matrix.os }} 15 | 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v4 19 | 20 | - name: Setup Rust 21 | uses: actions-rust-lang/setup-rust-toolchain@v1 22 | 23 | - name: Build Release 24 | run: make build 25 | 26 | - name: Package release for Mac 27 | if: matrix.os == 'macos-latest' 28 | run: make release-mac 29 | 30 | - name: Package release for Linux 31 | if: matrix.os == 'ubuntu-latest' 32 | run: make release-linux 33 | 34 | - name: Package release for Windows 35 | if: matrix.os == 'windows-latest' 36 | run: make release-win 37 | 38 | - name: Publish to GitHub 39 | uses: softprops/action-gh-release@v2 40 | with: 41 | files: | 42 | ./release/*.tar.gz 43 | ./release/*.zip 44 | ./onefetch-setup.exe 45 | env: 46 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 47 | 48 | - name: Publish to Homebrew 49 | uses: mislav/bump-homebrew-formula-action@v3 50 | if: matrix.os == 'macos-latest' 51 | env: 52 | COMMITTER_TOKEN: ${{ secrets.BREW_TOKEN }} 53 | with: 54 | formula-name: onefetch 55 | 56 | - name: Publish to WinGet 57 | uses: vedantmgoyal9/winget-releaser@main 58 | if: matrix.os == 'windows-latest' 59 | with: 60 | identifier: o2sh.onefetch 61 | installers-regex: '\.exe$' 62 | version: ${{ github.event.release.tag_name }} 63 | token: ${{ secrets.WINGET_TOKEN }} 64 | 65 | crates: 66 | name: Publish to crates.io 67 | runs-on: ubuntu-latest 68 | 69 | steps: 70 | - name: Checkout 71 | uses: actions/checkout@v4 72 | 73 | - name: Setup Rust 74 | uses: actions-rust-lang/setup-rust-toolchain@v1 75 | 76 | - name: Publish to crates.io (ascii) 77 | env: 78 | CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} 79 | run: cargo publish -p onefetch-ascii 80 | 81 | - name: Publish to crates.io (image) 82 | env: 83 | CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} 84 | run: cargo publish -p onefetch-image 85 | 86 | - name: Publish to crates.io (manifest) 87 | env: 88 | CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} 89 | run: cargo publish -p onefetch-manifest 90 | 91 | - name: Publish to crates.io 92 | env: 93 | CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} 94 | run: cargo publish 95 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: ["*"] 5 | paths-ignore: 6 | - "docs/**" 7 | - "**.md" 8 | - "docs/vercel/**" 9 | pull_request: 10 | branches: [main] 11 | paths-ignore: 12 | - "docs/**" 13 | - "**.md" 14 | - "docs/vercel/**" 15 | env: 16 | CARGO_TERM_COLOR: always 17 | 18 | jobs: 19 | CI: 20 | strategy: 21 | matrix: 22 | os: [ubuntu-latest, windows-latest, macOS-latest] 23 | runs-on: ${{ matrix.os }} 24 | 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v4 28 | 29 | - name: Setup Rust 30 | uses: actions-rust-lang/setup-rust-toolchain@v1 31 | 32 | - name: Build 33 | run: cargo build --features=fail-on-deprecated 34 | 35 | - name: Run tests 36 | run: cargo test 37 | -------------------------------------------------------------------------------- /.github/workflows/msrv-badge.yml: -------------------------------------------------------------------------------- 1 | name: MSRV Badge 2 | on: 3 | schedule: 4 | # Once a week at midnight UTC 5 | - cron: "0 0 * * 0" 6 | workflow_dispatch: 7 | 8 | jobs: 9 | make-badge: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v4 15 | with: 16 | ref: ${{ github.event.pull_request.head.ref }} 17 | token: ${{ secrets.BADGE_TOKEN }} 18 | 19 | - name: Get Minimum Supported Rust Version 20 | uses: spenserblack/actions-msrv@v0.4 21 | id: get-msrv 22 | timeout-minutes: 60 23 | 24 | - name: Create Badge 25 | run: curl https://img.shields.io/badge/rustc-${{ steps.get-msrv.outputs.msrv }}%2B-blue > ./assets/msrv-badge.svg 26 | 27 | - name: Commit Badge 28 | continue-on-error: true 29 | run: | 30 | git status 31 | git pull --ff-only 32 | git add ./assets/msrv-badge.svg 33 | git config user.name "github-actions[bot]" 34 | git config user.email "github-actions[bot]@users.noreply.github.com" 35 | git commit -m "Update msrv badge [Skip CI]" 36 | git push 37 | -------------------------------------------------------------------------------- /.github/workflows/web-ci.yml: -------------------------------------------------------------------------------- 1 | name: Web UI CI 2 | on: 3 | push: 4 | branches: ["main"] 5 | paths: 6 | - "docs/vercel/**" 7 | pull_request: 8 | branches: [main] 9 | paths: 10 | - "docs/vercel/**" 11 | 12 | jobs: 13 | check: 14 | name: Check Vercel Code Quality 15 | runs-on: ubuntu-latest 16 | defaults: 17 | run: 18 | working-directory: docs/vercel 19 | 20 | steps: 21 | - name: Checkout 22 | uses: actions/checkout@v4 23 | 24 | - name: Setup Node 25 | uses: actions/setup-node@v4 26 | with: 27 | node-version: 20 28 | cache: npm 29 | cache-dependency-path: docs/vercel/package-lock.json 30 | 31 | - name: Install Dependencies 32 | run: npm ci 33 | 34 | - name: Svelte Check 35 | run: npm run check:svelte -- --fail-on-warnings 36 | 37 | - name: ESLint 38 | run: npm run check:lint 39 | 40 | - name: Prettier 41 | run: npm run check:prettier 42 | -------------------------------------------------------------------------------- /.github/workflows/wiki.yml: -------------------------------------------------------------------------------- 1 | name: Publish Wiki 2 | on: 3 | push: 4 | branches: [main] 5 | paths: 6 | - "docs/wiki/**" 7 | 8 | workflow_dispatch: 9 | 10 | concurrency: 11 | group: wiki 12 | cancel-in-progress: true 13 | permissions: 14 | contents: write 15 | jobs: 16 | wiki: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: actions/checkout@v4 20 | - uses: spenserblack/actions-wiki@v0.3.0 21 | with: 22 | path: docs/wiki 23 | -------------------------------------------------------------------------------- /.github/workflows/windows-installer.iss: -------------------------------------------------------------------------------- 1 | ; Script generated by the Inno Setup Script Wizard. 2 | ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! 3 | 4 | #define MyAppName "onefetch" 5 | ;#define MyAppVersion "1.0" 6 | #define MyAppPublisher "Ossama Hjaji" 7 | #define MyAppURL "https://github.com/o2sh/onefetch" 8 | #define MyAppExeName "onefetch.exe" 9 | 10 | [Setup] 11 | ; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications. 12 | ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) 13 | AppId={{BB44DE71-B34D-4707-AE9D-5FF3FA632283} 14 | AppName={#MyAppName} 15 | AppVersion={#MyAppVersion} 16 | ;AppVerName={#MyAppName} {#MyAppVersion} 17 | AppPublisher={#MyAppPublisher} 18 | AppPublisherURL={#MyAppURL} 19 | AppSupportURL={#MyAppURL} 20 | AppUpdatesURL={#MyAppURL} 21 | DefaultDirName={autopf}\{#MyAppName} 22 | DisableDirPage=yes 23 | DisableProgramGroupPage=yes 24 | ; Uncomment the following line to run in non administrative install mode (install for current user only.) 25 | ;PrivilegesRequired=lowest 26 | OutputDir=..\.. 27 | OutputBaseFilename=onefetch-setup 28 | SetupIconFile=..\..\assets\onefetch.ico 29 | UninstallDisplayIcon={app}\{#MyAppExeName} 30 | Compression=lzma 31 | SolidCompression=yes 32 | WizardStyle=modern 33 | ChangesEnvironment=true 34 | 35 | [Languages] 36 | Name: "english"; MessagesFile: "compiler:Default.isl" 37 | 38 | [Files] 39 | Source: "..\..\target\release\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion 40 | ; NOTE: Don't use "Flags: ignoreversion" on any shared system files 41 | 42 | [Icons] 43 | Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" 44 | 45 | [Code] 46 | { https://stackoverflow.com/a/46609047/149111 } 47 | const EnvironmentKey = 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'; 48 | procedure EnvAddPath(instlPath: string); 49 | var 50 | Paths: string; 51 | begin 52 | { Retrieve current path (use empty string if entry not exists) } 53 | if not RegQueryStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) then 54 | Paths := ''; 55 | if Paths = '' then 56 | Paths := instlPath + ';' 57 | else 58 | begin 59 | { Skip if string already found in path } 60 | if Pos(';' + Uppercase(instlPath) + ';', ';' + Uppercase(Paths) + ';') > 0 then exit; 61 | if Pos(';' + Uppercase(instlPath) + '\;', ';' + Uppercase(Paths) + ';') > 0 then exit; 62 | { Append App Install Path to the end of the path variable } 63 | if Paths[length(Paths)] <> ';' then 64 | Paths := Paths + ';'; 65 | Paths := Paths + instlPath + ';'; 66 | end; 67 | { Overwrite (or create if missing) path environment variable } 68 | if RegWriteStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) 69 | then Log(Format('The [%s] added to PATH: [%s]', [instlPath, Paths])) 70 | else Log(Format('Error while adding the [%s] to PATH: [%s]', [instlPath, Paths])); 71 | end; 72 | procedure EnvRemovePath(instlPath: string); 73 | var 74 | Paths: string; 75 | P, Offset, DelimLen: Integer; 76 | begin 77 | { Skip if registry entry not exists } 78 | if not RegQueryStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) then 79 | exit; 80 | { Skip if string not found in path } 81 | DelimLen := 1; { Length(';') } 82 | P := Pos(';' + Uppercase(instlPath) + ';', ';' + Uppercase(Paths) + ';'); 83 | if P = 0 then 84 | begin 85 | { perhaps instlPath lives in Paths, but terminated by '\;' } 86 | DelimLen := 2; { Length('\;') } 87 | P := Pos(';' + Uppercase(instlPath) + '\;', ';' + Uppercase(Paths) + ';'); 88 | if P = 0 then exit; 89 | end; 90 | { Decide where to start string subset in Delete() operation. } 91 | if P = 1 then 92 | Offset := 0 93 | else 94 | Offset := 1; 95 | { Update path variable } 96 | Delete(Paths, P - Offset, Length(instlPath) + DelimLen); 97 | { Overwrite path environment variable } 98 | if RegWriteStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) 99 | then Log(Format('The [%s] removed from PATH: [%s]', [instlPath, Paths])) 100 | else Log(Format('Error while removing the [%s] from PATH: [%s]', [instlPath, Paths])); 101 | end; 102 | 103 | procedure CurStepChanged(CurStep: TSetupStep); 104 | begin 105 | if CurStep = ssPostInstall then 106 | EnvAddPath(ExpandConstant('{app}')); 107 | end; 108 | procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); 109 | begin 110 | if CurUninstallStep = usPostUninstall then 111 | EnvRemovePath(ExpandConstant('{app}')); 112 | end; 113 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | /stage 4 | /parts 5 | /prime 6 | .gitignore.swp 7 | .DS_Store 8 | result 9 | **/generated-* 10 | **/.idea 11 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Ossama Hjaji 2 | Komeil Parseh 3 | Eduardo Broto 4 | -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | # See also https://rust-lang.github.io/rustfmt for more settings. 2 | edition = "2021" 3 | newline_style = "Unix" 4 | -------------------------------------------------------------------------------- /.tokeignore: -------------------------------------------------------------------------------- 1 | docs/vercel 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "search.exclude": { 3 | "**/node_modules": false, 4 | "**/target": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ### Getting started 2 | 3 | Follow the instructions for [installing onefetch from source](https://github.com/o2sh/onefetch/wiki/Installation#build-from-source). 4 | 5 | ### Adding support for a new language 6 | 7 | Adding support for a new Language consists in adding a new entry to [language.yaml](./languages.yaml) and filling it in with the right data. 8 | 9 | **Example**: 10 | 11 | ```yaml 12 | CSharp: # required, this will be the name of the enum variant for the language as specified by tokei (link 1) 13 | type: programming # required, can be programming, data, markup, or prose as specified by linguist (link 2) 14 | # required, this is the logo. If it's not within 25x40 bounds, you will get a compiler error. Use `{i}` to color the ascii with `i` the color index. 15 | ascii: | 16 | {0} ++++++ 17 | {0} ++++++++++++ 18 | {0} ++++++++++++++++++++ 19 | {0} ++++++++++++++++++++++++++ 20 | {0} ++++++++++++++++++++++++++++++++ 21 | {0} +++++++++++++{3}************{0}+++++++++++++ 22 | {0}+++++++++++{3}******************{0}++++++++{2};;; 23 | {0}+++++++++{3}**********************{0}++{2};;;;;;; 24 | {0}++++++++{3}*********{0}++++++{3}******{2};;;;;;;;;;; 25 | {0}+++++++{3}********{0}++++++++++{3}**{2};;;{3}**{2};;;{3}**{2};;; 26 | {0}+++++++{3}*******{0}+++++++++{2};;;;;;{3}*********{2}:: 27 | {0}+++++++{3}******{0}+++++++{2};;;;;;;;;;{3}**{2};;;{3}**{2};;; 28 | {0}+++++++{3}*******{0}+++{1}:::::{2};;;;;;;{3}*********{2};; 29 | {0}+++++++{3}********{1}::::::::::{3}**{2};;;{3}**{2};;;{3}**{2};;; 30 | {0}++++++++{3}*********{1}::::::{3}******{2};;;;;;;;;;; 31 | {0}++++++{1}:::{3}**********************{1}::{2};;;;;;; 32 | {0}+++{1}::::::::{3}******************{1}::::::::{2};;; 33 | {1} :::::::::::::{3}************{1}::::::::::::: 34 | {1} :::::::::::::::::::::::::::::::: 35 | {1} :::::::::::::::::::::::::: 36 | {1} :::::::::::::::::::: 37 | {1} :::::::::::: 38 | {1} :::::: 39 | colors: 40 | ansi: # required, a list of the ANSI colors used to colorize the logo 41 | - blue 42 | - magenta 43 | - magenta 44 | - white 45 | hex: # optional, alternative to basic colors for terminals that support true colour. 46 | - "#9B4F97" 47 | - "#67217A" 48 | - "#803788" 49 | - "#FFFFFF" 50 | chip: "#178600" # required, this is used for the language breakdown bar, its value can be found in linguist (link 2). 51 | icon: '\u{E648}' # optional, the UTF-16 code point of the nerd font icon if supported (link 3). 52 | serialization: c# # required only if the Enum name `CSharp` doesn't match the display name `C#` 53 | ``` 54 | 55 | - link 1: https://github.com/XAMPPRocky/tokei#supported-languages 56 | - link 2: https://github.com/github/linguist/blob/master/lib/linguist/languages.yml 57 | - link 3: https://www.nerdfonts.com/cheat-sheet 58 | 59 |

Special Thanks to

60 | 61 | - Every onefetch user, who contributed to the project by writing issues or PRs. 62 | - [@spenserblack](https://github.com/spenserblack) and [@Byron](https://github.com/Byron) for maintaining this project. 63 | - Everyone I forgot to mention here, but also influenced onefetch and helped it grow. 64 | 65 |

:heart::heart:

66 | 67 |

68 | 69 |

70 | 71 | Made with [contributors-img](https://contrib.rocks). 72 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace.package] 2 | authors = ["o2sh "] 3 | edition = "2021" 4 | license = "MIT" 5 | version = "2.24.0" 6 | repository = "https://github.com/o2sh/onefetch" 7 | 8 | [workspace] 9 | members = ["ascii", "image", "manifest"] 10 | 11 | [workspace.dependencies] 12 | owo-colors = "4.2.1" 13 | anyhow = "1.0" 14 | clap = { version = "4.5.34", features = ["derive"] } 15 | image = { version = "0.25.6", default-features = false, features = [ 16 | "color_quant", 17 | "jpeg", 18 | "png", 19 | "webp", 20 | ] } 21 | strum = { version = "0.26.3", features = ["derive"] } 22 | 23 | [package] 24 | authors.workspace = true 25 | edition.workspace = true 26 | version.workspace = true 27 | license.workspace = true 28 | repository.workspace = true 29 | categories = ["command-line-utilities"] 30 | description = "Command-line Git information tool" 31 | exclude = ["docs/vercel/*"] 32 | keywords = ["git", "cli", "terminal"] 33 | name = "onefetch" 34 | homepage = "https://onefetch.dev" 35 | rust-version = "1.82.0" 36 | 37 | [dependencies] 38 | anyhow.workspace = true 39 | askalono = "0.5.0" 40 | byte-unit = "5.1.6" 41 | clap.workspace = true 42 | clap_complete = "4.5.47" 43 | crossbeam-channel = "0.5.15" 44 | gix = { version = "0.72.1", default-features = false, features = [ 45 | "max-performance-safe", 46 | "blob-diff", 47 | "mailmap", 48 | "index", 49 | "status", 50 | ] } 51 | gix-features = { version = "0.42.1", features = ["zlib-ng"] } 52 | globset = "0.4.16" 53 | human-panic = "2.0.2" 54 | image.workspace = true 55 | num-format = "0.4.4" 56 | onefetch-ascii = { path = "ascii", version = "2.19.0" } 57 | onefetch-image = { path = "image", version = "2.19.0" } 58 | onefetch-manifest = { path = "manifest", version = "2.19.0" } 59 | owo-colors.workspace = true 60 | regex = "1.11.1" 61 | serde = "1.0" 62 | serde_json = "1.0" 63 | serde_yaml = "0.9.34" 64 | # TODO With the new value parsers, we're really close to being able to eliminate 65 | # the strum dependency 66 | strum.workspace = true 67 | time = { version = "0.3.41", features = ["formatting"] } 68 | time-humanize = { version = "0.1.3", features = ["time"] } 69 | tokei = "13.0.0-alpha.8" 70 | typetag = "0.2" 71 | 72 | [dev-dependencies] 73 | criterion = "0.6.0" 74 | gix-testtools = "0.16.1" 75 | insta = { version = "1.43.1", features = ["json", "redactions"] } 76 | rstest = "0.25.0" 77 | 78 | [[bench]] 79 | name = "repo" 80 | harness = false 81 | 82 | [build-dependencies] 83 | lazy_static = "1" 84 | regex = "1" 85 | serde_json = "1" 86 | serde_yaml = "0.9" 87 | tera = { version = "1", default-features = false } 88 | 89 | [target.'cfg(windows)'.build-dependencies] 90 | winres = "0.1" 91 | 92 | [target.'cfg(windows)'.dependencies] 93 | enable-ansi-support = "0.2.1" 94 | 95 | [features] 96 | fail-on-deprecated = [] 97 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Ossama Hjaji 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | install: 2 | cargo install --path "." --features=fail-on-deprecated 3 | 4 | build: 5 | cargo build --release --features=fail-on-deprecated 6 | 7 | uninstall: 8 | cargo uninstall onefetch 9 | 10 | clean: 11 | cargo clean 12 | 13 | release-mac: 14 | strip target/release/onefetch 15 | mkdir -p release 16 | tar -C ./target/release/ -czvf ./release/onefetch-mac.tar.gz ./onefetch 17 | 18 | release-win: TAG_NAME = $$(git describe --abbrev=0 --tags) 19 | release-win: 20 | mkdir -p release 21 | tar -C ./target/release/ -czvf ./release/onefetch-win.tar.gz ./onefetch.exe 22 | iscc.exe -DMyAppVersion=${TAG_NAME} ./.github/workflows/windows-installer.iss 23 | 24 | release-linux: 25 | strip target/release/onefetch 26 | mkdir -p release 27 | tar -C ./target/release/ -czvf ./release/onefetch-linux.tar.gz ./onefetch 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
Command-line Git information tool written in Rust
4 | 5 |

6 | cargo 7 | Build Status 8 | help wanted 9 | 10 | 11 |

12 | 13 |

14 | العربية | 15 | Česky | 16 | 简体中文 | 17 | Deutsch | 18 | Español | 19 | فارسی | 20 | Français | 21 | Italiano | 22 | 日本語 | 23 | 한국어 | 24 | Русский | 25 | Türkçe | 26 | Polski 27 |

28 | 29 | 30 | 31 | Onefetch is a command-line Git information tool written in `Rust` that displays project information and code statistics for a local Git repository directly to your terminal. The tool is completely offline - no network access is required. 32 | 33 | By default, the repo's information is displayed alongside the dominant language's logo, but you can further configure onefetch to instead use an image - on supported terminals -, a text input or nothing at all. 34 | 35 | It automatically detects open source licenses from texts and provides the user with valuable information like code distribution, pending changes, number of dependencies (by package manager), top contributors (by number of commits), size on disk, creation date, LOC (lines of code), etc. 36 | 37 | 38 | 39 | Onefetch can be configured via command-line flags to display exactly what you want, the way you want it to: you can customize ASCII/Text formatting, disable info lines, ignore files & directories, output in multiple formats (Json, Yaml), etc. 40 | 41 | As of now, onefetch supports more than [100 different programming languages](https://onefetch.dev); if your language of choice isn't supported: Open up an issue and support will be added. 42 | 43 | Contributions are very welcome! See [CONTRIBUTING](CONTRIBUTING.md) for more info. 44 | 45 | *Artwork by @Kuvshinov_Ilya* 46 | 47 | ### More: \[[Wiki](https://github.com/o2sh/onefetch/wiki)\] \[[Installation](https://github.com/o2sh/onefetch/wiki/Installation)\] \[[Getting Started](https://github.com/o2sh/onefetch/wiki/getting-started)\] 48 | -------------------------------------------------------------------------------- /ascii/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors.workspace = true 3 | edition.workspace = true 4 | version.workspace = true 5 | license.workspace = true 6 | repository.workspace = true 7 | name = "onefetch-ascii" 8 | description = "Display colorized ascii art to the terminal" 9 | 10 | [dependencies] 11 | owo-colors.workspace = true 12 | -------------------------------------------------------------------------------- /ascii/LICENSE.md: -------------------------------------------------------------------------------- 1 | ../LICENSE.md -------------------------------------------------------------------------------- /ascii/README.md: -------------------------------------------------------------------------------- 1 | # ascii 2 | 3 | [![crates.io](https://img.shields.io/crates/v/onefetch-ascii)](https://crates.io/crates/onefetch-ascii) 4 | [![docs.rs](https://img.shields.io/docsrs/onefetch-ascii)](https://docs.rs/onefetch-ascii) 5 | 6 | Provides the primary interface to display ascii art to the terminal. 7 | 8 | More info [here](https://github.com/o2sh/onefetch/wiki/ascii-art). 9 | 10 | _This crate is designed as part of the [onefetch](https://github.com/o2sh/onefetch) project._ 11 | -------------------------------------------------------------------------------- /assets/msrv-badge.svg: -------------------------------------------------------------------------------- 1 | rustc: 1.82.0+rustc1.82.0+ -------------------------------------------------------------------------------- /assets/onefetch.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/o2sh/onefetch/be4f2c8235100730a9c80954e93a5d2296294f8a/assets/onefetch.ico -------------------------------------------------------------------------------- /assets/screenshot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/o2sh/onefetch/be4f2c8235100730a9c80954e93a5d2296294f8a/assets/screenshot-1.png -------------------------------------------------------------------------------- /assets/screenshot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/o2sh/onefetch/be4f2c8235100730a9c80954e93a5d2296294f8a/assets/screenshot-2.png -------------------------------------------------------------------------------- /benches/repo.rs: -------------------------------------------------------------------------------- 1 | use criterion::{criterion_group, criterion_main, Criterion}; 2 | use gix::{open, ThreadSafeRepository}; 3 | use onefetch::{cli::CliOptions, info::build_info}; 4 | use std::hint::black_box; 5 | 6 | fn bench_repo_info(c: &mut Criterion) { 7 | let name = "make_repo.sh".to_string(); 8 | let repo_path = gix_testtools::scripted_fixture_read_only(name).unwrap(); 9 | let repo = ThreadSafeRepository::open_opts(repo_path, open::Options::isolated()).unwrap(); 10 | let config: CliOptions = CliOptions { 11 | input: repo.path().to_path_buf(), 12 | ..Default::default() 13 | }; 14 | 15 | c.bench_function("get repo information", |b| { 16 | b.iter(|| { 17 | let result = black_box(build_info(&config)); 18 | assert!(result.is_ok()); 19 | }); 20 | }); 21 | } 22 | 23 | criterion_group!(benches, bench_repo_info); 24 | criterion_main!(benches); 25 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | use lazy_static::lazy_static; 2 | use regex::Regex; 3 | use std::collections::HashMap; 4 | use std::env; 5 | use std::error::Error; 6 | use std::fs::{self, File}; 7 | use std::path::Path; 8 | use tera::{Context, Tera}; 9 | 10 | fn main() -> Result<(), Box> { 11 | #[cfg(windows)] 12 | { 13 | let mut res = winres::WindowsResource::new(); 14 | res.set_icon("assets/onefetch.ico"); 15 | res.compile()?; 16 | } 17 | let out_dir = env::var("OUT_DIR").expect("No OUT_DIR variable."); 18 | let mut tera = Tera::default(); 19 | tera.register_filter("strip_color_tokens", strip_color_tokens_filter); 20 | tera.register_filter("hex_to_rgb", hex_to_rgb_filter); 21 | 22 | let lang_data: serde_json::Value = serde_yaml::from_reader(File::open("languages.yaml")?)?; 23 | 24 | let output_path = Path::new(&out_dir).join("language.rs"); 25 | 26 | let rust_code = tera.render_str( 27 | &std::fs::read_to_string("src/info/langs/language.tera")?, 28 | &Context::from_value(serde_json::json!({ "languages": lang_data, }))?, 29 | )?; 30 | fs::write(output_path, rust_code)?; 31 | 32 | Ok(()) 33 | } 34 | 35 | /// Strips out `{n}` from the given string. 36 | fn strip_color_tokens_filter( 37 | value: &tera::Value, 38 | _args: &HashMap, 39 | ) -> tera::Result { 40 | lazy_static! { 41 | static ref COLOR_INDEX_REGEX: Regex = Regex::new(r"\{\d+\}").unwrap(); 42 | } 43 | let s = match value { 44 | tera::Value::String(s) => s, 45 | _ => return Err(tera::Error::msg("expected string")), 46 | }; 47 | Ok(tera::Value::String( 48 | COLOR_INDEX_REGEX.replace_all(s, "").to_string(), 49 | )) 50 | } 51 | 52 | fn hex_to_rgb_filter( 53 | value: &tera::Value, 54 | _args: &HashMap, 55 | ) -> tera::Result { 56 | let hex_string = match value { 57 | tera::Value::String(s) => s, 58 | _ => return Err(tera::Error::msg("expected string")), 59 | }; 60 | let hex_string = match hex_string.strip_prefix('#') { 61 | Some(s) => s, 62 | None => return Err(tera::Error::msg("expected hex string starting with `#`")), 63 | }; 64 | if hex_string.len() != 6 { 65 | return Err(tera::Error::msg("expected a 6 digit hex string")); 66 | } 67 | let channel_bytes = match u32::from_str_radix(hex_string, 16) { 68 | Ok(n) => n, 69 | Err(_) => return Err(tera::Error::msg("expected a valid hex string")), 70 | }; 71 | let r = (channel_bytes >> 16) & 0xFF; 72 | let g = (channel_bytes >> 8) & 0xFF; 73 | let b = channel_bytes & 0xFF; 74 | 75 | Ok(serde_json::json!({ 76 | "r": r, 77 | "g": g, 78 | "b": b, 79 | })) 80 | } 81 | -------------------------------------------------------------------------------- /docs/README.ar.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
Rust مكتوبه بالغة GIT أداة سطر الأوامر لعرض معلومات مستودع
4 | 5 |

6 | cargo 7 | Build Status 8 | help wanted 9 | 10 | 11 |

12 | 13 | 14 | 15 |

16 | Onefetch 17 | هي أداة سطر الأوامر مكتوبة بالغة 18 | Rust 19 | تعرض معلومات المشروع وإحصائيات الكود لمستودع 20 | Git 21 | .المحلي مباشرة الي جهازك الطرفي 22 | الأداة مستقلة تمامًا عن الإنترنت - لا يتطلب الوصول إلى الشبكة. 23 |

24 | 25 |

26 | يتم عرض معلومات المستودع جنباً إلي جنب مع شعار اللغة السائدة في المشروع بشكل إفتراضي، ولكن يمكنك أيضاً تكوين 27 | Onefetch 28 | بحيث يستخدم بدلاً من ذلك صورة - على الأنظمة المدعومة - أو إدخال نص أو حتى لا شيء على الإطلاق. 29 |

30 | 31 |

32 | يكتشف تلقائياً التراخيص مفتوحة المصدر من النصوص، ويزود المستخدم بمعلومات قيمة مثل توزيع الكود، التغييرات المعلقة، عدد التبعيات (بواسطة مدير الحزم)، المساهمين الأساسين (حسب عدد الالتزامات)، وحجم المستودع علي القرص الصلب، وتاريخ الإنشاء، 33 | LOC 34 | (عدد أسطر الكود)، إلخ. 35 |

36 | 37 | 38 | 39 |

40 | يمكن تكوين 41 | Onefetch 42 | عن طريق معلمات سطر الأوامر 43 | (Flags) 44 | لعرض ما تريده بالضبط، بالطريقة التي تريدها. 45 | يمكنك تخصيص تنسيق النص/ 46 | ASCII 47 | ، وتعطيل المعلومات التي لا تهمك، وتجاهل الملفات والمجلدات، وإخراج النتائج بتنسيقات مختلفة 48 | مثل 49 | (Json, Yaml) 50 | إلخ. 51 |

52 | 53 |

54 | حتى الآن، يدعم 55 | Onefetch 56 | أكثر من 57 | 100 لغة برمجة مختلفة 58 | ؛ إذا لم تكن لغتك المفضلة مدعومة: افتح مشكلة وسيتم إضافة الدعم. 59 |

60 | 61 |

62 | المساهمات مرحب بها جداً جداً جداً! انظر 63 | دليل المساهمة 64 | لمزيد من المعلومات. 65 |

66 | 67 | ### المزيد: \[[ويكي](https://github.com/o2sh/onefetch/wiki)\] \[[التثبيت](https://github.com/o2sh/onefetch/wiki/Installation)\] \[[البدء](https://github.com/o2sh/onefetch/wiki/getting-started)\] 68 | -------------------------------------------------------------------------------- /docs/README.cn.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
Rust编写的一款命令行Git信息工具
4 | 5 |

6 | cargo 7 | Build Status 8 | help wanted 9 | 10 | 11 |

12 | 13 | 14 | 15 | Onefetch 是一款由 `Rust` 编写的命令行 Git 信息工具,它将直接在终端中展示本地 Git 仓库的项目详情和代码统计等内容。工具完全离线可用(不需要网络连接)。

16 | 17 | 默认情况下,仓库信息显示在主要语言 logo 的旁边,但是您还可以进一步配置 onefetch 以使用图像(在支持的终端上)、文本输入或什么都不展示。

18 | 19 | 它会自动从文本中检测开源许可证,并为用户提供有价值的信息,例如代码分发、pending、依赖数量(使用包管理器)、主要贡献者(按提交次数)、占用磁盘大小、创建日期、LOC(代码行数)等。

20 | 21 | 22 | 23 | Onefetch 可以通过命令行参数进行配置,以准确显示您想要的内容和方式:您可以自定义 ASCII/文本格式、禁用信息行、忽略文件和目录、以多种格式输出(Json、Yaml),等等。

24 | 25 | 截至目前,onefetch 支持超过 100 种不同的编程语言;如果您选择的语言不受支持:创建一个 issue,我们将尽快适配。

26 | 27 | 欢迎大家一起来维护项目!详见 [CONTRIBUTING](../CONTRIBUTING.md).

28 | 29 | ### 更多: \[[Wiki](https://github.com/o2sh/onefetch/wiki)\] \[[安装](https://github.com/o2sh/onefetch/wiki/Installation)\] \[[开始使用](https://github.com/o2sh/onefetch/wiki/getting-started)\] 30 | -------------------------------------------------------------------------------- /docs/README.cs.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
Informační nástroj Git pro příkazový řádek vytvořený v Rust
4 | 5 |

6 | cargo 7 | Build Status 8 | help wanted 9 | 10 | 11 |

12 | 13 | 14 | 15 | Onefetch je informační nástroj Git pro příkazový řádek napsaný v `Rust`, který zobrazuje informace o projektu a statistiky kódu pro lokální úložiště Git přímo ve vašem terminálu. Nástroj je zcela offline – není vyžadován žádný přístup k síti. 16 | 17 | Ve výchozím nastavení se informace o úložišti zobrazují vedle loga dominantního jazyka, ale můžete si onefetch nakonfigurovat tak, aby místo toho používal obrázek (na podporovaných terminálech), textový vstup nebo vůbec nic. 18 | 19 | Automaticky detekuje licence open source z textů a poskytuje uživateli cenné informace, jako je distribuce kódu, čekající změny, počet závislostí (podle správce balíčků), hlavní přispěvatelé (podle počtu potvrzení), velikost na disku, datum vytvoření, počet řádků kódu atd. 20 | 21 | 22 | 23 | Onefetch lze nakonfigurovat tak, aby zobrazoval přesně to, co chcete, způsobem, jakým to chcete: můžete přizpůsobit formátování ASCII/Text, zakázat informační řádky, ignorovat soubory a adresáře, výstup ve více formátech (Json, Yaml), atd. 24 | 25 | V současné době podporuje onefetch více než [100 různých programovacích jazyků](https://onefetch.dev); pokud váš vybraný jazyk není podporován: Otevřete nový požadavek a podpora bude přidána. 26 | 27 | Příspěvky jsou vítány! Další informace najdete v [CONTRIBUTING](CONTRIBUTING.md). 28 | 29 | ### Více: \[[Wiki](https://github.com/o2sh/onefetch/wiki)\] \[[Instalace](https://github.com/o2sh/onefetch/wiki/Installation)\] \[[Začínáme](https://github.com/o2sh/onefetch/wiki/getting-started)\] 30 | -------------------------------------------------------------------------------- /docs/README.de.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
Kommandozeilen-Git-Informationstool geschrieben in Rust
4 | 5 |

6 | cargo 7 | Build Status 8 | help wanted 9 | 10 | 11 |

12 | 13 | 14 | 15 | Onefetch ist ein in `Rust` geschriebenes Kommandozeilen-Git-Informationstool, das Projektinformationen und Codestatistiken für ein lokales Git-Repository direkt in Ihrem Terminal anzeigt. Das Tool ist komplett offline - es ist kein Netzwerkzugang erforderlich. 16 | 17 | Standardmäßig werden die Repository-Informationen zusammen mit dem Logo der vorherrschenden Sprache angezeigt, aber du kannst onefetch auch so konfigurieren, dass es stattdessen ein Bild - auf unterstützten Terminals -, eine Texteingabe oder gar nichts anzeigt. 18 | 19 | Es erkennt automatisch Open-Source-Lizenzen aus Texten und versorgt den Benutzer mit wertvollen Informationen wie Code-Verteilung, ausstehende Änderungen, Anzahl der Abhängigkeiten (nach Paketmanager), Top-Beitragende (nach Anzahl der Commits), Größe auf der Festplatte, Erstellungsdatum, LOC (Lines of Code), etc. 20 | 21 | 22 | 23 | Onefetch kann über Befehlszeilen-Flags so konfiguriert werden, dass es genau das anzeigt, was du möchtest, und zwar so, wie du es willst: du kannst die ASCII-/Text-Formatierung anpassen, Infozeilen deaktivieren, Dateien und Verzeichnisse ignorieren, aus verschiedenen Ausgabeformaten (Json, Yaml) wählen usw. 24 | 25 | Ab sofort unterstützt onefetch mehr als [100 verschiedene Programmiersprachen](https://onefetch.dev); wenn die Sprache Ihrer Wahl nicht unterstützt wird: Erstelle ein neues Issue und die Übersetzung wird hinzugefügt. 26 | 27 | Beiträge sind sehr willkommen! Siehe [CONTRIBUTING](../CONTRIBUTING.md) für weitere Informationen. 28 | 29 | ### Mehr: \[[Wiki](https://github.com/o2sh/onefetch/wiki)\] \[[Installation](https://github.com/o2sh/onefetch/wiki/Installation)\] \[[Erste Schritte](https://github.com/o2sh/onefetch/wiki/getting-started)\] 30 | -------------------------------------------------------------------------------- /docs/README.es.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
Una herramienta de información de Git de línea de comandos escrita en Rust
4 | 5 |

6 | cargo 7 | Build Status 8 | help wanted 9 | 10 | 11 |

12 | 13 | 14 | 15 | Onefetch es una herramienta de información Git de línea de comandos escrita en `Rust` que muestra información del proyecto y estadísticas de código para un repositorio Git local directamente en su terminal. La herramienta funciona sin conexión a internet. 16 | 17 | De manera predeterminada, la información del repositorio se muestra junto con el logotipo del lenguaje dominante, pero puede configurar onefetch para usar una imagen, en terminales compatibles, una entrada de texto o nada en absoluto. 18 | 19 | Detecta automáticamente las licencias de código abierto de los textos y proporciona al usuario información valiosa como distribución de código, cambios pendientes, número de dependencias (por administrador de paquetes), principales contribuyentes (por número de confirmaciones), tamaño en disco, fecha de creación, LOC (líneas de código), etc. 20 | 21 | 22 | 23 | Onefetch se puede configurar a través de indicadores de línea de comandos para mostrar exactamente lo que desea, de la manera que desea: puede personalizar el formato de texto/ASCII, deshabilitar líneas de información, ignorar archivos y directorios, salida en múltiples formatos (Json, Yaml), etc. 24 | 25 | A partir de ahora, onefetch admite más de 100 lenguajes de programación diferentes;si el lenguaje de su elección no es compatible: abra una propuesta (issue) y se agregará soporte. 26 | 27 | ¡Las contribuciones son muy bienvenidas! Consulte [CONTRIBUTING](../CONTRIBUTING.md) para obtener más información. 28 | 29 | ### Más: \[[Wiki](https://github.com/o2sh/onefetch/wiki)\] \[[Instalación](https://github.com/o2sh/onefetch/wiki/Installation)\] \[[Para Empezar](https://github.com/o2sh/onefetch/wiki/getting-started)\] 30 | -------------------------------------------------------------------------------- /docs/README.fa.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |

4 | 5 |
یک ابزار کامند لاینی برای نمایش دادن اطلاعات گیت نوشته شده با زبان برنامه‌نویسی راست
6 | 7 |

8 | cargo 9 | Build Status 10 | help wanted 11 | 12 | 13 |

14 | 15 | 16 | 17 | Onefetch یک ابزار کامند لاینی نوشته شده با زبان راست است که اطلاعات پروژه و آمار کد را برای یک مخزن محلی گیت مستقیماً در ترمینال شما نمایش می دهد. این ابزار کاملا آفلاین است و به دسترسی اینترنت نیازی نیست. 18 | 19 | به طور پیش‌فرض، اطلاعات ریپازیتوری در کنار لوگو زبان برنامه‌نویسی نمایش داده میشود. 20 | 21 | شما میتوانید پیکربندی های بیشتری اعمال کنید تا بجای تصویر پیشفرض -در ترمینال های پشتیبانی شده- عکس یا متن دیکری نمایش داده شود. 22 | 23 | این به طور خودکار مجوزهای منبع باز را از متن شناسایی می کند و اطلاعات ارزشمندی مانند توضیح ریپازیتوری ، تغییرات در حال انتظار ، تعداد وابستگی ها (توسط مدیر بسته) ، مشارکت کنندگان برتر (بر اساس تعداد کامیت ها) ، اندازه روی دیسک ، تاریخ ایجاد ریپازیتوری، LOC (تعداد خطوط کد) و غیره را در اختیار کاربر قرار می دهد. 24 | 25 | 26 | 27 | Onefetch را می توان از طریق پرچم های خط فرمان پیکربندی کرد تا دقیقاً همان چیزی را که می خواهید نمایش دهد ، همانطور که می خواهید: شما می توانید قالب‌بندی اَسکی/متن را سفارش سازی کنید ، خطوط اطلاعات را غیرفعال کنید ، پرونده ها و دایرکتوری ها را نادیده بگیرید ، خروجی در چندین قالب (Json ، Yaml) قرار دهید و کار های دیگر که این ابزار میتواند انجام دهد. 28 | 29 | Onefetch بیش از 100 زبان برنامه نویسی مختلف پشتیبانی می کند. اگر زبان انتخابی شما پشتیبانی نمی شود: [مسئله ای](https://github.com/o2sh/onefetch/issues/new/choose) را باز کنید و تا آن زبان به برنامه اضافه شود. 30 | 31 | برای مشارکت بسیار خوش آمدید! این [فایل را](../CONTRIBUTING.md) برای اطلاعات بیشتر مطالعه کنید. 32 | 33 | ### سایر لینک ها: \[[ویکی](https://github.com/o2sh/onefetch/wiki)\] \[[نصب کردن](https://github.com/o2sh/onefetch/wiki/Installation)\] \[[شروع](https://github.com/o2sh/onefetch/wiki/getting-started)\] 34 | 35 |
36 | -------------------------------------------------------------------------------- /docs/README.fr.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
Outil Git en ligne de commande écrit en Rust
4 | 5 |

6 | cargo 7 | Build Status 8 | help wanted 9 | 10 | 11 |

12 | 13 | 14 | 15 | Onefetch est un outil Git en ligne de commande écrit en `Rust` qui permet d'afficher les informations d'un projet et des statistiques de codes pour un dépôt local directement depuis un terminal. L'outil est complètement hors ligne - aucun accès réseau n'est requis. 16 | 17 | Par défaut, les informations du dépôt sont affichées à côté d'une représentation ASCII du logo du langage dominant, mais vous pouvez choisir d'afficher une image à la place - sur les terminaux le supportant -, du texte, ou laisser vide. 18 | 19 | Il détecte automatiquement les licences open sources et fournit à l'utilisateur plusieurs informations utiles comme la décomposition du code par langage, les changements en attentes, le nombres de dépendances (par gestionnaire de paquets), les principaux contributeurs (par nombre de commits), la taille du dépôt sur le disque, la date de création, le nombre de lignes de code, etc. 20 | 21 | 22 | 23 | Onefetch peut être configuré afin d'afficher exactement ce que vous souhaitez, comme vous le souhaitez : vous pouvez personnaliser le formatage du texte, cacher certaines lignes, ignorer des fichiers & répertoires, générer la sortie dans plusieurs formats (Json, Yaml), etc. 24 | 25 | Actuellement, onefetch supporte plus de [100 langages de programmation](https://onefetch.dev); si le langage de votre choix n'est pas supporté, créez une issue et le support sera ajouté. 26 | 27 | Les contributions sont plus que bienvenues! Rendez-vous sur la page [CONTRIBUTING](../CONTRIBUTING.md) pour plus d'informations. 28 | 29 | ### Compléments: \[[Wiki](https://github.com/o2sh/onefetch/wiki)\] \[[Installation](https://github.com/o2sh/onefetch/wiki/Installation)\] \[[Premiers Pas](https://github.com/o2sh/onefetch/wiki/getting-started)\] 30 | -------------------------------------------------------------------------------- /docs/README.it.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
Uno strumento a riga di comando per informazioni su Git scritto in Rust
4 | 5 |

6 | cargo 7 | Build Status 8 | help wanted 9 | 10 | 11 |

12 | 13 | 14 | 15 | Onefetch è uno strumento a riga di comando per ottenere informazioni su Git ed è scritto in `Rust`. Il programma mostra le informazioni e le statistiche del codice di una repository locale direttamente nel terminale, senza necessitare di una connessione ad Internet. 16 | 17 | Di default, le informazioni della repo vengono mostrate accanto al logo del linguaggio più utilizzato, ma è possibile configurare Onefetch in modo che mostri un'immagine (se il terminale lo supporta), del testo fornito come input oppure nulla. 18 | 19 | Rileva automaticamente le licenze open source e fornisce all'utente informazioni utili riguardo alla distribuzione del codice, ai cambiamenti in attesa, al numero di dipendenze (divise per package manager), ai maggiori contributori (per numero di commit), alla dimensione sul disco, alla data di creazione, alle linee di codice, ecc. 20 | 21 | 22 | 23 | Onefetch può essere configurato con delle flag per mostrare esattamente ciò che desideri, nel modo che preferisci: puoi personalizzare l'ASCII e la formattazione del testo, disabilitare informazioni specifiche, ignorare file e cartelle e formattare il testo in formati come JSON e YAML, ecc. 24 | 25 | Al momento onefetch supporta più di [100 diversi linguaggi di programmazione](https://onefetch.dev); Se il linguaggio che hai scelto non è supportato apri una issue e lo supporteremo. 26 | 27 | I contributi sono molto graditi! Vedi [CONTRIBUTING](../CONTRIBUTING.md) per avere più informazioni. 28 | 29 | ### Altro: \[[Wiki](https://github.com/o2sh/onefetch/wiki)\] \[[Installazione](https://github.com/o2sh/onefetch/wiki/Installation)\] \[[Per iniziare](https://github.com/o2sh/onefetch/wiki/getting-started)\] 30 | -------------------------------------------------------------------------------- /docs/README.ja.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
‎Rustで書かれたコマンドラインインターフェースのGit情報ツール‎
4 | 5 |

6 | cargo 7 | Build Status 8 | help wanted 9 | 10 | 11 |

12 | 13 | 14 | 15 | Onefetch は`Rust`で書かれたコマンドラインインターフェースの Git 情報ツールで、ローカルにある Git リポジトリのプロジェクト情報やコードの統計をターミナルへ直接表示します。このツールは常にオフラインで動作し、ネットワークへのアクセスは必要ありません。 16 | 17 | ‎ デフォルトの設定ではリポジトリ内の情報は主要な言語のロゴと一緒に表示されますが、代わりに画像(ターミナルでサポートされている場合)やテキスト、または何も表示しないように設定できます。 18 | 19 | テキストからオープンソースライセンスを自動的に検出し、ソースコードの配布ページや保留中の変更、依存関係の数(パッケージマネージャーによる)、トップコントリビューター(コミット数による)、ディスク上のサイズ、作成日、LOC(コードの行数)などの有益な情報をユーザーに提供します。 20 | 21 | 22 | 23 | Onefetch はコマンドラインフラグを使用して ASCII/テキストフォーマットのカスタマイズや情報行の無効化、ファイルやディレクトリの除外、複数のフォーマット(JSON、YAML)での出力など設定できます。 24 | 25 | ‎ 現在、Onefetch は 100 種類以上のプログラミング言語をサポートしています。選択した言語がサポートされていない場合は Issue を追加してください。 26 | 27 | 貢献は大歓迎です。詳しくは [CONTRIBUTING](../CONTRIBUTING.md) をご覧ください。 28 | 29 | ### 詳細: \[[Wiki](https://github.com/o2sh/onefetch/wiki)\] \[[Installation](https://github.com/o2sh/onefetch/wiki/Installation)\] \[[Getting Started](https://github.com/o2sh/onefetch/wiki/getting-started)\] 30 | -------------------------------------------------------------------------------- /docs/README.kr.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
Rust로 작성된 깃 정보 커맨드라인 유틸리티
4 | 5 |

6 | cargo 7 | Build Status 8 | help wanted 9 | 10 | 11 |

12 | 13 | 14 | 15 | Onefetch는 `Rust`로 작성된 깃 정보 유틸리티 입니다. Onefetch를 사용하면 네트워크 연결이 필요 없이 터미널에서 바로 로컬 깃 저장소의 프로젝트 정보와 코드 통계 등을 볼 수 있습니다. 16 | 17 | 기본적으로, 해당 저장소 정보와 함께 가장 많이 쓰인 프로그래밍 언어의 로고가 표시됩니다. 하지만 (만약 터미널이 지원한다면) 이미지, 원하는 텍스트, 또는 아무것도 표시하지 않도록 설정할 수도 있습니다. 18 | 19 | Onefetch는 텍스트를 읽고 어떤 라이선스를 사용 중인지 자동으로 알아내며, 언어 종류, 대기중인 커밋, (패키지 관리자별) 의존성 갯수, 가장 많이 커밋한 기여자들, 총 용량, 만들어진 날짜, 총 코드 줄 수 등 다양한 정보를 보여줍니다. 20 | 21 | 22 | 23 | 또한 명령줄 인자를 통해 정확히 어떤 부분을 보여줄지 원하는 대로 설정할 수 있습니다. 예를 들어 텍스트 포맷을 변경하거나, 정보 칸을 표시하지 않거나, 특정 파일 또는 폴더를 무시하거나, Json또는 Yaml등 다양한 포맷으로 출력할 수 있습니다. 24 | 25 | 현재 onefetch는 [100개가 넘는 프로그래밍 언어들](https://onefetch.dev)을 지원합니다. 만약 여러분이 사용하는 언어가 포함되어있지 않다면 새 이슈를 열어주세요. 26 | 27 | 기여는 언제나 환영입니다! [CONTRIBUTING](../CONTRIBUTING.md)에서 더 자세한 내용을 확인해주세요. 28 | 29 | ### 더 알아보기: \[[Wiki](https://github.com/o2sh/onefetch/wiki)\] \[[Installation](https://github.com/o2sh/onefetch/wiki/Installation)\] \[[Getting Started](https://github.com/o2sh/onefetch/wiki/getting-started)\] 30 | -------------------------------------------------------------------------------- /docs/README.pl.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
Narzędzie informacyjne Git CLI napisane w Rust
4 | 5 |

6 | cargo 7 | Build Status 8 | help wanted 9 | 10 | 11 |

12 | 13 | 14 | 15 | Onefech jest narzędziem informacyjnym Git CLI napisanym w `Rust`. Wyświetla ono informacje o projekcie i statystyki kodu lokalnego repozytorium bezpośrednio w terminalu. Jest także w pełni offline - dostęp do internetu nie jest wymagany. 16 | 17 | Domyślnie, informacje o repozytorium są wyświetlane obok logo dominującego języka, ale można skonfigurować Onefetch aby zamiast tego wyświetlał zdjęcie (we wspieranych terminalach), tekst lub nic. 18 | 19 | Narzędzie automatycznie wykrywa licencje open source i zapewnia użytkownikowi cenne informacje, takie jak dystrybucja kodu, oczekujące zmiany, liczba zależności (według menedżera pakietów), top contributorzy (według liczby commitów), rozmiar na dysku, data utworzenia, number linii kodu, itp. 20 | 21 | 22 | 23 | Onefetch może być konfigurowany poprzez flagi CLI tak, aby wyświetlał dokładnie to, czego chcesz, tak, jak chcesz: można dostosować formatowanie ASCII/tekstu, wyłączyć wiersze informacyjne, ignorować pliki i katalogi, a nawet outputować dane w różnych formatach (JSON, YAML) itd. 24 | 25 | Obecnie onefetch obsługuje ponad [100 różnych języków programowania](https://onefetch.dev). Jeśli wybrany przez Ciebie język nie jest obsługiwany: zgłoś Issue, a wsparcie zostanie dodane. 26 | 27 | Wkłady są mile widziane! Więcej informacji znajdziesz w [CONTRIBUTING](../CONTRIBUTING.md). 28 | 29 | ### Więcej: \[[Wiki](https://github.com/o2sh/onefetch/wiki)\] \[[Instalacja](https://github.com/o2sh/onefetch/wiki/Installation)\] \[[Jak Zacząć](https://github.com/o2sh/onefetch/wiki/getting-started)\] 30 | -------------------------------------------------------------------------------- /docs/README.ru.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
Утилита коммандной строки для вывода информации о Git 4 | репозиториях, написанная на Rust
5 | 6 |

7 | cargo 8 | Build Status 9 | help wanted 10 | 11 | 12 |

13 | 14 | 15 | 16 | Onefetch - это инструмент коммандной строки для вывода инфомации о Git репозиториях, написанная на `Rust`, которая отображает информацию о проекте и статистику кода локального Git репозитория прямо в ваш теминал. Утилита может работать полностью оффлайн - доступ к сети не нужен. 17 | 18 | По умолчанию информация о репозитории отображается вместе с логотипом главного 19 | языка программирования, но вы можете сделать так, чтобы Onefetch использовал 20 | изображение (если терминал это позволяет), читал ваш собственный ASCII-рисунок 21 | или вообще не выводил его. 22 | 23 | Утилита автоматически обнаруживает OpenSource лицензии по их тексту и предоставляет 24 | различную информацию, вроде языков программирования, из которых состоит 25 | репозиторий, изменений, ожидающих подтверждения, числа зависимостей (по 26 | пакетному менеджеру), главных контрибьюторов (по числу коммитов), 27 | размера занимаемого места на диске, даты создания, количества строк и т.п. 28 | 29 | 30 | 31 | Onefetch конфигурируется через флаги, позволяющие отображать только нужную вам 32 | информацию, в нужном вам виде: вы можете менять форматирование текста, 33 | выключать отображение определенных полей, игнорировать определенные файлы и директории, 34 | выводить информацию в различных форматах (Json, Yaml) и т.д. 35 | 36 | На данный момент Onefetch поддерживает более [100 языков программирования](https://onefetch.dev). Если 37 | нужный вам язык не поддерживается, дайте нам об этом знать, мы добавим 38 | его. 39 | 40 | Вклады всегда приветствуются! Прочтите [CONTRIBUTING](../CONTRIBUTING.md), 41 | чтобы узнать больше. 42 | 43 | ### Больше информации: \[[Wiki](https://github.com/o2sh/onefetch/wiki)\] \[[Установка](https://github.com/o2sh/onefetch/wiki/Installation)\] \[[Основы](https://github.com/o2sh/onefetch/wiki/getting-started)\] 44 | -------------------------------------------------------------------------------- /docs/README.tr.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
Rust ile yazılmış komut satırı Git bilgi aracı.
4 | 5 |

6 | cargo 7 | Build Status 8 | help wanted 9 | 10 | 11 |

12 | 13 | 14 | 15 | Onefetch, Rust ile yazılmış ,yerel bir Git deposu için proje bilgilerini ve kod istatistiklerini doğrudan terminalinize görüntüleyen bir komut satırı Git bilgi aracıdır. Araç tamamen çevrimdışıdır yani ağ erişimi gerekmez. 16 | 17 | Varsayılan olarak, deponun bilgileri baskın dilin logosuyla birlikte görüntülenir, ancak onefetch'i bunun yerine bir resim - sadece desteklenen terminallerde - , bir metin girişi veya hiçbir şey kullanmayacak şekilde yapılandırabilirsiniz. 18 | 19 | Açık kaynak lisanslarını metinlerden otomatik olarak algılar ve kullanıcıya kod dağıtımı, bekleyen değişiklikler, bağımlılık sayısı (paket yöneticisine göre), en çok katkıda bulunanlar ("git commit" sayısına göre), diskteki boyut, oluşturma tarihi, yazın kod satırları sayısı, vb. gibi değerli bilgiler sağlar. 20 | 21 | 22 | 23 | Onefetch, tam olarak istediğinizi, istediğiniz şekilde görüntülemek için komut satırı bayrakları aracılığıyla yapılandırılabilir: ASCII / Metin biçimlendirmesini özelleştirebilir, bilgi satırlarını devre dışı bırakabilir, dosyaları ve dizinleri yok sayabilir, birden çok biçimde (Json, Yaml) çıktısı ve benzerini alabilirsiniz. 24 | 25 | Onefetch şu anda, [100'den fazla farklı programlama dilini desteklemektedir](https://onefetch.dev) ; seçtiğiniz dil desteklenmiyorsa: Bir "issue" açın ve o dil desteği eklenecektir. 26 | 27 | Katkıda bulunabilirsiniz! Daha fazlası için [CONTRIBUTING](../CONTRIBUTING.md)'a bir göz atın. 28 | 29 | ### Daha Fazla: \[[Viki](https://github.com/o2sh/onefetch/wiki)\] \[[Kurulum](https://github.com/o2sh/onefetch/wiki/Installation)\] \[[Başlarken](https://github.com/o2sh/onefetch/wiki/getting-started)\] 30 | -------------------------------------------------------------------------------- /docs/onefetch.1: -------------------------------------------------------------------------------- 1 | .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. 2 | .TH ONEFETCH "1" "April 2025" "onefetch 2.24.0" "User Commands" 3 | .SH NAME 4 | onefetch \- Command-line Git information tool 5 | .SH SYNOPSIS 6 | .B onefetch 7 | [\fI\,OPTIONS\/\fR] [\fI\,INPUT\/\fR] 8 | .SH DESCRIPTION 9 | Command\-line Git information tool 10 | .SS "Arguments:" 11 | .IP 12 | [INPUT] 13 | .IP 14 | Run as if onefetch was started in instead of the current working directory 15 | .SH OPTIONS 16 | .HP 17 | \fB\-h\fR, \fB\-\-help\fR 18 | .IP 19 | Print help (see a summary with '\-h') 20 | .HP 21 | \fB\-V\fR, \fB\-\-version\fR 22 | .IP 23 | Print version 24 | .SS "INFO:" 25 | .HP 26 | \fB\-d\fR, \fB\-\-disabled\-fields\fR ... 27 | .IP 28 | Allows you to disable FIELD(s) from appearing in the output 29 | .HP 30 | \fB\-\-no\-title\fR 31 | .IP 32 | Hides the title 33 | .HP 34 | \fB\-\-number\-of\-authors\fR 35 | .IP 36 | Maximum NUM of authors to be shown 37 | .IP 38 | [default: 3] 39 | .HP 40 | \fB\-\-number\-of\-languages\fR 41 | .IP 42 | Maximum NUM of languages to be shown 43 | .IP 44 | [default: 6] 45 | .HP 46 | \fB\-\-number\-of\-file\-churns\fR 47 | .IP 48 | Maximum NUM of file churns to be shown 49 | .IP 50 | [default: 3] 51 | .HP 52 | \fB\-\-churn\-pool\-size\fR 53 | .IP 54 | Minimum NUM of commits from HEAD used to compute the churn summary 55 | .IP 56 | By default, the actual value is non\-deterministic due to time\-based computation and will be displayed under the info title "Churn (NUM)" 57 | .HP 58 | \fB\-e\fR, \fB\-\-exclude\fR ... 59 | .IP 60 | Ignore all files & directories matching EXCLUDE 61 | .HP 62 | \fB\-\-no\-bots[=\fR] 63 | .IP 64 | Exclude [bot] commits. Use to override the default pattern 65 | .HP 66 | \fB\-\-no\-merges\fR 67 | .IP 68 | Ignores merge commits 69 | .HP 70 | \fB\-E\fR, \fB\-\-email\fR 71 | .IP 72 | Show the email address of each author 73 | .HP 74 | \fB\-\-http\-url\fR 75 | .IP 76 | Display repository URL as HTTP 77 | .HP 78 | \fB\-\-hide\-token\fR 79 | .IP 80 | Hide token in repository URL 81 | .HP 82 | \fB\-\-include\-hidden\fR 83 | .IP 84 | Count hidden files and directories 85 | .HP 86 | \fB\-T\fR, \fB\-\-type\fR ... 87 | .IP 88 | Filters output by language type 89 | .IP 90 | [default: programming markup] 91 | [possible values: programming, markup, prose, data] 92 | .SS "TEXT FORMATTING:" 93 | .HP 94 | \fB\-t\fR, \fB\-\-text\-colors\fR ... 95 | .IP 96 | Changes the text colors (X X X...) 97 | .IP 98 | Goes in order of title, ~, underline, subtitle, colon, and info 99 | .IP 100 | For example: 101 | .IP 102 | \&'\-\-text\-colors 9 10 11 12 13 14' 103 | .HP 104 | \fB\-z\fR, \fB\-\-iso\-time\fR 105 | .IP 106 | Use ISO 8601 formatted timestamps 107 | .HP 108 | \fB\-\-number\-separator\fR 109 | .IP 110 | Which thousands SEPARATOR to use 111 | .IP 112 | [default: plain] 113 | [possible values: plain, comma, space, underscore] 114 | .HP 115 | \fB\-\-no\-bold\fR 116 | .IP 117 | Turns off bold formatting 118 | .SS "ASCII:" 119 | .HP 120 | \fB\-\-ascii\-input\fR 121 | .IP 122 | Takes a non\-empty STRING as input to replace the ASCII logo 123 | .IP 124 | It is possible to pass a generated STRING by command substitution 125 | .IP 126 | For example: 127 | .IP 128 | \&'\-\-ascii\-input "$(fortune | cowsay \fB\-W\fR 25)"' 129 | .HP 130 | \fB\-c\fR, \fB\-\-ascii\-colors\fR ... 131 | .IP 132 | Colors (X X X...) to print the ascii art 133 | .HP 134 | \fB\-a\fR, \fB\-\-ascii\-language\fR 135 | .IP 136 | Which LANGUAGE's ascii art to print 137 | .HP 138 | \fB\-\-true\-color\fR 139 | .IP 140 | Specify when to use true color 141 | .IP 142 | If set to auto: true color will be enabled if supported by the terminal 143 | .IP 144 | [default: auto] 145 | [possible values: auto, never, always] 146 | .SS "IMAGE:" 147 | .HP 148 | \fB\-i\fR, \fB\-\-image\fR 149 | .IP 150 | Path to the IMAGE file 151 | .HP 152 | \fB\-\-image\-protocol\fR 153 | .IP 154 | Which image PROTOCOL to use 155 | .IP 156 | [possible values: kitty, sixel, iterm] 157 | .HP 158 | \fB\-\-color\-resolution\fR 159 | .IP 160 | VALUE of color resolution to use with SIXEL backend 161 | .IP 162 | [default: 16] 163 | [possible values: 16, 32, 64, 128, 256] 164 | .SS "VISUALS:" 165 | .HP 166 | \fB\-\-no\-color\-palette\fR 167 | .IP 168 | Hides the color palette 169 | .HP 170 | \fB\-\-no\-art\fR 171 | .IP 172 | Hides the ascii art or image if provided 173 | .HP 174 | \fB\-\-nerd\-fonts\fR 175 | .IP 176 | Use Nerd Font icons 177 | .IP 178 | Replaces language chips with Nerd Font icons 179 | .SS "DEVELOPER:" 180 | .HP 181 | \fB\-o\fR, \fB\-\-output\fR 182 | .IP 183 | Outputs Onefetch in a specific format 184 | .IP 185 | [possible values: json, yaml] 186 | .HP 187 | \fB\-\-generate\fR 188 | .IP 189 | If provided, outputs the completion file for given SHELL 190 | .IP 191 | [possible values: bash, elvish, fish, powershell, zsh] 192 | .SS "OTHER:" 193 | .HP 194 | \fB\-l\fR, \fB\-\-languages\fR 195 | .IP 196 | Prints out supported languages 197 | .HP 198 | \fB\-p\fR, \fB\-\-package\-managers\fR 199 | .IP 200 | Prints out supported package managers 201 | -------------------------------------------------------------------------------- /docs/vercel/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | # Output 4 | .output 5 | .vercel 6 | /.svelte-kit 7 | /build 8 | 9 | # OS 10 | .DS_Store 11 | Thumbs.db 12 | 13 | # Env 14 | .env 15 | .env.* 16 | !.env.example 17 | !.env.test 18 | 19 | # Vite 20 | vite.config.js.timestamp-* 21 | vite.config.ts.timestamp-* 22 | -------------------------------------------------------------------------------- /docs/vercel/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /docs/vercel/.prettierignore: -------------------------------------------------------------------------------- 1 | # Package Managers 2 | package-lock.json 3 | pnpm-lock.yaml 4 | yarn.lock 5 | -------------------------------------------------------------------------------- /docs/vercel/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": false, 3 | "tabWidth": 2, 4 | "semi": true, 5 | "singleQuote": true, 6 | "trailingComma": "none", 7 | "bracketSameLine": true, 8 | "singleAttributePerLine": false, 9 | "quoteProps": "consistent", 10 | "plugins": ["prettier-plugin-svelte"], 11 | "overrides": [ 12 | { 13 | "files": "*.svelte", 14 | "options": { 15 | "parser": "svelte" 16 | } 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /docs/vercel/README.md: -------------------------------------------------------------------------------- 1 | # Onefetch Web 2 | 3 | ## Development 4 | 5 | ```bash 6 | # setup 7 | ## install dependencies 8 | npm i 9 | 10 | # run server with hot reloading 11 | npm start 12 | ``` 13 | -------------------------------------------------------------------------------- /docs/vercel/eslint.config.js: -------------------------------------------------------------------------------- 1 | import prettier from 'eslint-config-prettier'; 2 | import js from '@eslint/js'; 3 | import svelte from 'eslint-plugin-svelte'; 4 | import globals from 'globals'; 5 | import ts from 'typescript-eslint'; 6 | 7 | export default ts.config( 8 | js.configs.recommended, 9 | ...ts.configs.recommended, 10 | ...svelte.configs['flat/recommended'], 11 | prettier, 12 | ...svelte.configs['flat/prettier'], 13 | { 14 | languageOptions: { 15 | globals: { 16 | ...globals.browser, 17 | ...globals.node 18 | } 19 | } 20 | }, 21 | { 22 | files: ['**/*.svelte'], 23 | 24 | languageOptions: { 25 | parserOptions: { 26 | parser: ts.parser 27 | } 28 | } 29 | }, 30 | { 31 | ignores: ['build/', '.svelte-kit/', 'dist/'] 32 | } 33 | ); 34 | -------------------------------------------------------------------------------- /docs/vercel/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "onefetch-web", 3 | "version": "0.0.1", 4 | "type": "module", 5 | "scripts": { 6 | "start": "vite", 7 | "build": "vite build", 8 | "format": "prettier -w .", 9 | "preview": "vite preview", 10 | "check": "npm run check:svelte && npm run check:prettier && npm run check:lint", 11 | "check:svelte": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 12 | "check:prettier": "prettier --check **/*.{ts,js,svelte,css,html,json}", 13 | "check:lint": "eslint" 14 | }, 15 | "devDependencies": { 16 | "@rollup/plugin-yaml": "^4.1.2", 17 | "@sveltejs/adapter-auto": "^6.0.0", 18 | "@sveltejs/kit": "^2.20.8", 19 | "@sveltejs/vite-plugin-svelte": "^5.0.3", 20 | "@types/eslint": "^9.6.0", 21 | "eslint": "^9.25.1", 22 | "eslint-config-prettier": "^10.1.2", 23 | "eslint-plugin-svelte": "^3.5.1", 24 | "globals": "^16.0.0", 25 | "prettier": "^3.5.3", 26 | "prettier-plugin-svelte": "^3.3.3", 27 | "svelte": "^5.28.2", 28 | "svelte-check": "^4.1.6", 29 | "typescript": "^5.8.3", 30 | "typescript-eslint": "^8.31.1", 31 | "vite": "^6.3.4" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /docs/vercel/src/app.css: -------------------------------------------------------------------------------- 1 | /* $color-text: #dedce5; */ 2 | /* Sakura.css v1.5.0 3 | * ================ 4 | * Minimal css theme. 5 | * Project: https://github.com/oxalorg/sakura/ 6 | */ 7 | /* Body */ 8 | html { 9 | font-size: 62.5%; 10 | font-family: 11 | -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', 12 | Arial, 'Noto Sans', sans-serif; 13 | } 14 | 15 | body { 16 | font-size: 1.8rem; 17 | line-height: 1.618; 18 | max-width: 38em; 19 | margin: auto; 20 | color: #c9c9c9; 21 | background-color: #222222; 22 | padding: 30px 13px 13px; 23 | } 24 | 25 | @media (max-width: 684px) { 26 | body { 27 | font-size: 1.53rem; 28 | } 29 | } 30 | @media (max-width: 382px) { 31 | body { 32 | font-size: 1.35rem; 33 | } 34 | } 35 | h1, 36 | h2, 37 | h3, 38 | h4, 39 | h5, 40 | h6 { 41 | line-height: 1.1; 42 | font-family: 43 | -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', 44 | Arial, 'Noto Sans', sans-serif; 45 | font-weight: 700; 46 | margin-top: 3rem; 47 | margin-bottom: 1.5rem; 48 | overflow-wrap: break-word; 49 | word-wrap: break-word; 50 | -ms-word-break: break-all; 51 | word-break: break-word; 52 | } 53 | 54 | h1 { 55 | font-size: 2.35em; 56 | } 57 | 58 | h2 { 59 | font-size: 2em; 60 | } 61 | 62 | h3 { 63 | font-size: 1.75em; 64 | } 65 | 66 | h4 { 67 | font-size: 1.5em; 68 | } 69 | 70 | h5 { 71 | font-size: 1.25em; 72 | } 73 | 74 | h6 { 75 | font-size: 1em; 76 | } 77 | 78 | p { 79 | margin-top: 0px; 80 | margin-bottom: 2.5rem; 81 | } 82 | 83 | small, 84 | sub, 85 | sup { 86 | font-size: 75%; 87 | } 88 | 89 | hr { 90 | border-color: #ffffff; 91 | } 92 | 93 | a { 94 | text-decoration: none; 95 | color: #ffffff; 96 | } 97 | a:visited { 98 | color: #e6e6e6; 99 | } 100 | a:hover { 101 | color: #c9c9c9; 102 | border-bottom: 2px solid #c9c9c9; 103 | } 104 | 105 | ul { 106 | padding-left: 1.4em; 107 | margin-top: 0px; 108 | margin-bottom: 2.5rem; 109 | } 110 | 111 | li { 112 | margin-bottom: 0.4em; 113 | } 114 | 115 | blockquote { 116 | margin-left: 0px; 117 | margin-right: 0px; 118 | padding-left: 1em; 119 | padding-top: 0.8em; 120 | padding-bottom: 0.8em; 121 | padding-right: 0.8em; 122 | border-left: 5px solid #ffffff; 123 | margin-bottom: 2.5rem; 124 | background-color: #4a4a4a; 125 | } 126 | 127 | blockquote p { 128 | margin-bottom: 0; 129 | } 130 | 131 | img, 132 | video { 133 | height: auto; 134 | max-width: 100%; 135 | margin-top: 0px; 136 | margin-bottom: 2.5rem; 137 | } 138 | 139 | /* Pre and Code */ 140 | pre { 141 | background-color: #4a4a4a; 142 | display: block; 143 | padding: 1em; 144 | overflow-x: auto; 145 | margin-top: 0px; 146 | margin-bottom: 2.5rem; 147 | font-size: 0.9em; 148 | } 149 | 150 | code, 151 | kbd, 152 | samp { 153 | font-size: 0.9em; 154 | padding: 0 0.5em; 155 | background-color: #4a4a4a; 156 | white-space: pre-wrap; 157 | } 158 | 159 | pre > code { 160 | padding: 0; 161 | background-color: transparent; 162 | white-space: pre; 163 | font-size: 1em; 164 | } 165 | 166 | /* Tables */ 167 | table { 168 | text-align: justify; 169 | width: 100%; 170 | border-collapse: collapse; 171 | margin-bottom: 2rem; 172 | } 173 | 174 | td, 175 | th { 176 | padding: 0.5em; 177 | border-bottom: 1px solid #4a4a4a; 178 | } 179 | 180 | /* Buttons, forms and input */ 181 | input, 182 | textarea { 183 | border: 1px solid #c9c9c9; 184 | } 185 | input:focus, 186 | textarea:focus { 187 | border: 1px solid #ffffff; 188 | } 189 | 190 | textarea { 191 | width: 100%; 192 | } 193 | 194 | .button, 195 | button, 196 | input[type='submit'], 197 | input[type='reset'], 198 | input[type='button'], 199 | input[type='file']::file-selector-button { 200 | display: inline-block; 201 | padding: 5px 10px; 202 | text-align: center; 203 | text-decoration: none; 204 | white-space: nowrap; 205 | background-color: #ffffff; 206 | color: #222222; 207 | border-radius: 1px; 208 | border: 1px solid #ffffff; 209 | cursor: pointer; 210 | box-sizing: border-box; 211 | } 212 | .button[disabled], 213 | button[disabled], 214 | input[type='submit'][disabled], 215 | input[type='reset'][disabled], 216 | input[type='button'][disabled], 217 | input[type='file']::file-selector-button[disabled] { 218 | cursor: default; 219 | opacity: 0.5; 220 | } 221 | .button:hover, 222 | button:hover, 223 | input[type='submit']:hover, 224 | input[type='reset']:hover, 225 | input[type='button']:hover, 226 | input[type='file']::file-selector-button:hover { 227 | background-color: #c9c9c9; 228 | color: #222222; 229 | outline: 0; 230 | } 231 | .button:focus-visible, 232 | button:focus-visible, 233 | input[type='submit']:focus-visible, 234 | input[type='reset']:focus-visible, 235 | input[type='button']:focus-visible, 236 | input[type='file']::file-selector-button:focus-visible { 237 | outline-style: solid; 238 | outline-width: 2px; 239 | } 240 | 241 | textarea, 242 | select, 243 | input { 244 | color: #c9c9c9; 245 | padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ 246 | margin-bottom: 10px; 247 | background-color: #4a4a4a; 248 | border: 1px solid #4a4a4a; 249 | border-radius: 4px; 250 | box-shadow: none; 251 | box-sizing: border-box; 252 | } 253 | textarea:focus, 254 | select:focus, 255 | input:focus { 256 | border: 1px solid #ffffff; 257 | outline: 0; 258 | } 259 | 260 | input[type='checkbox']:focus { 261 | outline: 1px dotted #ffffff; 262 | } 263 | 264 | label, 265 | legend, 266 | fieldset { 267 | display: block; 268 | margin-bottom: 0.5rem; 269 | font-weight: 600; 270 | } 271 | -------------------------------------------------------------------------------- /docs/vercel/src/app.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*/languages.yaml' { 2 | export interface LanguageColors { 3 | ansi: string[]; 4 | hex?: string[]; 5 | chip: string; 6 | } 7 | 8 | export interface Language { 9 | name: string; 10 | type: string; 11 | ascii: string; 12 | colors: LanguageColors; 13 | icon: string; 14 | } 15 | 16 | export type Languages = Record; 17 | export type Language = Language; 18 | } 19 | -------------------------------------------------------------------------------- /docs/vercel/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/vercel/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | export function mapToDefaultTerminalFgColor( 2 | color: string, 3 | dark: boolean 4 | ): string { 5 | return color === 'white' && !dark ? 'black' : color; 6 | } 7 | -------------------------------------------------------------------------------- /docs/vercel/src/routes/+page.svelte: -------------------------------------------------------------------------------- 1 | 54 | 55 |
56 | {#if tagName && htmlUrl} 57 | 61 | {/if} 62 |

Onefetch

63 |

64 | 65 | github | 66 | wiki 67 | | built with ❤ by 68 | @spenserblack and 69 | @o2sh 70 |

71 |
72 |
73 |

74 | This page displays an ASCII preview for all the programming languages 75 | supported by onefetch. Like the binary, the data is sourced from the Languages.yaml file, and the layout aims to replicate how 78 | the logo would appear inside a terminal. 79 |

80 |

81 | Suggestions and PRs are welcome at github.com/o2sh/onefetch 83 |

84 |
85 |

Languages ({$filteredLanguages.length})

86 | 87 |
88 | 89 |
90 |
91 | {#each languageTypes as type (type)} 92 | 100 | {/each} 101 |
102 | Note: By default, onefetch will only recognize programming 105 | and markup types. Use the 106 | --type flag to configure. 107 |
108 | 109 | {#each $filteredLanguages as language (language.name)} 110 | 117 | {/each} 118 |
119 | 120 | 158 | -------------------------------------------------------------------------------- /docs/vercel/src/routes/+page.ts: -------------------------------------------------------------------------------- 1 | // since there's no dynamic data here, we can prerender 2 | // it so that it gets served as a static asset in production 3 | export const prerender = true; 4 | -------------------------------------------------------------------------------- /docs/vercel/src/routes/AsciiPreview.svelte: -------------------------------------------------------------------------------- 1 | 32 | 33 |
34 |
35 |

{chipIcon}

36 | 37 |
38 |
39 | 40 | 41 |
42 |
43 | 48 | 49 |
50 |
51 |
52 | 53 |
{@html html}
54 |
55 | 56 | 100 | -------------------------------------------------------------------------------- /docs/vercel/src/routes/TitleLink.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |

{name}

6 | -------------------------------------------------------------------------------- /docs/vercel/static/onefetch.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/o2sh/onefetch/be4f2c8235100730a9c80954e93a5d2296294f8a/docs/vercel/static/onefetch.ico -------------------------------------------------------------------------------- /docs/vercel/static/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /docs/vercel/svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-auto'; 2 | import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; 3 | 4 | /** @type {import('@sveltejs/kit').Config} */ 5 | const config = { 6 | // Consult https://svelte.dev/docs/kit/integrations 7 | // for more information about preprocessors 8 | preprocess: vitePreprocess(), 9 | 10 | kit: { 11 | // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list. 12 | // If your environment is not supported, or you settled on a specific environment, switch out the adapter. 13 | // See https://svelte.dev/docs/kit/adapters for more information about adapters. 14 | adapter: adapter() 15 | } 16 | }; 17 | 18 | export default config; 19 | -------------------------------------------------------------------------------- /docs/vercel/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true, 12 | "moduleResolution": "bundler" 13 | } 14 | // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias 15 | // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files 16 | // 17 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 18 | // from the referenced tsconfig.json - TypeScript does not merge them in 19 | } 20 | -------------------------------------------------------------------------------- /docs/vercel/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "github": { 3 | "silent": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /docs/vercel/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { sveltekit } from '@sveltejs/kit/vite'; 2 | import { defineConfig } from 'vite'; 3 | import yaml from '@rollup/plugin-yaml'; 4 | 5 | export default defineConfig({ 6 | plugins: [sveltekit(), yaml()], 7 | server: { 8 | fs: { 9 | // Allow serving files from one level up to the project root 10 | allow: ['..'] 11 | } 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /docs/wiki/_Footer.md: -------------------------------------------------------------------------------- 1 | - 📰 [Wiki Home](https://github.com/o2sh/onefetch/wiki) 2 | - 🛖 [Project Home](https://github.com/o2sh/onefetch) -------------------------------------------------------------------------------- /docs/wiki/_Sidebar.md: -------------------------------------------------------------------------------- 1 | - **[Home](https://github.com/o2sh/onefetch/wiki)** 2 | - **General** 3 | - [Installation](https://github.com/o2sh/onefetch/wiki/installation) 4 | - [Getting started](https://github.com/o2sh/onefetch/wiki/getting-started) 5 | - [Nix local setup](https://github.com/o2sh/onefetch/wiki/nix-local-setup) 6 | - **Options** 7 | - [Command-line options](https://github.com/o2sh/onefetch/wiki/command-line-options) 8 | - **Images** 9 | - [Images in the terminal](https://github.com/o2sh/onefetch/wiki/images-in-the-terminal) 10 | - **Ascii** 11 | - [Ascii art](https://github.com/o2sh/onefetch/wiki/ascii-art) 12 | -------------------------------------------------------------------------------- /docs/wiki/ascii-art.md: -------------------------------------------------------------------------------- 1 | This is the format onefetch uses for its ASCII art files. 2 | 3 | #### Here's an example: 4 | 5 | ``` 6 | {2} .:--::////::--.` 7 | {1} `/yNMMNho{2}////////////:. 8 | {1} `+NMMMMMMMMmy{2}/////////////:` 9 | {0} `-:::{1}ohNMMMMMMMNy{2}/////////////:` 10 | {0} .::::::::{1}odMMMMMMMNy{2}/////////////- 11 | {0} -:::::::::::{1}/hMMMMMMMmo{2}////////////- 12 | {0} .::::::::::::::{1}oMMMMMMMMh{2}////////////- 13 | {0}`:::::::::::::{1}/dMMMMMMMMMMNo{2}///////////` 14 | {0}-::::::::::::{1}sMMMMMMmMMMMMMMy{2}//////////- 15 | {0}-::::::::::{1}/dMMMMMMs{0}:{1}+NMMMMMMd{2}/////////: 16 | {0}-:::::::::{1}+NMMMMMm/{0}:::{1}/dMMMMMMm+{2}///////: 17 | {0}-::::::::{1}sMMMMMMh{0}:::::::{1}dMMMMMMm+{2}//////- 18 | {0}`:::::::{1}sMMMMMMy{0}:::::::::{1}dMMMMMMm+{2}/////` 19 | {0} .:::::{1}sMMMMMMs{0}:::::::::::{1}mMMMMMMd{2}////- 20 | {0} -:::{1}sMMMMMMy{0}::::::::::::{1}/NMMMMMMh{2}//- 21 | {0} .:{1}+MMMMMMd{0}::::::::::::::{1}oMMMMMMMo{2}- 22 | {1} `yMMMMMN/{0}:::::::::::::::{1}hMMMMMh. 23 | {1} -yMMMo{0}::::::::::::::::{1}/MMMy- 24 | {1} `/s{0}::::::::::::::::::{1}o/` 25 | {0} ``.---::::---..` 26 | ``` 27 | 28 | #### Features: 29 | 30 | - You can use `{0}` to `{X}`to color the ascii, with X > 0. 31 | - You can pass the flag `-c, --ascii-colors 2 5 ...` to set your own colors. 32 | - Look at the color palette to know the color order 33 | 34 | ![](https://i.imgur.com/NFT4WL4.png) 35 | -------------------------------------------------------------------------------- /docs/wiki/command-line-options.md: -------------------------------------------------------------------------------- 1 | ```man 2 | Usage: onefetch.exe [OPTIONS] [INPUT] 3 | 4 | Arguments: 5 | [INPUT] 6 | Run as if onefetch was started in instead of the current working directory 7 | 8 | Options: 9 | -h, --help 10 | Print help (see a summary with '-h') 11 | 12 | -V, --version 13 | Print version 14 | 15 | INFO: 16 | -d, --disabled-fields ... 17 | Allows you to disable FIELD(s) from appearing in the output 18 | 19 | --no-title 20 | Hides the title 21 | 22 | --number-of-authors 23 | Maximum NUM of authors to be shown 24 | 25 | [default: 3] 26 | 27 | --number-of-languages 28 | Maximum NUM of languages to be shown 29 | 30 | [default: 6] 31 | 32 | --number-of-file-churns 33 | Maximum NUM of file churns to be shown 34 | 35 | [default: 3] 36 | 37 | --churn-pool-size 38 | Minimum NUM of commits from HEAD used to compute the churn summary 39 | 40 | By default, the actual value is non-deterministic due to time-based computation and will be displayed under the info title "Churn (NUM)" 41 | 42 | -e, --exclude ... 43 | Ignore all files & directories matching EXCLUDE 44 | 45 | --no-bots[=] 46 | Exclude [bot] commits. Use to override the default pattern 47 | 48 | --no-merges 49 | Ignores merge commits 50 | 51 | -E, --email 52 | Show the email address of each author 53 | 54 | --http-url 55 | Display repository URL as HTTP 56 | 57 | --hide-token 58 | Hide token in repository URL 59 | 60 | --include-hidden 61 | Count hidden files and directories 62 | 63 | -T, --type ... 64 | Filters output by language type 65 | 66 | [default: programming markup] 67 | [possible values: programming, markup, prose, data] 68 | 69 | TEXT FORMATTING: 70 | -t, --text-colors ... 71 | Changes the text colors (X X X...) 72 | 73 | Goes in order of title, ~, underline, subtitle, colon, and info 74 | 75 | For example: 76 | 77 | '--text-colors 9 10 11 12 13 14' 78 | 79 | -z, --iso-time 80 | Use ISO 8601 formatted timestamps 81 | 82 | --number-separator 83 | Which thousands SEPARATOR to use 84 | 85 | [default: plain] 86 | [possible values: plain, comma, space, underscore] 87 | 88 | --no-bold 89 | Turns off bold formatting 90 | 91 | ASCII: 92 | --ascii-input 93 | Takes a non-empty STRING as input to replace the ASCII logo 94 | 95 | It is possible to pass a generated STRING by command substitution 96 | 97 | For example: 98 | 99 | '--ascii-input "$(fortune | cowsay -W 25)"' 100 | 101 | -c, --ascii-colors ... 102 | Colors (X X X...) to print the ascii art 103 | 104 | -a, --ascii-language 105 | Which LANGUAGE's ascii art to print 106 | 107 | --true-color 108 | Specify when to use true color 109 | 110 | If set to auto: true color will be enabled if supported by the terminal 111 | 112 | [default: auto] 113 | [possible values: auto, never, always] 114 | 115 | IMAGE: 116 | -i, --image 117 | Path to the IMAGE file 118 | 119 | --image-protocol 120 | Which image PROTOCOL to use 121 | 122 | [possible values: kitty, sixel, iterm] 123 | 124 | --color-resolution 125 | VALUE of color resolution to use with SIXEL backend 126 | 127 | [default: 16] 128 | [possible values: 16, 32, 64, 128, 256] 129 | 130 | VISUALS: 131 | --no-color-palette 132 | Hides the color palette 133 | 134 | --no-art 135 | Hides the ascii art or image if provided 136 | 137 | --nerd-fonts 138 | Use Nerd Font icons 139 | 140 | Replaces language chips with Nerd Font icons 141 | 142 | DEVELOPER: 143 | -o, --output 144 | Outputs Onefetch in a specific format 145 | 146 | [possible values: json, yaml] 147 | 148 | --generate 149 | If provided, outputs the completion file for given SHELL 150 | 151 | [possible values: bash, elvish, fish, powershell, zsh] 152 | 153 | OTHER: 154 | -l, --languages 155 | Prints out supported languages 156 | 157 | -p, --package-managers 158 | Prints out supported package managers 159 | ``` 160 | -------------------------------------------------------------------------------- /docs/wiki/getting-started.md: -------------------------------------------------------------------------------- 1 | Onefetch is installed, then what? 2 | 3 | ### Usage 4 | 5 | ```sh 6 | > onefetch /path/of/your/repo 7 | ``` 8 | 9 | Or 10 | 11 | ```sh 12 | > cd /path/of/your/repo 13 | > onefetch 14 | ``` 15 | 16 | ### Misc 17 | 18 | By [**@spenserblack**](https://github.com/spenserblack) 19 | 20 | ```sh 21 | # Runs `onefetch -a Assembly`, `onefetch -a C`, etc. 22 | onefetch -l | tr "[:upper:] " "[:lower:]-" | while read line; do echo "$line"; onefetch -a $line; done; 23 | ``` 24 | 25 | ### Automatic repo detection and running 26 | 27 | If you want to automate the detection and running of `onefetch` every time you `cd` into a repository you can leverage one of the methods below: 28 | 29 | #### 1. Bash / Zsh 30 | 31 | By [**@quazar-omega**](https://github.com/quazar-omega) 32 | 33 | A script to put in your `.bashrc` - or `.zshrc` - to run onefetch whenever you open a shell into a repository or `cd` into a repository, making sure that it's different from the last one you were in: 34 | 35 | ```sh 36 | # git repository greeter 37 | last_repository= 38 | check_directory_for_new_repository() { 39 | current_repository=$(git rev-parse --show-toplevel 2> /dev/null) 40 | 41 | if [ "$current_repository" ] && \ 42 | [ "$current_repository" != "$last_repository" ]; then 43 | onefetch 44 | fi 45 | last_repository=$current_repository 46 | } 47 | cd() { 48 | builtin cd "$@" 49 | check_directory_for_new_repository 50 | } 51 | 52 | # optional, greet also when opening shell directly in repository directory 53 | # adds time to startup 54 | check_directory_for_new_repository 55 | ``` 56 | 57 | #### 2. Fish 58 | 59 | By [**@TheSast**](https://github.com/TheSast) 60 | 61 | A fish adaptation of the previous script, run it once in your shell to save it: 62 | 63 | ```fish 64 | function cd -w='cd' 65 | builtin cd $argv || return 66 | check_directory_for_new_repository 67 | end 68 | 69 | function check_directory_for_new_repository 70 | set current_repository (git rev-parse --show-toplevel 2> /dev/null) 71 | if [ "$current_repository" ] && \ 72 | [ "$current_repository" != "$last_repository" ] 73 | onefetch 74 | end 75 | set -gx last_repository $current_repository 76 | end 77 | 78 | funcsave cd 79 | funcsave check_directory_for_new_repository 80 | ``` 81 | 82 | #### 3. CMD 83 | 84 | By [**@mataha**](https://github.com/mataha) 85 | 86 | An adaptation of the above snippet suited for Windows's `cmd.exe`, 87 | specifically for inclusion in AutoRun scripts or DOSKEY macrofiles: 88 | 89 | ```bat 90 | @set LAST_REPOSITORY= 91 | 92 | @doskey cd = ( ^ 93 | for %%^^^^ in ("") do @for /f "delims=" %%i in (^^""$*%%~^^"^") do @( ^ 94 | if "%%~i"=="" ( ^ 95 | if defined USERPROFILE ( ^ 96 | if /i not "%%CD%%"=="%%USERPROFILE%%" ( ^ 97 | chdir /d "%%USERPROFILE%%" ^&^& set "OLDPWD=%%CD%%" ^ 98 | ) ^ 99 | ) else (call) ^ 100 | ) else if "%%~i"=="-" ( ^ 101 | if defined OLDPWD ( ^ 102 | if /i not "%%CD%%"=="%%OLDPWD%%" ( ^ 103 | chdir /d "%%OLDPWD%%" ^&^& set "OLDPWD=%%CD%%" ^ 104 | ) ^ 105 | ) else (call) ^ 106 | ) else ( ^ 107 | if defined CD ( ^ 108 | if /i not "%%CD%%"=="%%~fi" ( ^ 109 | chdir /d %%~fi ^&^& set "OLDPWD=%%CD%%" ^ 110 | ) ^ 111 | ) else (call) ^ 112 | ) ^ 113 | ) ^ 114 | ) ^&^& for /f "delims=" %%r in ('git rev-parse --show-toplevel 2^^^>nul') do @( ^ 115 | if not "%%~r"=="%%LAST_REPOSITORY%%" ( ^ 116 | onefetch ^ 117 | ) ^& set "LAST_REPOSITORY=%%~r" ^ 118 | ) 119 | ``` 120 | 121 | #### 4. Powershell 122 | 123 | By [**@kiapanahi**](https://github.com/kiapanahi) 124 | 125 | An adaptation of the above snippet suited for `Powershell`. Put this script in the `$PROFILE`. 126 | 127 | ```pwsh 128 | # git repository greeter 129 | 130 | # Set the console output encoding to UTF-8, so that special characters are displayed correctly when piping to Write-Host 131 | [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 132 | $global:lastRepository = $null 133 | 134 | function Check-DirectoryForNewRepository { 135 | $currentRepository = git rev-parse --show-toplevel 2>$null 136 | if ($currentRepository -and ($currentRepository -ne $global:lastRepository)) { 137 | onefetch | Write-Host 138 | } 139 | $global:lastRepository = $currentRepository 140 | } 141 | 142 | function Set-Location { 143 | Microsoft.PowerShell.Management\Set-Location @args 144 | Check-DirectoryForNewRepository 145 | } 146 | 147 | # Optional: Check the repository also when opening a shell directly in a repository directory 148 | # Uncomment the following line if desired 149 | #Check-DirectoryForNewRepository 150 | ``` 151 | 152 | ### Git alias 153 | 154 | By [**@mbrehin**](https://github.com/mbrehin) 155 | 156 | You can also add git alias to run onefetch during your git workflows 157 | 158 | ```sh 159 | # Add Git alias for onefetch. 160 | git config --global alias.project-summary '!which onefetch && onefetch' 161 | ``` 162 | -------------------------------------------------------------------------------- /docs/wiki/home.md: -------------------------------------------------------------------------------- 1 | Welcome to the onefetch's wiki! 2 | 3 | - **[Home](https://github.com/o2sh/onefetch/wiki)** 4 | - **General** 5 | - [Installation](https://github.com/o2sh/onefetch/wiki/installation) 6 | - [Getting started](https://github.com/o2sh/onefetch/wiki/getting-started) 7 | - [Nix local setup](https://github.com/o2sh/onefetch/wiki/nix-local-setup) 8 | - **Options** 9 | - [Command-line options](https://github.com/o2sh/onefetch/wiki/command-line-options) 10 | - **Images** 11 | - [Images in the terminal](https://github.com/o2sh/onefetch/wiki/images-in-the-terminal) 12 | - **Ascii** 13 | - [Ascii art](https://github.com/o2sh/onefetch/wiki/ascii-art) 14 | -------------------------------------------------------------------------------- /docs/wiki/images-in-the-terminal.md: -------------------------------------------------------------------------------- 1 | Onefetch supports displaying images using [`kitty`](https://sw.kovidgoyal.net/kitty/graphics-protocol.html), [`Sixel`](https://en.wikipedia.org/wiki/Sixel) and [`iTerm`](https://www.iterm2.com/documentation-images.html) protocols. 2 | 3 |

4 | 5 |

6 | 7 | When running `onefetch --image ./My-picture.jpg`, the program looks for the first `Image Protocol` supported by the terminal and use it to display the requested image instead of the Ascii logo. 8 | 9 | If you decide to go manual, and want to force the use of a specific image protocol: `onefetch --image ./My-picture.jpg --image-protocol sixel|kitty|iterm` 10 | 11 | ### Sixel 12 | 13 | The Sixel protocol is handled by multiple terminal emulators such as [`xterm`](https://invisible-island.net/xterm/) (enabled via flag `-ti 340`), [`mlterm`](https://wiki.ubuntu.com/Mlterm) and [`WezTerm`](https://github.com/wez/wezterm) which are actively maintained. 14 | 15 | You can increase the color resolution using the `--color-resolution` flag. 16 | 17 | ### Kitty 18 | 19 | The kitty terminal graphics protocol used on the terminal of the same name allows the program running in the terminal, to render graphics to the screen of the terminal emulator. 20 | 21 | ### ITerm 22 | 23 | The iTerm inline image protocol supported by iTerm2 (also WezTerm) allows to display images within the terminal. 24 | -------------------------------------------------------------------------------- /docs/wiki/installation.md: -------------------------------------------------------------------------------- 1 | This wiki page will guide you through getting onefetch working on your system. 2 | 3 | [![Packaging status](https://repology.org/badge/vertical-allrepos/onefetch.svg)](https://repology.org/project/onefetch/versions) 4 | 5 | # Table of Contents 6 | 7 | - [Universal Install](#universal-install) 8 | - [Build from source](#build-from-source) 9 | - [Cargo](#cargo) 10 | - [Snap](#snap) 11 | - [OS/Distro Packages](#osdistro-packages) 12 | - [Alpine Linux](#alpine-linux) 13 | - [Arch](#arch) 14 | - [Fedora](#fedora) 15 | - [FreeBSD](#freebsd) 16 | - [Funtoo](#funtoo) 17 | - [macOS](#macos) 18 | - [Homebrew](#homebrew) 19 | - [MacPorts](#macports) 20 | - [NetBSD](#netbsd) 21 | - [NixOS](#nixos) 22 | - [openSUSE](#openSUSE-Leap-or-Tumbleweed) 23 | - [Ubuntu](#ubuntu-ppa) 24 | - [Void Linux](#void-linux) 25 | - [Windows](#windows) 26 | - [Winget](#Winget) 27 | - [Scoop](#scoop) 28 | - [Chocolatey](#chocolatey) 29 | 30 | # Universal Install 31 | 32 | If your architecture is supported by the pre-built binaries, you can download them from the [releases page](https://github.com/o2sh/onefetch/releases/latest). 33 | 34 | ## Build from source 35 | 36 | First, install rust toolchain with [rustup](https://rustup.rs/): 37 | 38 | ```shell 39 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 40 | ``` 41 | 42 | > [!IMPORTANT] 43 | > Ensure [CMake](https://cmake.org/download/) is installed. 44 | 45 | ``` 46 | git clone https://github.com/o2sh/onefetch 47 | cd onefetch 48 | make install 49 | ``` 50 | 51 | ## Cargo 52 | 53 | First, install rust toolchain with [rustup](https://rustup.rs/): 54 | 55 | ```shell 56 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 57 | ``` 58 | 59 | > [!IMPORTANT] 60 | > Ensure [CMake](https://cmake.org/download/) is installed. 61 | 62 | ``` 63 | cargo install onefetch 64 | ``` 65 | 66 | This method will build the binary from source. 67 | 68 | To update, run 69 | 70 | ``` 71 | cargo install onefetch --force 72 | ``` 73 | 74 | ## Snap 75 | 76 | For a system with Snap installed, run 77 | 78 | ``` 79 | snap install onefetch 80 | ``` 81 | 82 | The stable version will be installed for you automatically. 83 | 84 | # OS/Distro Packages 85 | 86 | ## Alpine Linux 87 | 88 | 1. Update repositories 89 | - `apk update` 90 | 2. Install the package 91 | - `apk add onefetch` 92 | 93 | ## Arch 94 | 95 | Onefetch is available in the official repos. 96 | 97 | - Install the package 98 | - `pacman -S onefetch` 99 | 100 | ## Fedora 101 | 102 | Install it from the COPR 103 | 104 | ``` 105 | sudo dnf copr enable varlad/onefetch 106 | sudo dnf install onefetch 107 | ``` 108 | 109 | ## FreeBSD 110 | 111 | Install it from the official repositories 112 | 113 | - `pkg install onefetch` 114 | 115 | ## Funtoo 116 | 117 | Funtoo has an autogenerated onefetch package in the official kits: 118 | 119 | - `emerge app-misc/onefetch` 120 | 121 | ## MacOS 122 | 123 | ### HomeBrew 124 | 125 | Install `onefetch` with Homebrew 126 | 127 | ``` 128 | brew install onefetch 129 | ``` 130 | 131 | To update, run 132 | 133 | ``` 134 | brew upgrade onefetch 135 | ``` 136 | 137 | ### MacPorts 138 | 139 | Install `onefetch` with MacPorts 140 | 141 | ``` 142 | sudo port selfupdate 143 | sudo port install onefetch 144 | ``` 145 | 146 | To update run, 147 | 148 | ``` 149 | sudo port upgrade onefetch 150 | ``` 151 | 152 | ## NetBSD 153 | 154 | Install it from the official repositories. 155 | 156 | - `pkg_add onefetch` 157 | 158 | ## NixOS 159 | 160 | Install it from the official repositories 161 | 162 | - `nix-env -i onefetch` 163 | 164 | ## openSUSE Leap or Tumbleweed 165 | 166 | Install it from the official repositories. 167 | 168 | - `zypper install onefetch` 169 | 170 | ## Ubuntu (ppa) 171 | 172 | ``` 173 | sudo add-apt-repository ppa:o2sh/onefetch 174 | sudo apt-get update 175 | sudo apt-get install onefetch 176 | ``` 177 | 178 | If your Ubuntu version isn't supported, use [snap](#snap). 179 | 180 | ## Void Linux 181 | 182 | Install it from the official repositories 183 | 184 | - `sudo xbps-install -S onefetch` 185 | 186 | ## Windows 187 | 188 | ### Winget 189 | 190 | You can install onefetch using [winget](https://docs.microsoft.com/en-us/windows/package-manager/winget/) 191 | 192 | ``` 193 | winget install onefetch 194 | ``` 195 | 196 | ### Scoop 197 | 198 | For [Scoop](https://scoop.sh/) users, onefetch is available from the "Extras" bucket 199 | 200 | ``` 201 | scoop bucket add extras 202 | scoop install onefetch 203 | ``` 204 | 205 | ### Chocolatey 206 | 207 | If you prefer to use [Chocolatey](https://chocolatey.org/) to manage software, it can be installed like so 208 | 209 | ``` 210 | choco install onefetch 211 | ``` 212 | -------------------------------------------------------------------------------- /docs/wiki/nix-local-setup.md: -------------------------------------------------------------------------------- 1 | [Nix](https://nixos.org/) is a package manager that uses a purely functional approach to dependency management. Packages in Nix are built and run in isolated, reproducible environments. This tutorial walks you through setting up a development environment for Onefetch using Nix. 2 | 3 | > This guide assumes you already have Nix [installed](https://nixos.org/download.html#nix-quick-install) on your system. 4 | 5 | ## Setup 6 | 7 | To begin, create a `flake.nix` file with the following content: 8 | 9 | ```nix 10 | { 11 | description = "onefetch"; 12 | 13 | inputs = { 14 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 15 | }; 16 | 17 | outputs = { 18 | self, 19 | nixpkgs, 20 | ... 21 | }: let 22 | forAllSystems = fn: nixpkgs.lib.genAttrs [ 23 | "aarch64-darwin" 24 | "aarch64-linux" 25 | "i686-linux" 26 | "x86_64-linux" 27 | "x86_64-darwin" 28 | ] (system: fn nixpkgs.legacyPackages.${system}); 29 | in { 30 | devShells = forAllSystems (pkgs: { 31 | default = pkgs.mkShell { 32 | name = "onefetch"; 33 | packages = with pkgs; [ 34 | cargo 35 | rustc 36 | clippy 37 | rustfmt 38 | rust-analyzer 39 | cmake 40 | ]; 41 | RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}"; 42 | }; 43 | }); 44 | }; 45 | } 46 | ``` 47 | 48 | then enter the development shell: 49 | 50 | ```bash 51 | nix develop 52 | ``` 53 | -------------------------------------------------------------------------------- /image/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors.workspace = true 3 | edition.workspace = true 4 | version.workspace = true 5 | license.workspace = true 6 | repository.workspace = true 7 | name = "onefetch-image" 8 | description = "Display images in the terminal" 9 | 10 | [dependencies] 11 | anyhow.workspace = true 12 | clap.workspace = true 13 | image.workspace = true 14 | 15 | [target.'cfg(not(windows))'.dependencies] 16 | color_quant = "1.1.0" 17 | base64 = "0.22.1" 18 | libc = "0.2.169" 19 | -------------------------------------------------------------------------------- /image/LICENSE.md: -------------------------------------------------------------------------------- 1 | ../LICENSE.md -------------------------------------------------------------------------------- /image/README.md: -------------------------------------------------------------------------------- 1 | # image 2 | 3 | [![crates.io](https://img.shields.io/crates/v/onefetch-image)](https://crates.io/crates/onefetch-image) 4 | [![docs.rs](https://img.shields.io/docsrs/onefetch-image)](https://docs.rs/onefetch-image) 5 | 6 | Provides the primary interface to display images to the terminal. 7 | 8 | Protocols supported: 9 | 10 | - Sixel 11 | - Kitty 12 | - Iterm 13 | 14 | _This crate is designed as part of the [onefetch](https://github.com/o2sh/onefetch) project._ 15 | -------------------------------------------------------------------------------- /image/src/iterm.rs: -------------------------------------------------------------------------------- 1 | use crate::get_dimensions; 2 | use anyhow::Result; 3 | use base64::{engine, Engine}; 4 | use image::{imageops::FilterType, DynamicImage}; 5 | use std::env; 6 | use std::io::Cursor; 7 | 8 | pub struct ITermBackend {} 9 | 10 | impl ITermBackend { 11 | pub fn new() -> Self { 12 | ITermBackend {} 13 | } 14 | 15 | pub fn supported() -> bool { 16 | let term_program = env::var("TERM_PROGRAM").unwrap_or_else(|_| "".to_string()); 17 | term_program == "iTerm.app" 18 | } 19 | } 20 | 21 | impl Default for ITermBackend { 22 | fn default() -> Self { 23 | Self::new() 24 | } 25 | } 26 | 27 | impl super::ImageBackend for ITermBackend { 28 | fn add_image( 29 | &self, 30 | lines: Vec, 31 | image: &DynamicImage, 32 | _colors: usize, 33 | ) -> Result { 34 | let tty_size = unsafe { get_dimensions() }; 35 | let width_ratio = f64::from(tty_size.ws_col) / f64::from(tty_size.ws_xpixel); 36 | let height_ratio = f64::from(tty_size.ws_row) / f64::from(tty_size.ws_ypixel); 37 | 38 | // resize image to fit the text height with the Lanczos3 algorithm 39 | let image = image.resize( 40 | u32::MAX, 41 | (lines.len() as f64 / height_ratio) as u32, 42 | FilterType::Lanczos3, 43 | ); 44 | let _image_columns = width_ratio * f64::from(image.width()); 45 | let image_rows = height_ratio * f64::from(image.height()); 46 | 47 | let mut bytes: Vec = Vec::new(); 48 | image.write_to(&mut Cursor::new(&mut bytes), image::ImageFormat::Png)?; 49 | let encoded_image = engine::general_purpose::STANDARD.encode(bytes); 50 | let mut image_data = Vec::::new(); 51 | 52 | image_data.extend(b"\x1B]1337;File=inline=1:"); 53 | image_data.extend(encoded_image.bytes()); 54 | image_data.extend(b"\x07"); 55 | 56 | image_data.extend(format!("\x1B[{}A", image_rows as u32 - 1).as_bytes()); // move cursor to start of image 57 | let mut i = 0; 58 | for line in &lines { 59 | image_data.extend(format!("\x1B[s{}\x1B[u\x1B[1B", line).as_bytes()); 60 | i += 1; 61 | } 62 | image_data 63 | .extend(format!("\n\x1B[{}B", lines.len().max(image_rows as usize) - i).as_bytes()); // move cursor to end of image 64 | 65 | Ok(String::from_utf8(image_data)?) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /image/src/kitty.rs: -------------------------------------------------------------------------------- 1 | use crate::get_dimensions; 2 | use anyhow::Result; 3 | use base64::{engine, Engine}; 4 | use image::{imageops::FilterType, DynamicImage}; 5 | use libc::{ 6 | c_void, poll, pollfd, read, tcgetattr, tcsetattr, termios, ECHO, ICANON, POLLIN, STDIN_FILENO, 7 | TCSANOW, 8 | }; 9 | use std::io::{stdout, Write}; 10 | use std::time::Instant; 11 | 12 | pub struct KittyBackend {} 13 | 14 | impl KittyBackend { 15 | pub fn new() -> Self { 16 | Self {} 17 | } 18 | 19 | pub fn supported() -> bool { 20 | // save terminal attributes and disable canonical input processing mode 21 | let old_attributes = unsafe { 22 | let mut old_attributes: termios = std::mem::zeroed(); 23 | tcgetattr(STDIN_FILENO, &mut old_attributes); 24 | 25 | let mut new_attributes = old_attributes; 26 | new_attributes.c_lflag &= !ICANON; 27 | new_attributes.c_lflag &= !ECHO; 28 | tcsetattr(STDIN_FILENO, TCSANOW, &new_attributes); 29 | old_attributes 30 | }; 31 | 32 | // generate red rgba test image 33 | let mut test_image = Vec::::with_capacity(32 * 32 * 4); 34 | test_image.extend(std::iter::repeat_n([255, 0, 0, 255].iter(), 32 * 32).flatten()); 35 | 36 | // print the test image with the action set to query 37 | print!( 38 | "\x1B_Gi=1,f=32,s=32,v=32,a=q;{}\x1B\\", 39 | engine::general_purpose::STANDARD.encode(&test_image) 40 | ); 41 | stdout().flush().unwrap(); 42 | 43 | let start_time = Instant::now(); 44 | let mut stdin_pollfd = pollfd { 45 | fd: STDIN_FILENO, 46 | events: POLLIN, 47 | revents: 0, 48 | }; 49 | let allowed_bytes = [0x1B, b'_', b'G', b'\\']; 50 | let mut buf = Vec::::new(); 51 | loop { 52 | // check for timeout while polling to avoid blocking the main thread 53 | while unsafe { poll(&mut stdin_pollfd, 1, 0) < 1 } { 54 | if start_time.elapsed().as_millis() > 50 { 55 | unsafe { 56 | tcsetattr(STDIN_FILENO, TCSANOW, &old_attributes); 57 | } 58 | return false; 59 | } 60 | } 61 | let mut byte = 0; 62 | unsafe { 63 | read(STDIN_FILENO, &mut byte as *mut _ as *mut c_void, 1); 64 | } 65 | if allowed_bytes.contains(&byte) { 66 | buf.push(byte); 67 | } 68 | if buf.starts_with(&[0x1B, b'_', b'G']) && buf.ends_with(&[0x1B, b'\\']) { 69 | unsafe { 70 | tcsetattr(STDIN_FILENO, TCSANOW, &old_attributes); 71 | } 72 | return true; 73 | } 74 | } 75 | } 76 | } 77 | 78 | impl Default for KittyBackend { 79 | fn default() -> Self { 80 | Self::new() 81 | } 82 | } 83 | 84 | impl super::ImageBackend for KittyBackend { 85 | fn add_image( 86 | &self, 87 | lines: Vec, 88 | image: &DynamicImage, 89 | _colors: usize, 90 | ) -> Result { 91 | let tty_size = unsafe { get_dimensions() }; 92 | let width_ratio = f64::from(tty_size.ws_col) / f64::from(tty_size.ws_xpixel); 93 | let height_ratio = f64::from(tty_size.ws_row) / f64::from(tty_size.ws_ypixel); 94 | 95 | // resize image to fit the text height with the Lanczos3 algorithm 96 | let image = image.resize( 97 | u32::MAX, 98 | (lines.len() as f64 / height_ratio) as u32, 99 | FilterType::Lanczos3, 100 | ); 101 | let _image_columns = width_ratio * f64::from(image.width()); 102 | let image_rows = height_ratio * f64::from(image.height()); 103 | 104 | // convert the image to rgba samples 105 | let rgba_image = image.to_rgba8(); 106 | let flat_samples = rgba_image.as_flat_samples(); 107 | let raw_image = flat_samples 108 | .image_slice() 109 | .expect("Conversion from image to rgba samples failed"); 110 | assert_eq!( 111 | image.width() as usize * image.height() as usize * 4, 112 | raw_image.len() 113 | ); 114 | 115 | let encoded_image = engine::general_purpose::STANDARD.encode(raw_image); // image data is base64 encoded 116 | let mut image_data = Vec::::new(); 117 | for chunk in encoded_image.as_bytes().chunks(4096) { 118 | // send a 4096 byte chunk of base64 encoded rgba image data 119 | image_data.extend( 120 | format!( 121 | "\x1B_Gf=32,s={},v={},m=1,a=T;", 122 | image.width(), 123 | image.height() 124 | ) 125 | .as_bytes(), 126 | ); 127 | image_data.extend(chunk); 128 | image_data.extend(b"\x1B\\"); 129 | } 130 | image_data.extend(b"\x1B_Gm=0;\x1B\\"); // write empty last chunk 131 | image_data.extend(format!("\x1B[{}A", image_rows as u32 - 1).as_bytes()); // move cursor to start of image 132 | let mut i = 0; 133 | for line in &lines { 134 | image_data.extend(format!("\x1B[s{}\x1B[u\x1B[1B", line).as_bytes()); 135 | i += 1; 136 | } 137 | image_data 138 | .extend(format!("\n\x1B[{}B", lines.len().max(image_rows as usize) - i).as_bytes()); // move cursor to end of image 139 | 140 | Ok(String::from_utf8(image_data)?) 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /image/src/lib.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use image::DynamicImage; 3 | 4 | #[derive(clap::ValueEnum, Clone, PartialEq, Eq, Debug)] 5 | pub enum ImageProtocol { 6 | Kitty, 7 | Sixel, 8 | Iterm, 9 | } 10 | 11 | #[cfg(not(windows))] 12 | pub mod iterm; 13 | #[cfg(not(windows))] 14 | pub mod kitty; 15 | #[cfg(not(windows))] 16 | pub mod sixel; 17 | 18 | pub trait ImageBackend { 19 | fn add_image(&self, lines: Vec, image: &DynamicImage, colors: usize) -> Result; 20 | } 21 | 22 | pub fn get_best_backend() -> Option> { 23 | #[cfg(not(windows))] 24 | if kitty::KittyBackend::supported() { 25 | Some(Box::new(kitty::KittyBackend::new())) 26 | } else if iterm::ITermBackend::supported() { 27 | Some(Box::new(iterm::ITermBackend::new())) 28 | } else if sixel::SixelBackend::supported() { 29 | Some(Box::new(sixel::SixelBackend::new())) 30 | } else { 31 | None 32 | } 33 | 34 | #[cfg(windows)] 35 | None 36 | } 37 | 38 | #[allow(unused_variables)] 39 | pub fn get_image_backend(image_protocol: ImageProtocol) -> Option> { 40 | #[cfg(not(windows))] 41 | let backend = Some(match image_protocol { 42 | ImageProtocol::Kitty => Box::new(kitty::KittyBackend::new()) as Box, 43 | ImageProtocol::Iterm => Box::new(iterm::ITermBackend::new()) as Box, 44 | ImageProtocol::Sixel => Box::new(sixel::SixelBackend::new()) as Box, 45 | }); 46 | 47 | #[cfg(windows)] 48 | let backend = None; 49 | backend 50 | } 51 | 52 | #[cfg(not(windows))] 53 | unsafe fn get_dimensions() -> libc::winsize { 54 | use libc::{ioctl, winsize, STDOUT_FILENO, TIOCGWINSZ}; 55 | use std::mem::zeroed; 56 | 57 | let mut window: winsize = zeroed(); 58 | let result = ioctl(STDOUT_FILENO, TIOCGWINSZ, &mut window); 59 | 60 | if result == -1 { 61 | zeroed() 62 | } else { 63 | window 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /manifest/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors.workspace = true 3 | edition.workspace = true 4 | version.workspace = true 5 | license.workspace = true 6 | repository.workspace = true 7 | name = "onefetch-manifest" 8 | description = "Detect and parse manifest files" 9 | 10 | [dependencies] 11 | anyhow.workspace = true 12 | cargo_toml = "0.22.1" 13 | npm-package-json = "0.1.3" 14 | strum.workspace = true 15 | -------------------------------------------------------------------------------- /manifest/LICENSE.md: -------------------------------------------------------------------------------- 1 | ../LICENSE.md -------------------------------------------------------------------------------- /manifest/README.md: -------------------------------------------------------------------------------- 1 | # manifest 2 | 3 | [![crates.io](https://img.shields.io/crates/v/onefetch-manifest)](https://crates.io/crates/onefetch-manifest) 4 | [![docs.rs](https://img.shields.io/docsrs/onefetch-manifest)](https://docs.rs/onefetch-manifest) 5 | 6 | Provides the primary interface to detect and parse the repository's manifest(s). 7 | 8 | _This crate is designed as part of the [onefetch](https://github.com/o2sh/onefetch) project._ 9 | -------------------------------------------------------------------------------- /manifest/src/lib.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{Context, Result}; 2 | use std::fs; 3 | use std::path::Path; 4 | use strum::{Display, EnumIter}; 5 | 6 | #[derive(Clone, PartialEq, Eq, Debug)] 7 | pub struct Manifest { 8 | pub manifest_type: ManifestType, 9 | pub number_of_dependencies: usize, 10 | pub name: String, 11 | pub description: Option, 12 | pub version: String, 13 | pub license: Option, 14 | } 15 | 16 | #[derive(Display, Clone, Copy, PartialEq, Eq, Debug, EnumIter)] 17 | pub enum ManifestType { 18 | Npm, 19 | Cargo, 20 | } 21 | 22 | pub fn get_manifests>(path: P) -> Result> { 23 | let manifest_paths = fs::read_dir(path)? 24 | .filter_map(std::result::Result::ok) 25 | .map(|entry| entry.path()) 26 | .filter(|entry| entry.is_file()) 27 | .filter_map(|file_path| { 28 | let file_name = file_path 29 | .file_name() 30 | .and_then(|name| name.to_str()) 31 | .unwrap_or_default(); 32 | file_name_to_manifest_type(file_name).map(|manifest_type| (file_path, manifest_type)) 33 | }) 34 | .map(|(file_path, manifest_type)| match manifest_type { 35 | ManifestType::Cargo => parse_cargo_manifest(&file_path), 36 | ManifestType::Npm => parse_npm_manifest(&file_path), 37 | }) 38 | .filter_map(std::result::Result::ok) 39 | .collect::>(); 40 | 41 | Ok(manifest_paths) 42 | } 43 | 44 | fn parse_cargo_manifest(path: &Path) -> Result { 45 | let m = cargo_toml::Manifest::from_path(path) 46 | .with_context(|| format!("Failed to parse Cargo.toml at '{}'", path.display()))?; 47 | let package = m.package.context("Not a package (only a workspace)")?; 48 | let description = package.description().map(|v| v.into()); 49 | 50 | Ok(Manifest { 51 | manifest_type: ManifestType::Cargo, 52 | number_of_dependencies: m.dependencies.len(), 53 | name: package.name.clone(), 54 | description, 55 | version: package.version().into(), 56 | license: package.license().map(|x| x.into()), 57 | }) 58 | } 59 | 60 | fn parse_npm_manifest(path: &Path) -> Result { 61 | let package = npm_package_json::Package::from_path(path) 62 | .with_context(|| format!("Failed to parse package.json at '{}'", path.display()))?; 63 | Ok(Manifest { 64 | manifest_type: ManifestType::Npm, 65 | number_of_dependencies: package.dependencies.len(), 66 | name: package.name, 67 | description: package.description, 68 | version: package.version, 69 | license: package.license, 70 | }) 71 | } 72 | 73 | fn file_name_to_manifest_type(filename: &str) -> Option { 74 | match filename { 75 | "Cargo.toml" => Some(ManifestType::Cargo), 76 | "package.json" => Some(ManifestType::Npm), 77 | _ => None, 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /manifest/tests/cargo.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use onefetch_manifest::{get_manifests, ManifestType}; 3 | 4 | #[test] 5 | fn should_detect_and_parse_cargo_manifest() -> Result<()> { 6 | let manifests = get_manifests("tests/fixtures/cargo")?; 7 | assert_eq!(manifests.len(), 1); 8 | let cargo_manifest = manifests.first().unwrap(); 9 | assert_eq!(cargo_manifest.manifest_type, ManifestType::Cargo); 10 | assert_eq!(cargo_manifest.number_of_dependencies, 5); 11 | assert_eq!(cargo_manifest.name, String::from("project")); 12 | assert_eq!( 13 | cargo_manifest.description, 14 | Some("this is a description".into()) 15 | ); 16 | assert_eq!(cargo_manifest.version, String::from("0.1.0")); 17 | assert_eq!(cargo_manifest.license, Some("MIT".into())); 18 | 19 | Ok(()) 20 | } 21 | -------------------------------------------------------------------------------- /manifest/tests/fixtures/cargo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "project" 3 | version = "0.1.0" 4 | edition = "2018" 5 | description = "this is a description" 6 | license = "MIT" 7 | 8 | [dependencies] 9 | cortex-m-rtic = "0.6.0-alpha.1" 10 | anyhow = "1.0" 11 | 12 | [dependencies.cortex-m] 13 | version = "0.7.1" 14 | 15 | [dependencies.cortex-m-rt] 16 | version = "0.6.11" 17 | 18 | [dependencies.stm32f4xx-hal] 19 | version = "0.8.3" 20 | features = ["rt", "stm32f401"] 21 | -------------------------------------------------------------------------------- /manifest/tests/fixtures/npm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my_package", 3 | "description": "description for my_package", 4 | "version": "1.0.0", 5 | "main": "index.js", 6 | "dependencies": { 7 | "@rollup/plugin-yaml": "^4.0.1", 8 | "@sveltejs/vite-plugin-svelte": "^1.0.8", 9 | "@tsconfig/svelte": "^3.0.0" 10 | }, 11 | "scripts": { 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com//my_package.git" 17 | }, 18 | "keywords": [], 19 | "author": "", 20 | "license": "ISC", 21 | "bugs": { 22 | "url": "https://github.com//my_package/issues" 23 | }, 24 | "homepage": "https://github.com//my_package" 25 | } 26 | -------------------------------------------------------------------------------- /manifest/tests/npm.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use onefetch_manifest::{get_manifests, ManifestType}; 3 | 4 | #[test] 5 | fn should_detect_and_parse_npm_manifest() -> Result<()> { 6 | let manifests = get_manifests("tests/fixtures/npm")?; 7 | assert_eq!(manifests.len(), 1); 8 | let npm_manifest = manifests.first().unwrap(); 9 | assert_eq!(npm_manifest.manifest_type, ManifestType::Npm); 10 | assert_eq!(npm_manifest.number_of_dependencies, 3); 11 | assert_eq!(npm_manifest.name, String::from("my_package")); 12 | assert_eq!( 13 | npm_manifest.description, 14 | Some("description for my_package".into()) 15 | ); 16 | assert_eq!(npm_manifest.version, String::from("1.0.0")); 17 | assert_eq!(npm_manifest.license, Some("ISC".into())); 18 | Ok(()) 19 | } 20 | -------------------------------------------------------------------------------- /resources/license.cache.zstd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/o2sh/onefetch/be4f2c8235100730a9c80954e93a5d2296294f8a/resources/license.cache.zstd -------------------------------------------------------------------------------- /scripts/nf-preview.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require "yaml" 3 | 4 | LANGUAGES_FILE = File.expand_path("../../languages.yaml", __FILE__) 5 | 6 | languages = YAML.safe_load_file(ARGV[0] || LANGUAGES_FILE, symbolize_names: true) 7 | 8 | languages.each do |language, attributes| 9 | icon = attributes[:icon] 10 | next if icon.nil? 11 | match = /\A\\u\{([A-F0-9]{4,})\}\z/i.match(icon) 12 | raise "Icon for #{language} is not in the correct format: `#{icon}`" unless match 13 | glyph = match.captures[0].hex.chr("UTF-8") 14 | puts "#{language}: #{glyph}" 15 | end 16 | -------------------------------------------------------------------------------- /snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: onefetch 2 | base: core22 3 | adopt-info: onefetch 4 | summary: Command-line Git information tool 5 | description: | 6 | Onefetch is a command-line Git information tool that displays project information 7 | and code statistics for a local Git repository directly to your terminal. 8 | 9 | grade: stable 10 | confinement: strict 11 | 12 | parts: 13 | onefetch: 14 | plugin: rust 15 | source: . 16 | build-packages: 17 | - cargo 18 | - rustc 19 | - cmake 20 | stage-packages: 21 | - git 22 | override-build: | 23 | snapcraftctl build 24 | snapcraftctl set-version $(git describe --abbrev=0 --tags) 25 | 26 | plugs: 27 | etc-gitconfig: 28 | interface: system-files 29 | read: 30 | - /etc/gitconfig 31 | gitconfig: 32 | interface: personal-files 33 | read: 34 | - $HOME/.gitconfig 35 | - $HOME/.config/git/config 36 | 37 | apps: 38 | onefetch: 39 | environment: 40 | HOME: $SNAP_REAL_HOME 41 | command: bin/onefetch 42 | plugs: 43 | - home 44 | - removable-media 45 | - etc-gitconfig 46 | - gitconfig 47 | -------------------------------------------------------------------------------- /src/info/commits.rs: -------------------------------------------------------------------------------- 1 | use super::git::metrics::GitMetrics; 2 | use crate::{ 3 | cli::NumberSeparator, 4 | info::utils::{format_number, info_field::InfoField}, 5 | }; 6 | use serde::Serialize; 7 | 8 | #[derive(Serialize)] 9 | #[serde(rename_all = "camelCase")] 10 | pub struct CommitsInfo { 11 | pub number_of_commits: usize, 12 | is_shallow: bool, 13 | #[serde(skip_serializing)] 14 | number_separator: NumberSeparator, 15 | } 16 | 17 | impl CommitsInfo { 18 | pub fn new( 19 | git_metrics: &GitMetrics, 20 | is_shallow: bool, 21 | number_separator: NumberSeparator, 22 | ) -> Self { 23 | Self { 24 | number_of_commits: git_metrics.total_number_of_commits, 25 | is_shallow, 26 | number_separator, 27 | } 28 | } 29 | } 30 | 31 | #[typetag::serialize] 32 | impl InfoField for CommitsInfo { 33 | fn value(&self) -> String { 34 | format!( 35 | "{}{}", 36 | format_number(&self.number_of_commits, self.number_separator), 37 | self.is_shallow.then_some(" (shallow)").unwrap_or_default() 38 | ) 39 | } 40 | 41 | fn title(&self) -> String { 42 | "Commits".into() 43 | } 44 | } 45 | 46 | #[cfg(test)] 47 | mod test { 48 | use super::*; 49 | 50 | #[test] 51 | fn test_display_commits_info() { 52 | let commits_info = CommitsInfo { 53 | number_of_commits: 3, 54 | is_shallow: false, 55 | number_separator: NumberSeparator::Plain, 56 | }; 57 | 58 | assert_eq!(commits_info.value(), "3".to_string()); 59 | } 60 | 61 | #[test] 62 | fn test_display_commits_info_shallow() { 63 | let commits_info = CommitsInfo { 64 | number_of_commits: 2, 65 | is_shallow: true, 66 | number_separator: NumberSeparator::Plain, 67 | }; 68 | 69 | assert_eq!(commits_info.value(), "2 (shallow)".to_string()); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/info/contributors.rs: -------------------------------------------------------------------------------- 1 | use super::utils::format_number; 2 | use crate::{cli::NumberSeparator, info::utils::info_field::InfoField}; 3 | use serde::Serialize; 4 | 5 | #[derive(Serialize)] 6 | #[serde(rename_all = "camelCase")] 7 | pub struct ContributorsInfo { 8 | pub total_number_of_authors: usize, 9 | #[serde(skip_serializing)] 10 | pub number_of_authors_to_display: usize, 11 | #[serde(skip_serializing)] 12 | number_separator: NumberSeparator, 13 | } 14 | 15 | impl ContributorsInfo { 16 | pub fn new( 17 | total_number_of_authors: usize, 18 | number_of_authors_to_display: usize, 19 | number_separator: NumberSeparator, 20 | ) -> Self { 21 | Self { 22 | total_number_of_authors, 23 | number_of_authors_to_display, 24 | number_separator, 25 | } 26 | } 27 | } 28 | 29 | #[typetag::serialize] 30 | impl InfoField for ContributorsInfo { 31 | fn value(&self) -> String { 32 | if self.total_number_of_authors > self.number_of_authors_to_display { 33 | format_number(&self.total_number_of_authors, self.number_separator) 34 | } else { 35 | "".to_string() 36 | } 37 | } 38 | 39 | fn title(&self) -> String { 40 | "Contributors".into() 41 | } 42 | } 43 | 44 | #[cfg(test)] 45 | mod test { 46 | use super::*; 47 | 48 | #[test] 49 | fn test_display_contributors_info() { 50 | let contributors_info = ContributorsInfo::new(12, 2, NumberSeparator::Plain); 51 | assert_eq!(contributors_info.value(), "12".to_string()); 52 | assert_eq!(contributors_info.title(), "Contributors".to_string()); 53 | } 54 | 55 | #[test] 56 | fn test_display_contributors_less_than_authors_to_display() { 57 | let contributors_info = ContributorsInfo { 58 | total_number_of_authors: 1, 59 | number_of_authors_to_display: 3, 60 | number_separator: NumberSeparator::Plain, 61 | }; 62 | 63 | assert!(contributors_info.value().is_empty()); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/info/created.rs: -------------------------------------------------------------------------------- 1 | use super::{git::metrics::GitMetrics, utils::format_time}; 2 | use crate::info::utils::info_field::InfoField; 3 | use serde::Serialize; 4 | 5 | #[derive(Serialize)] 6 | #[serde(rename_all = "camelCase")] 7 | pub struct CreatedInfo { 8 | pub creation_date: String, 9 | } 10 | 11 | impl CreatedInfo { 12 | pub fn new(iso_time: bool, git_metrics: &GitMetrics) -> Self { 13 | let creation_date = get_creation_date(git_metrics, iso_time); 14 | Self { creation_date } 15 | } 16 | } 17 | 18 | fn get_creation_date(git_metrics: &GitMetrics, iso_time: bool) -> String { 19 | format_time(git_metrics.time_of_first_commit, iso_time) 20 | } 21 | 22 | #[typetag::serialize] 23 | impl InfoField for CreatedInfo { 24 | fn value(&self) -> String { 25 | self.creation_date.to_string() 26 | } 27 | 28 | fn title(&self) -> String { 29 | "Created".into() 30 | } 31 | } 32 | 33 | #[cfg(test)] 34 | mod test { 35 | use super::*; 36 | 37 | #[test] 38 | fn test_display_created_info() { 39 | let created_info = CreatedInfo { 40 | creation_date: "2 years ago".to_string(), 41 | }; 42 | 43 | assert_eq!(created_info.value(), "2 years ago".to_string()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/info/dependencies.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | cli::NumberSeparator, 3 | info::utils::{format_number, info_field::InfoField}, 4 | }; 5 | use onefetch_manifest::Manifest; 6 | use serde::Serialize; 7 | 8 | #[derive(Serialize)] 9 | pub struct DependenciesInfo { 10 | pub dependencies: String, 11 | } 12 | 13 | impl DependenciesInfo { 14 | pub fn new(manifest: Option<&Manifest>, number_separator: NumberSeparator) -> Self { 15 | let dependencies = manifest 16 | .and_then(|m| { 17 | (m.number_of_dependencies != 0).then(|| { 18 | format!( 19 | "{} ({})", 20 | format_number(&m.number_of_dependencies, number_separator), 21 | m.manifest_type 22 | ) 23 | }) 24 | }) 25 | .unwrap_or_default(); 26 | 27 | Self { dependencies } 28 | } 29 | } 30 | 31 | #[typetag::serialize] 32 | impl InfoField for DependenciesInfo { 33 | fn value(&self) -> String { 34 | self.dependencies.clone() 35 | } 36 | 37 | fn title(&self) -> String { 38 | "Dependencies".into() 39 | } 40 | } 41 | 42 | #[cfg(test)] 43 | mod test { 44 | use super::*; 45 | use onefetch_manifest::ManifestType; 46 | 47 | #[test] 48 | fn should_display_license() { 49 | let dependencies_info = DependenciesInfo::new( 50 | Some(&Manifest { 51 | manifest_type: ManifestType::Cargo, 52 | name: String::new(), 53 | description: None, 54 | number_of_dependencies: 21, 55 | version: String::new(), 56 | license: None, 57 | }), 58 | NumberSeparator::Plain, 59 | ); 60 | 61 | assert_eq!(dependencies_info.value(), "21 (Cargo)".to_string()); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/info/description.rs: -------------------------------------------------------------------------------- 1 | use crate::info::utils::info_field::InfoField; 2 | use onefetch_manifest::Manifest; 3 | use serde::Serialize; 4 | 5 | const NUMBER_OF_WORDS_PER_LINE: usize = 5; 6 | 7 | #[derive(Serialize)] 8 | pub struct DescriptionInfo { 9 | pub description: Option, 10 | } 11 | 12 | impl DescriptionInfo { 13 | pub fn new(manifest: Option<&Manifest>) -> Self { 14 | let description = match manifest { 15 | Some(m) => m.description.clone(), 16 | None => None, 17 | }; 18 | 19 | Self { description } 20 | } 21 | } 22 | 23 | #[typetag::serialize] 24 | impl InfoField for DescriptionInfo { 25 | fn value(&self) -> String { 26 | match &self.description { 27 | Some(description) => { 28 | let left_pad = self.title().len() + 2; 29 | break_sentence_into_lines(description, left_pad) 30 | } 31 | None => String::new(), 32 | } 33 | } 34 | 35 | fn title(&self) -> String { 36 | "Description".into() 37 | } 38 | } 39 | 40 | fn break_sentence_into_lines(sentence: &str, left_pad: usize) -> String { 41 | let words: Vec<&str> = sentence.split_whitespace().collect(); 42 | let mut lines = Vec::new(); 43 | 44 | for (i, chunk) in words.chunks(NUMBER_OF_WORDS_PER_LINE).enumerate() { 45 | let line = if i == 0 { 46 | chunk.join(" ") 47 | } else { 48 | format!("{:>width$}{}", "", chunk.join(" "), width = left_pad) 49 | }; 50 | lines.push(line); 51 | } 52 | 53 | lines.join("\n") 54 | } 55 | 56 | #[cfg(test)] 57 | mod test { 58 | use super::*; 59 | use onefetch_manifest::ManifestType; 60 | use rstest::rstest; 61 | 62 | #[test] 63 | fn should_display_description() { 64 | let description_info = DescriptionInfo::new(Some(&Manifest { 65 | manifest_type: ManifestType::Cargo, 66 | name: String::new(), 67 | description: Some("test".into()), 68 | number_of_dependencies: 0, 69 | version: "0.1.0".into(), 70 | license: None, 71 | })); 72 | 73 | assert_eq!(description_info.value(), "test".to_string()); 74 | } 75 | 76 | #[rstest] 77 | #[case("Hello", "Hello")] 78 | #[case( 79 | "Hello world, how are you doing?", 80 | "Hello world, how are you\n doing?" 81 | )] 82 | #[case( 83 | "This is a long sentence that needs to be broken into multiple lines.", 84 | "This is a long sentence\n that needs to be broken\n into multiple lines." 85 | )] 86 | fn test_break_sentence_into_lines(#[case] sentence: &str, #[case] expected_result: &str) { 87 | assert_eq!(break_sentence_into_lines(sentence, 4), expected_result); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/info/git/metrics.rs: -------------------------------------------------------------------------------- 1 | use super::sig::Sig; 2 | use anyhow::Result; 3 | use gix::bstr::BString; 4 | use gix::date::Time; 5 | use std::collections::HashMap; 6 | 7 | pub struct GitMetrics { 8 | pub number_of_commits_by_signature: HashMap, 9 | pub number_of_commits_by_file_path: HashMap, 10 | pub total_number_of_authors: usize, 11 | pub total_number_of_commits: usize, 12 | pub churn_pool_size: usize, 13 | pub time_of_most_recent_commit: gix::date::Time, 14 | pub time_of_first_commit: gix::date::Time, 15 | } 16 | 17 | impl GitMetrics { 18 | pub fn new( 19 | number_of_commits_by_signature: HashMap, 20 | number_of_commits_by_file_path: HashMap, 21 | churn_pool_size: usize, 22 | time_of_first_commit: Option