├── .github ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug.yml │ ├── config.yml │ ├── question.yml │ └── suggestion.yml ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml ├── images │ ├── 256_colors.png │ ├── card.svg │ ├── color_b.svg │ ├── color_bl.svg │ ├── color_c.svg │ ├── color_cl.svg │ ├── color_d.svg │ ├── color_g.svg │ ├── color_gl.svg │ ├── color_m.svg │ ├── color_ml.svg │ ├── color_r.svg │ ├── color_rl.svg │ ├── color_s.svg │ ├── color_sl.svg │ ├── color_w.svg │ ├── color_y.svg │ ├── color_yl.svg │ ├── fmtc_highlight.png │ ├── godoc.svg │ └── license.svg └── workflows │ ├── ci.yml │ ├── codeql-analysis.yml │ └── godoc.yml ├── .gitignore ├── .scripts ├── fuzz-gen.sh ├── nix.sh ├── packages.list └── windows.ps1 ├── .typos.toml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── SECURITY.md ├── ansi ├── ansi.go ├── ansi_test.go └── examples_test.go ├── cache ├── cache.go ├── fs │ ├── examples_test.go │ ├── fs.go │ ├── fs_stubs.go │ └── fs_test.go └── memory │ ├── examples_test.go │ ├── memory.go │ └── memory_test.go ├── color ├── color.go ├── color_test.go └── examples_test.go ├── cron ├── cron.go ├── cron_test.go ├── examples_test.go └── fuzz.go ├── csv ├── csv.go ├── csv_test.go └── examples_test.go ├── directio ├── directio.go ├── directio_darwin.go ├── directio_linux.go ├── directio_stubs.go └── directio_test.go ├── easing ├── back.go ├── bounce.go ├── circ.go ├── cubic.go ├── ease.go ├── ease_test.go ├── elastic.go ├── examples_test.go ├── expo.go ├── linear.go ├── quad.go ├── quint.go └── sine.go ├── ek.go ├── ek_windows.go ├── emoji ├── emoji.go ├── emoji_test.go └── examples_test.go ├── env ├── env.go ├── env_stubs.go ├── env_test.go ├── env_unix.go └── example_test.go ├── errors ├── errors.go ├── errors_test.go └── example_test.go ├── events ├── events.go ├── events_test.go └── examples_test.go ├── fmtc ├── README.md ├── cond_wrapper.go ├── examples_test.go ├── fmtc.go ├── fmtc_test.go └── fuzz.go ├── fmtutil ├── barcode │ ├── barcode.go │ └── barcode_test.go ├── example_test.go ├── filetree │ └── filetree.go ├── fmtutil.go ├── fmtutil_test.go ├── panel │ ├── example_test.go │ ├── panel.go │ └── panel_test.go ├── separator.go └── table │ ├── example_test.go │ ├── table.go │ └── table_test.go ├── fsutil ├── examples_test.go ├── fs.go ├── fs_darwin.go ├── fs_freebsd.go ├── fs_linux.go ├── fs_stubs.go ├── fs_test.go ├── fs_user.go ├── fs_user_unit.go ├── helpers.go ├── helpers_stubs.go ├── line_count.go ├── list.go ├── list_stubs.go ├── walker.go └── walker_stubs.go ├── go.mod ├── go.sum ├── hash └── filehash.go ├── hashutil ├── example_test.go ├── helpers.go └── helpers_test.go ├── httputil ├── examples_test.go ├── httputil.go └── httputil_test.go ├── i18n ├── example_test.go ├── i18n.go └── i18n_test.go ├── initsystem ├── examples_test.go ├── initsystem.go ├── initsystem_darwin.go ├── initsystem_darwin_test.go ├── initsystem_stubs.go ├── initsystem_test.go └── sdnotify │ ├── example_test.go │ ├── sdnotify_linux.go │ └── sdnotify_stubs.go ├── jsonutil ├── example_test.go ├── jsonutil.go └── jsonutil_test.go ├── knf ├── example_test.go ├── fuzz.go ├── knf.go ├── knf_parser.go ├── knf_test.go ├── united │ ├── example_test.go │ ├── united.go │ └── united_test.go ├── validators │ ├── cron │ │ ├── validators.go │ │ └── validators_test.go │ ├── fs │ │ ├── validators.go │ │ └── validators_test.go │ ├── network │ │ ├── validators.go │ │ └── validators_test.go │ ├── regexp │ │ ├── validators.go │ │ └── validators_test.go │ ├── system │ │ ├── validators.go │ │ ├── validators_linux.go │ │ ├── validators_linux_test.go │ │ └── validators_test.go │ ├── time │ │ ├── validators.go │ │ └── validators_test.go │ ├── validators.go │ └── validators_test.go └── value │ ├── value.go │ └── value_test.go ├── lock ├── examples_test.go ├── lock.go ├── lock_darwin.go ├── lock_linux.go ├── lock_stubs.go └── lock_test.go ├── log ├── example_test.go ├── log.go ├── log_test.go ├── nil.go └── std.go ├── lscolors ├── examples_test.go ├── lscolors.go └── lscolors_test.go ├── mathutil ├── example_test.go ├── mathutil.go └── mathutil_test.go ├── netutil ├── example_test.go ├── netutil.go ├── netutil_darwin.go ├── netutil_darwin_test.go ├── netutil_linux.go ├── netutil_linux_test.go └── netutil_stubs.go ├── options ├── arguments.go ├── example_test.go ├── options.go └── options_test.go ├── pager ├── example_test.go ├── pager_posix.go ├── pager_stubs.go └── pager_test.go ├── passthru ├── passthru.go ├── passthru_spinner_test.go └── passthru_test.go ├── passwd ├── example_test.go ├── passwd.go └── passwd_test.go ├── path ├── example_test.go ├── path.go ├── path_posix.go ├── path_posix_test.go ├── path_test.go ├── path_windows.go └── path_windows_test.go ├── pid ├── example_test.go ├── pid.go ├── pid_darwin.go ├── pid_darwin_test.go ├── pid_freebsd.go ├── pid_linux.go ├── pid_linux_test.go ├── pid_stubs.go └── pid_test.go ├── pluralize ├── examples_test.go ├── pluralize.go ├── pluralize_test.go └── pluralizers.go ├── progress ├── examples_test.go ├── progress.go └── progress_test.go ├── protip ├── example_test.go ├── protip.go └── protip_test.go ├── rand ├── rand.go └── rand_test.go ├── req ├── auth.go ├── example_test.go ├── headers.go ├── limiter.go ├── query.go ├── req.go ├── req_test.go └── retrier.go ├── reutil ├── example_test.go ├── reutil.go └── reutil_test.go ├── secstr ├── example_test.go ├── secstring.go ├── secstring_stubs.go └── secstring_test.go ├── setup ├── setup.go ├── setup_stub.go └── setup_test.go ├── signal ├── example_test.go ├── signal.go └── signal_stubs.go ├── sliceutil ├── example_test.go ├── sliceutil.go └── sliceutil_test.go ├── sortutil ├── example_test.go ├── natural.go ├── sortutil.go └── sortutil_test.go ├── spellcheck ├── example_test.go ├── spellcheck.go └── spellcheck_test.go ├── spinner ├── examples_test.go ├── spinner.go └── spinner_test.go ├── strutil ├── example_test.go ├── fuzz.go ├── strutil.go └── strutil_test.go ├── support ├── apps │ ├── apps.go │ └── example_test.go ├── deps │ └── deps.go ├── fs │ ├── fs.go │ └── fs_windows.go ├── kernel │ ├── kernel.go │ └── kernel_windows.go ├── network │ ├── ip-resolver.go │ ├── network.go │ └── network_windows.go ├── pkgs │ ├── pkgs_darwin.go │ ├── pkgs_linux.go │ └── pkgs_windows.go ├── resources │ ├── resources.go │ └── resources_windows.go ├── services │ ├── services.go │ └── services_windows.go ├── support.go ├── support_darwin.go ├── support_linux.go ├── support_test.go └── support_windows.go ├── system ├── container │ ├── container.go │ ├── container_test.go │ └── example_test.go ├── examples_test.go ├── exec │ ├── examples_test.go │ ├── exec.go │ └── exec_stubs.go ├── fuzz.go ├── info.go ├── info_cpu_darwin.go ├── info_cpu_linux.go ├── info_darwin.go ├── info_darwin_test.go ├── info_fs_darwin.go ├── info_fs_linux.go ├── info_linux.go ├── info_linux_arm.go ├── info_linux_basic.go ├── info_linux_test.go ├── info_loadavg_darwin.go ├── info_loadavg_linux.go ├── info_memory_darwin.go ├── info_memory_linux.go ├── info_net_darwin.go ├── info_net_linux.go ├── info_stubs.go ├── info_uptime_darwin.go ├── info_uptime_linux.go ├── process │ ├── examples_test.go │ ├── process_cpu.go │ ├── process_darwin.go │ ├── process_memory.go │ ├── process_mount.go │ ├── process_nice.go │ ├── process_stubs.go │ ├── process_test.go │ ├── processes_darwin.go │ ├── processes_linux.go │ └── processes_stubs.go ├── procname │ ├── examples_test.go │ ├── setprocname.go │ └── setprocname_stubs.go ├── sensors │ ├── sensors_darwin.go │ ├── sensors_linux.go │ ├── sensors_stubs.go │ └── sensors_test.go ├── sysctl │ ├── example_test.go │ ├── sysctl.go │ ├── sysctl_darwin.go │ ├── sysctl_linux.go │ ├── sysctl_stubs.go │ └── sysctl_test.go ├── user.go ├── user_bsd.go ├── user_darwin.go ├── user_linux.go ├── user_stubs.go └── user_unix.go ├── terminal ├── example_test.go ├── input │ ├── example_test.go │ ├── input.go │ ├── input_stubs.go │ ├── input_test.go │ └── input_validators.go ├── terminal.go ├── terminal_test.go └── tty │ ├── example_test.go │ ├── size_posix.go │ ├── tmux_darwin.go │ ├── tmux_linux.go │ ├── tty_posix.go │ ├── tty_stubs.go │ └── tty_test.go ├── timeutil ├── example_test.go ├── fuzz.go ├── period.go ├── timeutil.go ├── timeutil_test.go ├── timeutil_unix.go ├── timeutil_unix_test.go ├── timeutil_windows.go ├── timeutil_windows_test.go └── tinydate.go ├── tmp ├── examples_test.go ├── tmp.go └── tmp_test.go ├── usage ├── completion │ ├── bash │ │ ├── bash.go │ │ ├── bash_test.go │ │ └── examples_test.go │ ├── fish │ │ ├── examples_test.go │ │ ├── fish.go │ │ └── fish_test.go │ └── zsh │ │ ├── examples_test.go │ │ ├── zsh.go │ │ └── zsh_test.go ├── example_test.go ├── man │ ├── man.go │ └── man_test.go ├── update │ ├── github.go │ ├── gitlab.go │ ├── update.go │ └── update_test.go ├── usage.go └── usage_test.go ├── uuid ├── example_test.go ├── prefixed │ ├── example_test.go │ ├── prefixed.go │ └── prefixed_test.go ├── uuid.go └── uuid_test.go ├── version.go └── version ├── example_test.go ├── fuzz.go ├── version.go └── version_test.go /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @essentialkaos/go 2 | /.github/workflows/* @essentialkaos/devops 3 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | **IMPORTANT! Contribute your code only if you have an excellent understanding of project idea and all existing code base. Otherwise, a nicely formatted issue will be more helpful to us.** 4 | 5 | ### Issues 6 | 7 | 1. Provide product version where the problem was found; 8 | 2. Provide info about your environment; 9 | 3. Provide detailed info about your problem; 10 | 4. Provide steps to reproduce the problem; 11 | 5. Provide actual and expected results. 12 | 13 | ### Code 14 | 15 | 1. Check your code **before** creating pull request; 16 | 2. If tests are present in a project, add tests for your code; 17 | 3. Add inline documentation for your code; 18 | 4. Apply code style used throughout the project; 19 | 5. Create your pull request to `develop` branch (_pull requests to other branches are not allowed_). 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.yml: -------------------------------------------------------------------------------- 1 | name: ❗ Bug Report 2 | description: File a bug report 3 | title: "[Bug]: " 4 | labels: ["issue • bug"] 5 | assignees: 6 | - andyone 7 | 8 | body: 9 | - type: markdown 10 | attributes: 11 | value: | 12 | > [!IMPORTANT] 13 | > Before you open an issue, search GitHub Issues for a similar bug reports. If so, please add a 👍 reaction to the existing issue. 14 | 15 | - type: textarea 16 | attributes: 17 | label: Module version info 18 | description: Output of `go list -m -u github.com/essentialkaos/ek/v13` command 19 | render: shell 20 | validations: 21 | required: true 22 | 23 | - type: textarea 24 | attributes: 25 | label: Steps to reproduce 26 | description: Short guide on how to reproduce this problem on our site 27 | placeholder: | 28 | 1. [First Step] 29 | 2. [Second Step] 30 | 3. [and so on...] 31 | validations: 32 | required: true 33 | 34 | - type: textarea 35 | attributes: 36 | label: Expected behavior 37 | description: What you expected to happen 38 | validations: 39 | required: true 40 | 41 | - type: textarea 42 | attributes: 43 | label: Actual behavior 44 | description: What actually happened 45 | validations: 46 | required: true 47 | 48 | - type: textarea 49 | attributes: 50 | label: Additional info 51 | description: Include gist of relevant config, logs, etc. 52 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.yml: -------------------------------------------------------------------------------- 1 | name: ❓ Question 2 | description: Question about application, configuration or code 3 | title: "[Question]: " 4 | labels: ["issue • question"] 5 | assignees: 6 | - andyone 7 | 8 | body: 9 | - type: markdown 10 | attributes: 11 | value: | 12 | > [!IMPORTANT] 13 | > Before you open an issue, search GitHub Issues for a similar question. If so, please add a 👍 reaction to the existing issue. 14 | 15 | - type: textarea 16 | attributes: 17 | label: Question 18 | description: Detailed question 19 | validations: 20 | required: true 21 | 22 | - type: textarea 23 | attributes: 24 | label: Related module version info 25 | description: Output of `go list -m -u github.com/essentialkaos/ek/v13` command 26 | render: shell 27 | validations: 28 | required: true 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/suggestion.yml: -------------------------------------------------------------------------------- 1 | name: ➕ Suggestion 2 | description: Suggest new feature or improvement 3 | title: "[Suggestion]: " 4 | labels: ["issue • suggestion"] 5 | assignees: 6 | - andyone 7 | 8 | body: 9 | - type: markdown 10 | attributes: 11 | value: | 12 | > [!IMPORTANT] 13 | > Before you open an issue, search GitHub Issues for a similar feature requests. If so, please add a 👍 reaction to the existing issue. 14 | > 15 | > Opening a feature request kicks off a discussion. Requests may be closed if we're not actively planning to work on them. 16 | 17 | - type: textarea 18 | attributes: 19 | label: Proposal 20 | description: Description of the feature 21 | validations: 22 | required: true 23 | 24 | - type: textarea 25 | attributes: 26 | label: Current behavior 27 | description: What currently happens 28 | validations: 29 | required: true 30 | 31 | - type: textarea 32 | attributes: 33 | label: Desired behavior 34 | description: What you would like to happen 35 | validations: 36 | required: true 37 | 38 | - type: textarea 39 | attributes: 40 | label: Use case 41 | description: Why is this important (helps with prioritizing requests) 42 | validations: 43 | required: true 44 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### What did you implement: 2 | 3 | Closes #XXXXX 4 | 5 | ### How did you implement it: 6 | 7 | ... 8 | 9 | ### How can we verify it: 10 | 11 | ... 12 | 13 | ### TODO's: 14 | 15 | - [ ] Write tests 16 | - [ ] Write documentation 17 | - [ ] Check that there aren't other open pull requests for the same issue/feature 18 | - [ ] Format your source code by `make fmt` 19 | - [ ] Pass the test by `make test` 20 | - [ ] Provide verification config / commands 21 | - [ ] Enable "Allow edits from maintainers" for this PR 22 | - [ ] Update the messages below 23 | 24 | **Is this ready for review?:** No 25 | **Is it a breaking change?:** No 26 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | - package-ecosystem: "gomod" 5 | directory: "/" 6 | target-branch: "develop" 7 | schedule: 8 | interval: "daily" 9 | timezone: "Etc/UTC" 10 | time: "03:00" 11 | labels: 12 | - "PR • MAINTENANCE" 13 | assignees: 14 | - "andyone" 15 | groups: 16 | all: 17 | applies-to: version-updates 18 | update-types: 19 | - "minor" 20 | - "patch" 21 | 22 | - package-ecosystem: "github-actions" 23 | directory: "/" 24 | target-branch: "develop" 25 | schedule: 26 | interval: "daily" 27 | timezone: "Etc/UTC" 28 | time: "03:00" 29 | labels: 30 | - "PR • MAINTENANCE" 31 | assignees: 32 | - "andyone" 33 | -------------------------------------------------------------------------------- /.github/images/256_colors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/essentialkaos/ek/26c66bcad5669d03cf1e4983bf767099f014d23e/.github/images/256_colors.png -------------------------------------------------------------------------------- /.github/images/card.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/images/color_b.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/images/color_bl.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/images/color_c.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/images/color_cl.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/images/color_d.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/images/color_g.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/images/color_gl.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/images/color_m.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/images/color_ml.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/images/color_r.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/images/color_rl.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/images/color_s.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/images/color_sl.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/images/color_w.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/images/color_y.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/images/color_yl.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/images/fmtc_highlight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/essentialkaos/ek/26c66bcad5669d03cf1e4983bf767099f014d23e/.github/images/fmtc_highlight.png -------------------------------------------------------------------------------- /.github/images/godoc.svg: -------------------------------------------------------------------------------- 1 | go: referencegoreference -------------------------------------------------------------------------------- /.github/images/license.svg: -------------------------------------------------------------------------------- 1 | license: Apache-2.0licenseApache-2.0 -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [master, develop] 6 | pull_request: 7 | branches: [master] 8 | schedule: 9 | - cron: '0 3 * * */2' 10 | 11 | permissions: 12 | security-events: write 13 | actions: read 14 | contents: read 15 | 16 | concurrency: 17 | group: ${{ github.workflow }}-${{ github.ref }} 18 | cancel-in-progress: true 19 | 20 | jobs: 21 | analyse: 22 | name: Analyse 23 | runs-on: ubuntu-latest 24 | 25 | steps: 26 | - name: Checkout repository 27 | uses: actions/checkout@v4 28 | with: 29 | fetch-depth: 2 30 | 31 | - name: Initialize CodeQL 32 | uses: github/codeql-action/init@v3 33 | with: 34 | languages: go 35 | 36 | - name: Perform CodeQL Analysis 37 | uses: github/codeql-action/analyze@v3 38 | -------------------------------------------------------------------------------- /.github/workflows/godoc.yml: -------------------------------------------------------------------------------- 1 | name: GoDoc 2 | 3 | on: 4 | create 5 | 6 | jobs: 7 | GoDoc: 8 | name: Generate docs 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - name: Trigger GoSumDB and PkgGoDev 13 | uses: essentialkaos/godoc-action@v1 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | coverage.html 2 | -------------------------------------------------------------------------------- /.scripts/packages.list: -------------------------------------------------------------------------------- 1 | * + ansi 2 | * + cache/fs 3 | * + cache/memory 4 | * + color 5 | * + cron 6 | * + csv 7 | * + directio 8 | * + easing 9 | * + emoji 10 | * + env 11 | * + errors 12 | * + events 13 | * + fmtc 14 | * + fmtutil 15 | * + fmtutil/barcode 16 | * + fmtutil/panel 17 | * + fmtutil/table 18 | * + fsutil 19 | * + hashutil 20 | * + httputil 21 | * + i18n 22 | * - initsystem 23 | * ! initsystem/sdnotify 24 | * + jsonutil 25 | * + knf 26 | * + knf/united 27 | * + knf/validators 28 | * + knf/validators/cron 29 | * + knf/validators/fs 30 | * + knf/validators/network 31 | * + knf/validators/regexp 32 | * + knf/validators/system 33 | * + knf/validators/time 34 | * + knf/value 35 | * + lock 36 | * + log 37 | * + lscolors 38 | * + mathutil 39 | L + netutil 40 | * + options 41 | * + pager 42 | * + passthru 43 | * + passwd 44 | * + path 45 | * + pid 46 | * + pluralize 47 | * + progress 48 | * + protip 49 | * + rand 50 | * + req 51 | * + reutil 52 | * + secstr 53 | L - setup 54 | * - signal 55 | * + sliceutil 56 | * + sortutil 57 | * + spellcheck 58 | * + spinner 59 | * + strutil 60 | * - support 61 | * - system 62 | * - system/container 63 | * - system/exec 64 | L - system/process 65 | * - system/procname 66 | L + system/sensors 67 | * + system/sysctl 68 | * + terminal 69 | * ! terminal/tty 70 | * - terminal/input 71 | * + timeutil 72 | * + tmp 73 | * + usage 74 | * + usage/completion/bash 75 | * + usage/completion/fish 76 | * + usage/completion/zsh 77 | * + usage/man 78 | * + usage/update 79 | * + uuid 80 | * + uuid/prefixed 81 | * + version 82 | -------------------------------------------------------------------------------- /.scripts/windows.ps1: -------------------------------------------------------------------------------- 1 | <# Download dependencies #> 2 | function Get-Deps { 3 | go get -v golang.org/x/crypto/bcrypt 4 | go get -v github.com/essentialkaos/depsy 5 | } 6 | 7 | <# Try to install everything #> 8 | function Install-All { 9 | go install ./... 10 | } 11 | 12 | Get-Deps 13 | Install-All 14 | -------------------------------------------------------------------------------- /.typos.toml: -------------------------------------------------------------------------------- 1 | [files] 2 | extend-exclude = ["go.sum"] 3 | 4 | [default.extend-identifiers] 5 | Childs = "Childs" 6 | dows = "dows" 7 | testin = "testin" 8 | Fo = "Fo" 9 | 2nd_place_medal = "2nd_place_medal" 10 | womens = "womens" 11 | mrs_claus = "mrs_claus" 12 | NewCFBEncrypter = "NewCFBEncrypter" 13 | iterm = "iterm" 14 | O_WRONLY = "O_WRONLY" 15 | FO = "FO" 16 | typ = "typ" 17 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ### The meaning of "open-source" 2 | 3 | Our open source projects have publicly available code and other resources. This means that you are free to read and use it as you see fit under the terms of the license (_usually [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0.html)_). 4 | 5 | This simple fact is often misunderstood, so let us be crystal clear about what open source **does not** automatically mean by default: 6 | 7 | - It does not mean open to contributions; 8 | - It does not mean support is offered; 9 | - It does not mean you’re entitled to feature requests; 10 | - It does not mean the developer owes you their time; 11 | - It does not mean you’re entitled to anything; 12 | - It does not mean it is _free_ and open-source (_FOSS_). 13 | 14 | You can read more about this POV in [this article](https://vale.rocks/posts/open-source-entitlement). 15 | 16 | ### Issues 17 | 18 | 1. Provide product version where the problem was found; 19 | 2. Provide info about your environment; 20 | 3. Provide detailed info about your problem; 21 | 4. Provide steps to reproduce the problem; 22 | 5. Provide actual and expected results. 23 | 24 | ### Code 25 | 26 | 1. Check your code **before** creating pull request; 27 | 2. If tests are present in a project, add tests for your code; 28 | 3. Add inline documentation for your code; 29 | 4. Apply code style used throughout the project; 30 | 5. Create your pull request to `develop` branch (_pull requests to other branches are not allowed_). 31 | 32 | ### Screenshots for README 33 | 34 | * Format — [PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics) optimized with [TinyPNG](https://tinypng.com); 35 | * Width — 888px or 1776px (_x2_); 36 | * Maximum size — 1MB. 37 | 38 | ### Usage demo for README 39 | 40 | * Console size — 133 ⨯ 33; 41 | * Format — [GIF](https://en.wikipedia.org/wiki/GIF) optimized with [EZGif](https://ezgif.com/optimize); 42 | * Size — 1332px ⨯ 812px; 43 | * FPS — 12 or 24; 44 | * Maximum size — 3MB. 45 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policies and Procedures 2 | 3 | This document outlines security procedures and general policies for all 4 | ESSENTIAL KAOS projects. 5 | 6 | * [Reporting a Bug](#reporting-a-bug) 7 | * [Disclosure Policy](#disclosure-policy) 8 | 9 | ## Reporting a Bug 10 | 11 | The ESSENTIAL KAOS team and community take all security bugs in our projects 12 | very seriously. Thank you for improving the security of our project. We 13 | appreciate your efforts and responsible disclosure and will make every effort 14 | to acknowledge your contributions. 15 | 16 | Report security bugs by emailing our security team at security@essentialkaos.com. 17 | 18 | The security team will acknowledge your email within 48 hours and will send a 19 | more detailed response within 48 hours, indicating the next steps in handling 20 | your report. After the initial reply to your report, the security team will 21 | endeavor to keep you informed of the progress towards a fix and full 22 | announcement, and may ask for additional information or guidance. 23 | 24 | Report security bugs in third-party dependencies to the person or team 25 | maintaining the dependencies. 26 | 27 | ## Disclosure Policy 28 | 29 | When the security team receives a security bug report, they will assign it to a 30 | primary handler. This person will coordinate the fix and release process, 31 | involving the following steps: 32 | 33 | * Confirm the problem and determine the affected versions; 34 | * Audit code to find any similar potential problems; 35 | * Prepare fixes for all releases still under maintenance. These fixes will be 36 | released as fast as possible. 37 | -------------------------------------------------------------------------------- /ansi/examples_test.go: -------------------------------------------------------------------------------- 1 | package ansi 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | func ExampleHasCodes() { 17 | input := "Hello" 18 | fmt.Println(HasCodes(input)) 19 | 20 | input = "\033[40;38;5;82mHello\x1B[0m" 21 | fmt.Println(HasCodes(input)) 22 | 23 | // Output: 24 | // false 25 | // true 26 | } 27 | 28 | func ExampleHasCodesBytes() { 29 | input := []byte("Hello") 30 | fmt.Println(HasCodesBytes(input)) 31 | 32 | input = []byte("\033[40;38;5;82mHello\x1B[0m") 33 | fmt.Println(HasCodesBytes(input)) 34 | 35 | // Output: 36 | // false 37 | // true 38 | } 39 | 40 | func ExampleRemoveCodes() { 41 | input := "\033[40;38;5;82mHello\x1B[0m" 42 | fmt.Println(RemoveCodes(input)) 43 | // Output: 44 | // Hello 45 | } 46 | 47 | func ExampleRemoveCodesBytes() { 48 | input := []byte("\033[40;38;5;82mHello\x1B[0m") 49 | fmt.Println(string(RemoveCodesBytes(input))) 50 | // Output: 51 | // Hello 52 | } 53 | -------------------------------------------------------------------------------- /cron/fuzz.go: -------------------------------------------------------------------------------- 1 | //go:build gofuzz 2 | // +build gofuzz 3 | 4 | package cron 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | func Fuzz(data []byte) int { 14 | _, err := Parse(string(data)) 15 | 16 | if err != nil { 17 | return 0 18 | } 19 | 20 | return 1 21 | } 22 | -------------------------------------------------------------------------------- /directio/directio_darwin.go: -------------------------------------------------------------------------------- 1 | package directio 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "errors" 12 | "os" 13 | "syscall" 14 | ) 15 | 16 | // ////////////////////////////////////////////////////////////////////////////////// // 17 | 18 | const ( 19 | BLOCK_SIZE = 4096 // Minimal block size 20 | ALIGN_SIZE = 0 // Align size 21 | ) 22 | 23 | // ////////////////////////////////////////////////////////////////////////////////// // 24 | 25 | func openFile(file string, flag int, perm os.FileMode) (*os.File, error) { 26 | fd, err := os.OpenFile(file, flag, perm) 27 | 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | _, _, e := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd.Fd()), syscall.F_NOCACHE, 1) 33 | 34 | if e != 0 { 35 | fd.Close() 36 | return nil, errors.New("Can't set F_NOCACHE for given file") 37 | } 38 | 39 | return fd, nil 40 | } 41 | -------------------------------------------------------------------------------- /directio/directio_linux.go: -------------------------------------------------------------------------------- 1 | package directio 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "os" 12 | "syscall" 13 | ) 14 | 15 | // ////////////////////////////////////////////////////////////////////////////////// // 16 | 17 | const ( 18 | BLOCK_SIZE = 4096 // Minimal block size 19 | ALIGN_SIZE = 4096 // Align size 20 | ) 21 | 22 | // ////////////////////////////////////////////////////////////////////////////////// // 23 | 24 | func openFile(file string, flag int, perm os.FileMode) (*os.File, error) { 25 | return os.OpenFile(file, syscall.O_DIRECT|flag, perm) 26 | } 27 | -------------------------------------------------------------------------------- /directio/directio_stubs.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !darwin 2 | // +build !linux,!darwin 3 | 4 | // Package directio provides methods for reading/writing files with direct io 5 | package directio 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | import ( 15 | "os" 16 | ) 17 | 18 | // ////////////////////////////////////////////////////////////////////////////////// // 19 | 20 | const ( 21 | BLOCK_SIZE = 0 // ❗ Minimal block size 22 | ALIGN_SIZE = 0 // ❗ Align size 23 | ) 24 | 25 | // ////////////////////////////////////////////////////////////////////////////////// // 26 | 27 | // ❗ ReadFile read file with Direct IO without buffering data in page cache 28 | func ReadFile(file string) ([]byte, error) { 29 | panic("UNSUPPORTED") 30 | return nil, nil 31 | } 32 | 33 | // ❗ WriteFile write file with Direct IO without buffering data in page cache 34 | func WriteFile(file string, data []byte, perms os.FileMode) error { 35 | panic("UNSUPPORTED") 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /easing/back.go: -------------------------------------------------------------------------------- 1 | package easing 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "math" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | // BackIn Accelerating from zero velocity 17 | // https://easings.net/#easeInBack 18 | func BackIn(t, b, c, d float64) float64 { 19 | if t > d { 20 | return c 21 | } 22 | 23 | s := math.SqrtPi 24 | t /= d 25 | 26 | return c*t*t*((s+1)*t-s) + b 27 | } 28 | 29 | // BackOut Decelerating to zero velocity 30 | // https://easings.net/#easeOutBack 31 | func BackOut(t, b, c, d float64) float64 { 32 | if t > d { 33 | return c 34 | } 35 | 36 | s := math.SqrtPi 37 | t = t/d - 1 38 | 39 | return c*(t*t*((s+1)*t+s)+1) + b 40 | } 41 | 42 | // BackInOut Acceleration until halfway, then deceleration 43 | // https://easings.net/#easeInOutBack 44 | func BackInOut(t, b, c, d float64) float64 { 45 | if t > d { 46 | return c 47 | } 48 | 49 | s := math.SqrtPi * 1.525 50 | t /= d / 2 51 | 52 | if t < 1 { 53 | return c/2*(t*t*((s+1)*t-s)) + b 54 | } 55 | 56 | t -= 2 57 | 58 | return c/2*(t*t*((s+1)*t+s)+2) + b 59 | } 60 | -------------------------------------------------------------------------------- /easing/bounce.go: -------------------------------------------------------------------------------- 1 | package easing 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | // BounceIn accelerating from zero velocity 11 | // https://easings.net/#easeInBounce 12 | func BounceIn(t, b, c, d float64) float64 { 13 | if t > d { 14 | return c 15 | } 16 | 17 | return c - BounceOut(d-t, 0.0, c, d) + b 18 | } 19 | 20 | // BounceOut Decelerating to zero velocity 21 | // https://easings.net/#easeOutBounce 22 | func BounceOut(t, b, c, d float64) float64 { 23 | if t > d { 24 | return c 25 | } 26 | 27 | t /= d 28 | 29 | switch { 30 | case t < 1/2.75: 31 | return c*(7.5625*t*t) + b 32 | case t < 2/2.75: 33 | t -= 1.5 / 2.75 34 | return c*(7.5625*t*t+0.75) + b 35 | case t < 2.5/2.75: 36 | t -= 2.25 / 2.75 37 | return c*(7.5625*t*t+0.9375) + b 38 | } 39 | 40 | t -= 2.625 / 2.75 41 | return c*(7.5625*t*t+0.984375) + b 42 | } 43 | 44 | // BounceInOut acceleration until halfway, then deceleration 45 | // https://easings.net/#easeInOutBounce 46 | func BounceInOut(t, b, c, d float64) float64 { 47 | if t > d { 48 | return c 49 | } 50 | 51 | if t < d/2 { 52 | return BounceIn(t*2, 0.0, c, d)*0.5 + b 53 | } 54 | 55 | return BounceOut(t*2-d, 0.0, c, d)*0.5 + c*0.5 + b 56 | } 57 | -------------------------------------------------------------------------------- /easing/circ.go: -------------------------------------------------------------------------------- 1 | package easing 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "math" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | // CircIn accelerating from zero velocity 17 | // https://easings.net/#easeInCirc 18 | func CircIn(t, b, c, d float64) float64 { 19 | if t > d { 20 | return c 21 | } 22 | 23 | t /= d 24 | 25 | return -c*(math.Sqrt(1-t*t)-1) + b 26 | } 27 | 28 | // CircOut decelerating to zero velocity 29 | // https://easings.net/#easeOutCirc 30 | func CircOut(t, b, c, d float64) float64 { 31 | if t > d { 32 | return c 33 | } 34 | 35 | t /= d 36 | t-- 37 | 38 | return c*math.Sqrt(1-t*t) + b 39 | } 40 | 41 | // CircInOut acceleration until halfway, then deceleration 42 | // https://easings.net/#easeInOutCirc 43 | func CircInOut(t, b, c, d float64) float64 { 44 | if t > d { 45 | return c 46 | } 47 | 48 | t /= d / 2 49 | 50 | if t < 1 { 51 | return -c/2*(math.Sqrt(1-t*t)-1) + b 52 | } 53 | 54 | t -= 2 55 | 56 | return c/2*(math.Sqrt(1-t*t)+1) + b 57 | } 58 | -------------------------------------------------------------------------------- /easing/cubic.go: -------------------------------------------------------------------------------- 1 | package easing 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | // CubicIn accelerating from zero velocity 11 | // https://easings.net/#easeInCubic 12 | func CubicIn(t, b, c, d float64) float64 { 13 | if t > d { 14 | return c 15 | } 16 | 17 | t /= d 18 | 19 | return c*t*t*t + b 20 | } 21 | 22 | // CubicOut decelerating to zero velocity 23 | // https://easings.net/#easeOutCubic 24 | func CubicOut(t, b, c, d float64) float64 { 25 | if t > d { 26 | return c 27 | } 28 | 29 | t /= d 30 | t-- 31 | 32 | return c*(t*t*t+1) + b 33 | } 34 | 35 | // CubicInOut acceleration until halfway, then deceleration 36 | // https://easings.net/#easeInOutCubic 37 | func CubicInOut(t, b, c, d float64) float64 { 38 | if t > d { 39 | return c 40 | } 41 | 42 | t /= d / 2 43 | 44 | if t < 1 { 45 | return c/2*t*t*t + b 46 | } 47 | 48 | t -= 2 49 | 50 | return c/2*(t*t*t+2) + b 51 | } 52 | -------------------------------------------------------------------------------- /easing/ease.go: -------------------------------------------------------------------------------- 1 | // Package easing contains easing functions 2 | package easing 3 | 4 | // ////////////////////////////////////////////////////////////////////////////////// // 5 | // // 6 | // Copyright (c) 2025 ESSENTIAL KAOS // 7 | // Apache License, Version 2.0 // 8 | // // 9 | // ////////////////////////////////////////////////////////////////////////////////// // 10 | 11 | import ( 12 | "math" 13 | ) 14 | 15 | // ////////////////////////////////////////////////////////////////////////////////// // 16 | 17 | // DoublePi is 2 * Pi 18 | const DoublePi = math.Pi * 2 19 | 20 | // ////////////////////////////////////////////////////////////////////////////////// // 21 | 22 | // Easing is type for any easing function 23 | // t - current time 24 | // b - start value 25 | // c - changes in value 26 | // d - duration 27 | type Easing func(t, b, c, d float64) float64 28 | 29 | // ////////////////////////////////////////////////////////////////////////////////// // 30 | -------------------------------------------------------------------------------- /easing/expo.go: -------------------------------------------------------------------------------- 1 | package easing 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "math" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | // ExpoIn accelerating from zero velocity 17 | // https://easings.net/#easeInExpo 18 | func ExpoIn(t, b, c, d float64) float64 { 19 | if t > d { 20 | return c 21 | } 22 | 23 | return c*math.Pow(2, 10*(t/d-1)) + b 24 | } 25 | 26 | // ExpoOut decelerating to zero velocity 27 | // https://easings.net/#easeOutExpo 28 | func ExpoOut(t, b, c, d float64) float64 { 29 | if t > d { 30 | return c 31 | } 32 | 33 | return c*(-math.Pow(2, -10*t/d)+1) + b 34 | } 35 | 36 | // ExpoInOut acceleration until halfway, then deceleration 37 | // https://easings.net/#easeInOutExpo 38 | func ExpoInOut(t, b, c, d float64) float64 { 39 | if t > d { 40 | return c 41 | } 42 | 43 | t /= d / 2 44 | 45 | if t < 1 { 46 | return c/2*math.Pow(2, 10*(t-1)) + b 47 | } 48 | 49 | t-- 50 | 51 | return c/2*(-math.Pow(2, -10*t)+2) + b 52 | } 53 | -------------------------------------------------------------------------------- /easing/linear.go: -------------------------------------------------------------------------------- 1 | package easing 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | // Linear no easing and no acceleration 11 | func Linear(t, b, c, d float64) float64 { 12 | if t > d { 13 | return c 14 | } 15 | 16 | return c*t/d + b 17 | } 18 | -------------------------------------------------------------------------------- /easing/quad.go: -------------------------------------------------------------------------------- 1 | package easing 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | // QuadIn accelerating from zero velocity 11 | // https://easings.net/#easeInQuad 12 | func QuadIn(t, b, c, d float64) float64 { 13 | if t > d { 14 | return c 15 | } 16 | 17 | t /= d 18 | 19 | return c*t*t + b 20 | } 21 | 22 | // QuadOut decelerating to zero velocity 23 | // https://easings.net/#easeOutQuad 24 | func QuadOut(t, b, c, d float64) float64 { 25 | if t > d { 26 | return c 27 | } 28 | 29 | t /= d 30 | 31 | return -c*t*(t-2) + b 32 | } 33 | 34 | // QuadInOut acceleration until halfway, then deceleration 35 | // https://easings.net/#easeInOutQuad 36 | func QuadInOut(t, b, c, d float64) float64 { 37 | if t > d { 38 | return c 39 | } 40 | 41 | t /= d / 2 42 | 43 | if t < 1 { 44 | return c/2*t*t + b 45 | } 46 | 47 | t-- 48 | 49 | return -c/2*(t*(t-2)-1) + b 50 | } 51 | -------------------------------------------------------------------------------- /easing/quint.go: -------------------------------------------------------------------------------- 1 | package easing 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | // QuintIn accelerating from zero velocity 11 | // https://easings.net/#easeInQuint 12 | func QuintIn(t, b, c, d float64) float64 { 13 | if t > d { 14 | return c 15 | } 16 | 17 | t /= d 18 | return c*t*t*t*t*t + b 19 | } 20 | 21 | // QuintOut decelerating to zero velocity 22 | // https://easings.net/#easeOutQuint 23 | func QuintOut(t, b, c, d float64) float64 { 24 | if t > d { 25 | return c 26 | } 27 | 28 | t /= d 29 | t-- 30 | 31 | return c*(t*t*t*t*t+1) + b 32 | } 33 | 34 | // QuintInOut acceleration until halfway, then deceleration 35 | // https://easings.net/#easeInOutQuint 36 | func QuintInOut(t, b, c, d float64) float64 { 37 | if t > d { 38 | return c 39 | } 40 | 41 | t /= d / 2 42 | 43 | if t < 1 { 44 | return c/2*t*t*t*t*t + b 45 | } 46 | 47 | t -= 2 48 | 49 | return c/2*(t*t*t*t*t+2) + b 50 | } 51 | -------------------------------------------------------------------------------- /easing/sine.go: -------------------------------------------------------------------------------- 1 | package easing 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "math" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | // SineIn accelerating from zero velocity 17 | // https://easings.net/#easeInSine 18 | func SineIn(t, b, c, d float64) float64 { 19 | if t > d { 20 | return c 21 | } 22 | 23 | return -c*math.Cos(t/d*math.Phi) + c + b 24 | } 25 | 26 | // SineOut decelerating to zero velocity 27 | // https://easings.net/#easeOutSine 28 | func SineOut(t, b, c, d float64) float64 { 29 | if t > d { 30 | return c 31 | } 32 | 33 | return c*math.Sin(t/d*math.Phi) + b 34 | } 35 | 36 | // SineInOut acceleration until halfway, then deceleration 37 | // https://easings.net/#easeInOutSine 38 | func SineInOut(t, b, c, d float64) float64 { 39 | if t > d { 40 | return c 41 | } 42 | 43 | return -c/2*(math.Cos(math.Pi*t/d)-1) + b 44 | } 45 | -------------------------------------------------------------------------------- /ek.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | // +build !windows 3 | 4 | // Package ek is a set of auxiliary packages 5 | package ek 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | import ( 15 | "golang.org/x/crypto/bcrypt" 16 | 17 | "github.com/essentialkaos/depsy" 18 | "github.com/essentialkaos/go-linenoise/v3" 19 | ) 20 | 21 | // ////////////////////////////////////////////////////////////////////////////////// // 22 | 23 | // worthless is used as dependency fix 24 | func worthless() { 25 | linenoise.Clear() 26 | depsy.Extract(nil, false) 27 | bcrypt.Cost(nil) 28 | } 29 | -------------------------------------------------------------------------------- /ek_windows.go: -------------------------------------------------------------------------------- 1 | package ek 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "golang.org/x/crypto/bcrypt" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | // worthless is used as dependency fix 17 | func worthless() { 18 | bcrypt.Cost(nil) 19 | } 20 | -------------------------------------------------------------------------------- /emoji/emoji_test.go: -------------------------------------------------------------------------------- 1 | package emoji 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "testing" 12 | 13 | . "github.com/essentialkaos/check" 14 | ) 15 | 16 | // ////////////////////////////////////////////////////////////////////////////////// // 17 | 18 | func Test(t *testing.T) { TestingT(t) } 19 | 20 | type EmojiSuite struct{} 21 | 22 | // ////////////////////////////////////////////////////////////////////////////////// // 23 | 24 | var _ = Suite(&EmojiSuite{}) 25 | 26 | // ////////////////////////////////////////////////////////////////////////////////// // 27 | 28 | func (s *EmojiSuite) TestGet(c *C) { 29 | c.Assert(Get("100"), Equals, "💯") 30 | c.Assert(Get("_unknown_"), Equals, "") 31 | } 32 | 33 | func (s *EmojiSuite) TestGetName(c *C) { 34 | c.Assert(GetName("⚡️"), Equals, "zap") 35 | c.Assert(GetName("_unknown_"), Equals, "") 36 | } 37 | 38 | func (s *EmojiSuite) TestFind(c *C) { 39 | c.Assert(Find("bikin"), HasLen, 3) 40 | } 41 | 42 | func (s *EmojiSuite) TestEmojize(c *C) { 43 | c.Assert(Emojize("Hi :smile: emoji: :zap:!"), Equals, "Hi 😄 emoji: ⚡️!") 44 | c.Assert(Emojize("Hi :smile__1: emoji: :zap:!"), Equals, "Hi :smile__1: emoji: ⚡️!") 45 | c.Assert(Emojize(""), Equals, "") 46 | } 47 | -------------------------------------------------------------------------------- /emoji/examples_test.go: -------------------------------------------------------------------------------- 1 | package emoji 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | func ExampleGet() { 17 | fmt.Println(Get("zap")) 18 | // Output: ⚡️ 19 | } 20 | 21 | func ExampleGetName() { 22 | fmt.Println(GetName("⚡️")) 23 | // Output: zap 24 | } 25 | 26 | func ExampleFind() { 27 | fmt.Printf("%#v\n", Find("baby_")) 28 | } 29 | 30 | func ExampleEmojize() { 31 | fmt.Println(Emojize("Hi :smile:!")) 32 | // Output: Hi 😄! 33 | } 34 | -------------------------------------------------------------------------------- /env/env_stubs.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !darwin && !freebsd 2 | // +build !linux,!darwin,!freebsd 3 | 4 | // Package env provides methods for working with environment variables 5 | package env 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | // ❗ Which find full path to some app 15 | func Which(name string) string { 16 | panic("UNSUPPORTED") 17 | } 18 | 19 | // ////////////////////////////////////////////////////////////////////////////////// // 20 | -------------------------------------------------------------------------------- /env/env_unix.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | // +build !windows 3 | 4 | // Package env provides methods for working with environment variables 5 | package env 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | import "syscall" 15 | 16 | // ////////////////////////////////////////////////////////////////////////////////// // 17 | 18 | // Which find full path to some app 19 | func Which(name string) string { 20 | paths := Get().Path() 21 | 22 | for _, path := range paths { 23 | if syscall.Access(path+"/"+name, syscall.F_OK) == nil { 24 | return path + "/" + name 25 | } 26 | } 27 | 28 | return "" 29 | } 30 | -------------------------------------------------------------------------------- /env/example_test.go: -------------------------------------------------------------------------------- 1 | package env 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | func ExampleGet() { 17 | env := Get() 18 | 19 | // Print PATH environment variable 20 | fmt.Println(env["PATH"]) 21 | 22 | // Path return PATH variable as slice 23 | for i, p := range env.Path() { 24 | fmt.Printf("%d %s\n", i, p) 25 | } 26 | 27 | // You can use getters for different value formats 28 | fmt.Printf("Integer value %s = %d\n", "INT_VALUE", env.GetI("INT_VALUE")) 29 | fmt.Printf("Float value %s = %g\n", "FLOAT_VALUE", env.GetF("FLOAT_VALUE")) 30 | fmt.Printf("String value %s = %s\n", "STR_VALUE", env.GetS("STR_VALUE")) 31 | } 32 | 33 | func ExampleWhich() { 34 | echoPath := Which("echo") 35 | 36 | fmt.Printf("Full path to echo binary is %s\n", echoPath) 37 | } 38 | 39 | func ExampleVar() { 40 | v := Var("PATH") 41 | 42 | fmt.Println(v.Get()) 43 | } 44 | -------------------------------------------------------------------------------- /fmtc/fuzz.go: -------------------------------------------------------------------------------- 1 | //go:build gofuzz 2 | // +build gofuzz 3 | 4 | package fmtc 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | func Fuzz(data []byte) int { 14 | Sprint(string(data)) 15 | return 0 16 | } 17 | -------------------------------------------------------------------------------- /fmtutil/table/example_test.go: -------------------------------------------------------------------------------- 1 | package table 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | func ExampleNewTable() { 11 | t := NewTable() 12 | 13 | t.SetHeaders("id", "user", "balance") 14 | t.SetSizes(4, 12) 15 | t.SetAlignments(ALIGN_RIGHT, ALIGN_RIGHT, ALIGN_LEFT) 16 | 17 | t.Add(1, "{g}Bob{!}", 1.42) 18 | t.Add(2, "John", 73.1) 19 | t.Add(3, "Mary", 2.29) 20 | t.Separator() 21 | t.Add(4, "Bob", 6.6) 22 | t.Add(5, "Matilda", 0.0) 23 | 24 | t.Render() 25 | } 26 | -------------------------------------------------------------------------------- /fsutil/fs_user.go: -------------------------------------------------------------------------------- 1 | //go:build !unit 2 | // +build !unit 3 | 4 | // Package fsutil provides methods for working with files on POSIX compatible systems 5 | package fsutil 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | import ( 15 | "github.com/essentialkaos/ek/v13/system" 16 | ) 17 | 18 | // ////////////////////////////////////////////////////////////////////////////////// // 19 | 20 | func getCurrentUser() (*system.User, error) { 21 | return system.CurrentUser() 22 | } 23 | -------------------------------------------------------------------------------- /fsutil/fs_user_unit.go: -------------------------------------------------------------------------------- 1 | //go:build unit 2 | // +build unit 3 | 4 | // Package fsutil provides methods for working with files on POSIX compatible systems 5 | package fsutil 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | import ( 15 | "errors" 16 | "github.com/essentialkaos/ek/v13/system" 17 | ) 18 | 19 | // ////////////////////////////////////////////////////////////////////////////////// // 20 | 21 | var useFakeUser bool 22 | var getUserError bool 23 | 24 | // ////////////////////////////////////////////////////////////////////////////////// // 25 | 26 | func getCurrentUser() (*system.User, error) { 27 | if useFakeUser { 28 | return &system.User{ 29 | Name: "test", 30 | UID: 65534, 31 | GID: 65534, 32 | RealUID: 65534, 33 | RealGID: 65534, 34 | HomeDir: "/unknown", 35 | }, nil 36 | } 37 | 38 | if getUserError { 39 | return nil, errors.New("Error") 40 | } 41 | 42 | return system.CurrentUser() 43 | } 44 | -------------------------------------------------------------------------------- /fsutil/helpers_stubs.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !darwin && !freebsd 2 | // +build !linux,!darwin,!freebsd 3 | 4 | package fsutil 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | import ( 14 | "os" 15 | ) 16 | 17 | // ////////////////////////////////////////////////////////////////////////////////// // 18 | 19 | // ❗ CopyFile copies file using bufio 20 | func CopyFile(from, to string, perms ...os.FileMode) error { 21 | panic("UNSUPPORTED") 22 | return nil 23 | } 24 | 25 | // ❗ CopyAttr copies attributes (mode, ownership, timestamps) from one object 26 | // (file or directory) to another 27 | func CopyAttr(from, to string) error { 28 | panic("UNSUPPORTED") 29 | return nil 30 | } 31 | 32 | // ❗ MoveFile moves file 33 | func MoveFile(from, to string, perms ...os.FileMode) error { 34 | panic("UNSUPPORTED") 35 | return nil 36 | } 37 | 38 | // ❗ CopyDir copies directory content recursively to target directory 39 | func CopyDir(from, to string) error { 40 | panic("UNSUPPORTED") 41 | return nil 42 | } 43 | 44 | // ❗ TouchFile creates empty file 45 | func TouchFile(path string, perm os.FileMode) error { 46 | panic("UNSUPPORTED") 47 | return nil 48 | } 49 | -------------------------------------------------------------------------------- /fsutil/line_count.go: -------------------------------------------------------------------------------- 1 | package fsutil 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "bytes" 12 | "io" 13 | "os" 14 | ) 15 | 16 | // ////////////////////////////////////////////////////////////////////////////////// // 17 | 18 | // CountLines returns number of lines in given file 19 | func CountLines(file string) (int, error) { 20 | if file == "" { 21 | return 0, ErrEmptyPath 22 | } 23 | 24 | fd, err := os.OpenFile(file, os.O_RDONLY, 0) 25 | 26 | if err != nil { 27 | return 0, err 28 | } 29 | 30 | // Use 32k buffer 31 | buf := make([]byte, 32*1024) 32 | count, sep := 0, []byte{'\n'} 33 | 34 | for { 35 | c, err := fd.Read(buf) 36 | 37 | if err != nil && err != io.EOF { 38 | fd.Close() 39 | return 0, err 40 | } 41 | 42 | count += bytes.Count(buf[:c], sep) 43 | 44 | if err == io.EOF { 45 | break 46 | } 47 | } 48 | 49 | return count, fd.Close() 50 | } 51 | -------------------------------------------------------------------------------- /fsutil/walker.go: -------------------------------------------------------------------------------- 1 | //go:build linux || darwin || freebsd 2 | // +build linux darwin freebsd 3 | 4 | package fsutil 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | import ( 14 | "os" 15 | ) 16 | 17 | // ////////////////////////////////////////////////////////////////////////////////// // 18 | 19 | var dirStack []string 20 | 21 | // ////////////////////////////////////////////////////////////////////////////////// // 22 | 23 | // Push changes current working directory and add previous working directory to stack 24 | func Push(dir string) string { 25 | var wd string 26 | 27 | if dirStack == nil { 28 | wd, _ = os.Getwd() 29 | dirStack = append(dirStack, wd) 30 | } 31 | 32 | err := os.Chdir(dir) 33 | 34 | if err != nil { 35 | return "" 36 | } 37 | 38 | wd, _ = os.Getwd() 39 | 40 | dirStack = append(dirStack, wd) 41 | 42 | return wd 43 | } 44 | 45 | // Pop changes current working directory to previous in stack 46 | func Pop() string { 47 | var wd string 48 | 49 | if dirStack == nil { 50 | wd, _ = os.Getwd() 51 | dirStack = append(dirStack, wd) 52 | } 53 | 54 | dl := len(dirStack) 55 | 56 | switch dl { 57 | 58 | case 0, 1: 59 | // nop 60 | 61 | default: 62 | err := os.Chdir(dirStack[dl-2]) 63 | 64 | if err != nil { 65 | return "" 66 | } 67 | 68 | dirStack = dirStack[0 : dl-1] 69 | } 70 | 71 | wd, _ = os.Getwd() 72 | 73 | return wd 74 | } 75 | -------------------------------------------------------------------------------- /fsutil/walker_stubs.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !darwin 2 | // +build !linux,!darwin 3 | 4 | package fsutil 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | // ❗ Push changes current working directory and add previous working directory to stack 14 | func Push(dir string) string { 15 | panic("UNSUPPORTED") 16 | return "" 17 | } 18 | 19 | // ❗ Pop changes current working directory to previous in stack 20 | func Pop() string { 21 | panic("UNSUPPORTED") 22 | return "" 23 | } 24 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/essentialkaos/ek/v13 2 | 3 | go 1.23.6 4 | 5 | require ( 6 | github.com/essentialkaos/check v1.4.1 7 | github.com/essentialkaos/depsy v1.3.1 8 | github.com/essentialkaos/go-linenoise/v3 v3.7.0 9 | golang.org/x/crypto v0.38.0 10 | golang.org/x/sys v0.33.0 11 | ) 12 | 13 | require ( 14 | github.com/kr/pretty v0.3.1 // indirect 15 | github.com/kr/text v0.2.0 // indirect 16 | github.com/rogpeppe/go-internal v1.14.1 // indirect 17 | ) 18 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 2 | github.com/essentialkaos/check v1.4.1 h1:SuxXzrbokPGTPWxGRnzy0hXvtb44mtVrdNxgPa1s4c8= 3 | github.com/essentialkaos/check v1.4.1/go.mod h1:xQOYwFvnxfVZyt5Qvjoa1SxcRqu5VyP77pgALr3iu+M= 4 | github.com/essentialkaos/depsy v1.3.1 h1:00k9QcMsdPM4IzDaEFHsTHBD/zoM0oxtB5+dMUwbQa8= 5 | github.com/essentialkaos/depsy v1.3.1/go.mod h1:B5+7Jhv2a2RacOAxIKU2OeJp9QfZjwIpEEPI5X7auWM= 6 | github.com/essentialkaos/go-linenoise/v3 v3.7.0 h1:a/DzU6GFBmrKJxNAzaYbLGN6yFnIMIFaWxvSWmeCEp0= 7 | github.com/essentialkaos/go-linenoise/v3 v3.7.0/go.mod h1:IhOWE0rvvu3aPmGko/C4SoZdhbko9eTuwe5yyw7/uQ8= 8 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 9 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 10 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 11 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 12 | github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= 13 | github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= 14 | github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= 15 | github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= 16 | golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= 17 | golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= 18 | golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= 19 | golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 20 | -------------------------------------------------------------------------------- /hash/filehash.go: -------------------------------------------------------------------------------- 1 | // Package hash contains different hash algorithms and utilities 2 | // 3 | // Deprecated: Use package hashutil instead 4 | package hash 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | import ( 14 | "crypto/sha256" 15 | 16 | "github.com/essentialkaos/ek/v13/hashutil" 17 | ) 18 | 19 | // ////////////////////////////////////////////////////////////////////////////////// // 20 | 21 | // FileHash generates an SHA-256 hash for a given file 22 | // 23 | // Deprecated: Use package hashutil instead 24 | func FileHash(file string) string { 25 | return hashutil.File(file, sha256.New()) 26 | } 27 | -------------------------------------------------------------------------------- /initsystem/initsystem_darwin_test.go: -------------------------------------------------------------------------------- 1 | package initsystem 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "testing" 12 | 13 | . "github.com/essentialkaos/check" 14 | ) 15 | 16 | // ////////////////////////////////////////////////////////////////////////////////// // 17 | 18 | func Test(t *testing.T) { TestingT(t) } 19 | 20 | type InitSuite struct{} 21 | 22 | // ////////////////////////////////////////////////////////////////////////////////// // 23 | 24 | var _ = Suite(&InitSuite{}) 25 | 26 | // ////////////////////////////////////////////////////////////////////////////////// // 27 | 28 | func (s *InitSuite) TestLaunchdIsPresent(c *C) { 29 | c.Assert(IsPresent("com.apple.unknown"), Equals, false) 30 | c.Assert(IsPresent("com.apple.homed"), Equals, true) 31 | c.Assert(IsPresent("com.apple.cloudphotod"), Equals, true) 32 | } 33 | 34 | func (s *InitSuite) TestLaunchdIsWorks(c *C) { 35 | isWorks, err := IsWorks("com.apple.homed") 36 | 37 | c.Assert(err, IsNil) 38 | c.Assert(isWorks, Equals, true) 39 | 40 | isWorks, err = IsWorks("com.apple.cloudphotod") 41 | 42 | c.Assert(err, IsNil) 43 | c.Assert(isWorks, Equals, false) 44 | } 45 | -------------------------------------------------------------------------------- /initsystem/initsystem_stubs.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !darwin 2 | // +build !linux,!darwin 3 | 4 | // Package initsystem provides methods for working with different init systems 5 | package initsystem 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | // ❗ SysV returns true if SysV is used on system 15 | func SysV() bool { 16 | panic("UNSUPPORTED") 17 | } 18 | 19 | // ❗ Upstart returns true if Upstart is used on system 20 | func Upstart() bool { 21 | panic("UNSUPPORTED") 22 | } 23 | 24 | // ❗ Systemd returns true if Systemd is used on system 25 | func Systemd() bool { 26 | panic("UNSUPPORTED") 27 | } 28 | 29 | // ❗ Launchd returns true if Launchd is used on the system 30 | func Launchd() bool { 31 | panic("UNSUPPORTED") 32 | } 33 | 34 | // ❗ IsPresent returns true if service is present in any init system 35 | func IsPresent(name string) bool { 36 | panic("UNSUPPORTED") 37 | } 38 | 39 | // ❗ IsWorks returns service state 40 | func IsWorks(name string) (bool, error) { 41 | panic("UNSUPPORTED") 42 | } 43 | 44 | // ❗ IsEnabled returns true if auto start enabled for given service 45 | func IsEnabled(name string) (bool, error) { 46 | panic("UNSUPPORTED") 47 | } 48 | -------------------------------------------------------------------------------- /initsystem/sdnotify/example_test.go: -------------------------------------------------------------------------------- 1 | package sdnotify 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | func ExampleConnect() { 11 | err := Connect() 12 | 13 | if err != nil { 14 | panic(err.Error()) 15 | } 16 | 17 | Status("Loading data %d%%", 50) 18 | Ready() 19 | } 20 | -------------------------------------------------------------------------------- /initsystem/sdnotify/sdnotify_stubs.go: -------------------------------------------------------------------------------- 1 | //go:build !linux 2 | // +build !linux 3 | 4 | // Package sdnotify provides methods for sending notifications to systemd 5 | package sdnotify 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | // ❗ Connect connects systemd to socket 17 | func Connect() error { 18 | panic("UNSUPPORTED") 19 | } 20 | 21 | // ❗ Notify sends provided message to systemd 22 | func Notify(msg string) error { 23 | panic("UNSUPPORTED") 24 | } 25 | 26 | // ❗ Ready sends READY message to systemd 27 | func Ready() error { 28 | panic("UNSUPPORTED") 29 | } 30 | 31 | // ❗ Reloading sends RELOADING message to systemd 32 | func Reloading() error { 33 | panic("UNSUPPORTED") 34 | } 35 | 36 | // ❗ Stopping sends STOPPING message to systemd 37 | func Stopping() error { 38 | panic("UNSUPPORTED") 39 | } 40 | 41 | // ❗ MainPID sends MAINPID message with PID to systemd 42 | func MainPID(pid int) error { 43 | panic("UNSUPPORTED") 44 | } 45 | 46 | // ❗ ExtendTimeout sends EXTEND_TIMEOUT_USEC message to systemd 47 | func ExtendTimeout(sec float64) error { 48 | panic("UNSUPPORTED") 49 | } 50 | 51 | // ❗ Status sends status message to systemd 52 | func Status(format string, a ...any) error { 53 | panic("UNSUPPORTED") 54 | } 55 | -------------------------------------------------------------------------------- /jsonutil/example_test.go: -------------------------------------------------------------------------------- 1 | package jsonutil 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | func ExampleWrite() { 17 | var data = make(map[string]int) 18 | 19 | data["john"] = 100 20 | data["bob"] = 300 21 | 22 | err := Write("/path/to/file.json", data, 0600) 23 | 24 | if err != nil { 25 | fmt.Printf("Error: %v\n", err) 26 | } 27 | } 28 | 29 | func ExampleRead() { 30 | var data = make(map[string]int) 31 | 32 | err := Read("/path/to/file.json", data) 33 | 34 | if err != nil { 35 | fmt.Printf("Error: %v\n", err) 36 | } 37 | } 38 | 39 | func ExampleWriteGz() { 40 | var data = make(map[string]int) 41 | 42 | data["john"] = 100 43 | data["bob"] = 300 44 | 45 | err := WriteGz("/path/to/file.gz", data, 0600) 46 | 47 | if err != nil { 48 | fmt.Printf("Error: %v\n", err) 49 | } 50 | } 51 | 52 | func ExampleReadGz() { 53 | var data = make(map[string]int) 54 | 55 | err := ReadGz("/path/to/file.gz", data) 56 | 57 | if err != nil { 58 | fmt.Printf("Error: %v\n", err) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /knf/fuzz.go: -------------------------------------------------------------------------------- 1 | //go:build gofuzz 2 | // +build gofuzz 3 | 4 | package knf 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | import ( 14 | "bytes" 15 | ) 16 | 17 | // ////////////////////////////////////////////////////////////////////////////////// // 18 | 19 | func Fuzz(data []byte) int { 20 | _, err := readData(bytes.NewReader(data)) 21 | 22 | if err != nil { 23 | return 0 24 | } 25 | 26 | return 1 27 | } 28 | -------------------------------------------------------------------------------- /knf/validators/cron/validators.go: -------------------------------------------------------------------------------- 1 | // Package regexp provides KNF validators for cron expressions 2 | package cron 3 | 4 | // ////////////////////////////////////////////////////////////////////////////////// // 5 | // // 6 | // Copyright (c) 2025 ESSENTIAL KAOS // 7 | // Apache License, Version 2.0 // 8 | // // 9 | // ////////////////////////////////////////////////////////////////////////////////// // 10 | 11 | import ( 12 | "fmt" 13 | 14 | "github.com/essentialkaos/ek/v13/cron" 15 | "github.com/essentialkaos/ek/v13/knf" 16 | ) 17 | 18 | // ////////////////////////////////////////////////////////////////////////////////// // 19 | 20 | var ( 21 | // Expression returns an error if configuration property contains invalid cron 22 | // expression 23 | Expression = validateCronExpression 24 | ) 25 | 26 | // ////////////////////////////////////////////////////////////////////////////////// // 27 | 28 | func validateCronExpression(config knf.IConfig, prop string, value any) error { 29 | v := config.GetS(prop) 30 | 31 | if v == "" { 32 | return nil 33 | } 34 | 35 | _, err := cron.Parse(v) 36 | 37 | if err != nil { 38 | return fmt.Errorf("Property %s contains invalid cron expression: %w", prop, err) 39 | } 40 | 41 | return nil 42 | } 43 | 44 | // ////////////////////////////////////////////////////////////////////////////////// // 45 | -------------------------------------------------------------------------------- /knf/validators/system/validators.go: -------------------------------------------------------------------------------- 1 | // Package system provides KNF validators for checking system items (user, groups, 2 | // network interfaces) 3 | package system 4 | 5 | // ////////////////////////////////////////////////////////////////////////////////// // 6 | // // 7 | // Copyright (c) 2025 ESSENTIAL KAOS // 8 | // Apache License, Version 2.0 // 9 | // // 10 | // ////////////////////////////////////////////////////////////////////////////////// // 11 | 12 | import ( 13 | "fmt" 14 | 15 | "github.com/essentialkaos/ek/v13/knf" 16 | "github.com/essentialkaos/ek/v13/system" 17 | ) 18 | 19 | // ////////////////////////////////////////////////////////////////////////////////// // 20 | 21 | var ( 22 | // User returns error if configuration property contains name of user or UID which not 23 | // present on the system 24 | User = validateUser 25 | 26 | // Group returns error if configuration property contains name of group or GID which 27 | // not present on the system 28 | Group = validateGroup 29 | ) 30 | 31 | // ////////////////////////////////////////////////////////////////////////////////// // 32 | 33 | func validateUser(config knf.IConfig, prop string, value any) error { 34 | v := config.GetS(prop) 35 | 36 | if v != "" && !system.IsUserExist(v) { 37 | return fmt.Errorf("User %q is not present on the system", v) 38 | } 39 | 40 | return nil 41 | } 42 | 43 | func validateGroup(config knf.IConfig, prop string, value any) error { 44 | v := config.GetS(prop) 45 | 46 | if v != "" && !system.IsGroupExist(v) { 47 | return fmt.Errorf("Group %q is not present on the system", v) 48 | } 49 | 50 | return nil 51 | } 52 | -------------------------------------------------------------------------------- /knf/validators/system/validators_linux.go: -------------------------------------------------------------------------------- 1 | // Package system provides KNF validators for checking system items (user, groups, 2 | // network interfaces) 3 | package system 4 | 5 | // ////////////////////////////////////////////////////////////////////////////////// // 6 | // // 7 | // Copyright (c) 2025 ESSENTIAL KAOS // 8 | // Apache License, Version 2.0 // 9 | // // 10 | // ////////////////////////////////////////////////////////////////////////////////// // 11 | 12 | import ( 13 | "fmt" 14 | 15 | "github.com/essentialkaos/ek/v13/knf" 16 | "github.com/essentialkaos/ek/v13/system" 17 | ) 18 | 19 | // ////////////////////////////////////////////////////////////////////////////////// // 20 | 21 | var ( 22 | // Interface returns error if configuration property contains name of network 23 | // interface which not present on the system 24 | Interface = validateInterface 25 | ) 26 | 27 | // ////////////////////////////////////////////////////////////////////////////////// // 28 | 29 | func validateInterface(config knf.IConfig, prop string, value any) error { 30 | v := config.GetS(prop) 31 | 32 | if v == "" { 33 | return nil 34 | } 35 | 36 | stats, err := system.GetInterfacesStats() 37 | 38 | if err != nil { 39 | return fmt.Errorf("Can't get interfaces info: %v", err) 40 | } 41 | 42 | _, isPresent := stats[v] 43 | 44 | if !isPresent { 45 | return fmt.Errorf("Interface %q is not present on the system", v) 46 | } 47 | 48 | return nil 49 | } 50 | -------------------------------------------------------------------------------- /knf/validators/system/validators_linux_test.go: -------------------------------------------------------------------------------- 1 | package system 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "github.com/essentialkaos/ek/v13/knf" 12 | 13 | . "github.com/essentialkaos/check" 14 | ) 15 | 16 | // ////////////////////////////////////////////////////////////////////////////////// // 17 | 18 | func (s *ValidatorSuite) TestInterfaceValidator(c *C) { 19 | configFile := createConfig(c, _CONFIG_DATA) 20 | 21 | err := knf.Global(configFile) 22 | c.Assert(err, IsNil) 23 | 24 | errs := knf.Validate(knf.Validators{ 25 | {"interface:test0", Interface, nil}, 26 | {"interface:test1", Interface, nil}, 27 | }) 28 | 29 | c.Assert(errs, HasLen, 0) 30 | 31 | errs = knf.Validate(knf.Validators{ 32 | {"interface:test2", Interface, nil}, 33 | }) 34 | 35 | c.Assert(errs, HasLen, 1) 36 | c.Assert(errs[0].Error(), Equals, `Interface "abc" is not present on the system`) 37 | } 38 | -------------------------------------------------------------------------------- /lock/examples_test.go: -------------------------------------------------------------------------------- 1 | package lock 2 | 3 | import "time" 4 | 5 | // ////////////////////////////////////////////////////////////////////////////////// // 6 | // // 7 | // Copyright (c) 2025 ESSENTIAL KAOS // 8 | // Apache License, Version 2.0 // 9 | // // 10 | // ////////////////////////////////////////////////////////////////////////////////// // 11 | 12 | func ExampleCreate() { 13 | err := Create("my_app") 14 | 15 | if err != nil { 16 | panic(err.Error()) 17 | } 18 | 19 | // do some stuff 20 | 21 | err = Remove("my_app") 22 | 23 | if err != nil { 24 | panic(err.Error()) 25 | } 26 | } 27 | 28 | func ExampleRemove() { 29 | err := Create("my_app") 30 | 31 | if err != nil { 32 | panic(err.Error()) 33 | } 34 | 35 | // do your stuff 36 | 37 | err = Remove("my_app") 38 | 39 | if err != nil { 40 | panic(err.Error()) 41 | } 42 | } 43 | 44 | func ExampleHas() { 45 | if Has("my_app") { 46 | panic("Can't start application due to lock file") 47 | } 48 | } 49 | 50 | func ExampleWait() { 51 | ok := Wait("my_app", time.Now().Add(time.Minute)) 52 | 53 | if !ok { 54 | panic("Can't start application due to lock file") 55 | } 56 | 57 | // do your stuff 58 | } 59 | 60 | func ExampleIsExpired() { 61 | if Has("my_app") { 62 | if IsExpired("my_app", time.Hour) { 63 | // looks like lock file was created long time ago, so delete it 64 | Remove("my_app") 65 | } else { 66 | panic("Can't start application due to lock file") 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lock/lock_darwin.go: -------------------------------------------------------------------------------- 1 | package lock 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | // Dir is a path to directory with lock files 11 | var Dir = "/var/tmp" 12 | 13 | // ////////////////////////////////////////////////////////////////////////////////// // 14 | -------------------------------------------------------------------------------- /lock/lock_linux.go: -------------------------------------------------------------------------------- 1 | package lock 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | // Dir is a path to directory with lock files 11 | var Dir = "/var/tmp" 12 | 13 | // ////////////////////////////////////////////////////////////////////////////////// // 14 | -------------------------------------------------------------------------------- /lock/lock_stubs.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !darwin 2 | // +build !linux,!darwin 3 | 4 | // Package lock provides methods for working with lock files 5 | package lock 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | import ( 15 | "time" 16 | ) 17 | 18 | // ////////////////////////////////////////////////////////////////////////////////// // 19 | 20 | // Dir is a path to directory with lock files 21 | var Dir = "" 22 | 23 | // ////////////////////////////////////////////////////////////////////////////////// // 24 | 25 | // ❗ Create creates new lock file 26 | func Create(name string) error { 27 | panic("UNSUPPORTED") 28 | return nil 29 | } 30 | 31 | // ❗ Remove deletes lock file 32 | func Remove(name string) error { 33 | panic("UNSUPPORTED") 34 | return nil 35 | } 36 | 37 | // ❗ Has returns true if lock file exists 38 | func Has(name string) bool { 39 | panic("UNSUPPORTED") 40 | return false 41 | } 42 | 43 | // ❗ Expired returns true if lock file reached TTL 44 | func Expired(name string, ttl time.Duration) bool { 45 | panic("UNSUPPORTED") 46 | return false 47 | } 48 | 49 | // ////////////////////////////////////////////////////////////////////////////////// // 50 | -------------------------------------------------------------------------------- /log/nil.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | // NilLogger is Logger (ILogger) compatible logger that doesn't print anything 11 | type NilLogger struct{} 12 | 13 | // ////////////////////////////////////////////////////////////////////////////////// // 14 | 15 | // Aux do nothing 16 | func (l *NilLogger) Aux(f string, a ...any) error { 17 | return nil 18 | } 19 | 20 | // Debug do nothing 21 | func (l *NilLogger) Debug(f string, a ...any) error { 22 | return nil 23 | } 24 | 25 | // Info do nothing 26 | func (l *NilLogger) Info(f string, a ...any) error { 27 | return nil 28 | } 29 | 30 | // Warn do nothing 31 | func (l *NilLogger) Warn(f string, a ...any) error { 32 | return nil 33 | } 34 | 35 | // Error do nothing 36 | func (l *NilLogger) Error(f string, a ...any) error { 37 | return nil 38 | } 39 | 40 | // Crit do nothing 41 | func (l *NilLogger) Crit(f string, a ...any) error { 42 | return nil 43 | } 44 | 45 | // Print do nothing 46 | func (l *NilLogger) Print(level uint8, f string, a ...any) error { 47 | return nil 48 | } 49 | -------------------------------------------------------------------------------- /lscolors/examples_test.go: -------------------------------------------------------------------------------- 1 | package lscolors 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | func ExampleGetColor() { 17 | file := "myfile.txt" 18 | dir := "/home/john" 19 | 20 | colorSeq := GetColor(file) 21 | 22 | fmt.Printf( 23 | "%s/"+colorSeq+"%s"+GetColor(RESET)+"\n", 24 | dir, file, 25 | ) 26 | } 27 | 28 | func ExampleColorize() { 29 | file := "myfile.txt" 30 | fmt.Println(Colorize(file)) 31 | } 32 | 33 | func ExampleColorizePath() { 34 | path := "/home/john/myfile.txt" 35 | fmt.Println(ColorizePath(path)) 36 | } 37 | -------------------------------------------------------------------------------- /netutil/example_test.go: -------------------------------------------------------------------------------- 1 | package netutil 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | func ExampleGetIP() { 17 | ip := GetIP() 18 | 19 | if ip != "" { 20 | fmt.Printf("Your IPv4 is %s\n", ip) 21 | } 22 | } 23 | 24 | func ExampleGetIP6() { 25 | ip := GetIP6() 26 | 27 | if ip != "" { 28 | fmt.Printf("Your IPv6 is %s\n", ip) 29 | } 30 | } 31 | 32 | func ExampleGetAllIP() { 33 | ips := GetAllIP() 34 | 35 | if len(ips) > 0 { 36 | fmt.Printf("All IPv4: %v\n", ips) 37 | } 38 | } 39 | 40 | func ExampleGetAllIP6() { 41 | ips := GetAllIP6() 42 | 43 | if len(ips) > 0 { 44 | fmt.Printf("All IPv6: %v\n", ips) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /netutil/netutil_darwin.go: -------------------------------------------------------------------------------- 1 | package netutil 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | func getDefaultRouteInterface() string { 11 | return "" 12 | } 13 | -------------------------------------------------------------------------------- /netutil/netutil_darwin_test.go: -------------------------------------------------------------------------------- 1 | package netutil 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "os" 12 | "testing" 13 | 14 | . "github.com/essentialkaos/check" 15 | ) 16 | 17 | // ////////////////////////////////////////////////////////////////////////////////// // 18 | 19 | func Test(t *testing.T) { TestingT(t) } 20 | 21 | type NetUtilSuite struct{} 22 | 23 | // ////////////////////////////////////////////////////////////////////////////////// // 24 | 25 | var _ = Suite(&NetUtilSuite{}) 26 | 27 | // ////////////////////////////////////////////////////////////////////////////////// // 28 | 29 | func (s *NetUtilSuite) TestGetIP(c *C) { 30 | c.Assert(GetIP(), Not(Equals), "") 31 | } 32 | 33 | func (s *NetUtilSuite) TestGetIP6(c *C) { 34 | if os.Getenv("CI") == "" { 35 | c.Assert(GetIP6(), Not(Equals), "") 36 | } 37 | } 38 | 39 | func (s *NetUtilSuite) TestGetAllIP(c *C) { 40 | c.Assert(GetAllIP(), Not(HasLen), 0) 41 | } 42 | 43 | func (s *NetUtilSuite) TestGetAllIP6(c *C) { 44 | if os.Getenv("CI") == "" { 45 | c.Assert(GetAllIP6(), Not(HasLen), 0) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /netutil/netutil_linux.go: -------------------------------------------------------------------------------- 1 | package netutil 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "bufio" 12 | "os" 13 | 14 | "github.com/essentialkaos/ek/v13/strutil" 15 | ) 16 | 17 | // ////////////////////////////////////////////////////////////////////////////////// // 18 | 19 | // Path to file with routes info in procfs 20 | var procRouteFile = "/proc/net/route" 21 | 22 | // ////////////////////////////////////////////////////////////////////////////////// // 23 | 24 | func getDefaultRouteInterface() string { 25 | fd, err := os.OpenFile(procRouteFile, os.O_RDONLY, 0) 26 | 27 | if err != nil { 28 | return "" 29 | } 30 | 31 | defer fd.Close() 32 | 33 | r := bufio.NewReader(fd) 34 | s := bufio.NewScanner(r) 35 | 36 | var header bool 37 | 38 | for s.Scan() { 39 | if !header { 40 | header = true 41 | continue 42 | } 43 | 44 | if strutil.ReadField(s.Text(), 1, true) == "00000000" { 45 | return strutil.ReadField(s.Text(), 0, true) 46 | } 47 | } 48 | 49 | return "" 50 | } 51 | -------------------------------------------------------------------------------- /netutil/netutil_stubs.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !darwin 2 | // +build !linux,!darwin 3 | 4 | // Package netutil provides methods for working with network 5 | package netutil 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | // ❗ GetIP returns main IPv4 address 15 | func GetIP() string { 16 | panic("UNSUPPORTED") 17 | return "" 18 | } 19 | 20 | // ❗ GetIP6 returns main IPv6 address 21 | func GetIP6() string { 22 | panic("UNSUPPORTED") 23 | return "" 24 | } 25 | 26 | // ❗ GetAllIP returns all IPv4 addresses 27 | func GetAllIP() []string { 28 | panic("UNSUPPORTED") 29 | return nil 30 | } 31 | 32 | // ❗ GetAllIP6 returns all IPv6 addresses 33 | func GetAllIP6() []string { 34 | panic("UNSUPPORTED") 35 | return nil 36 | } 37 | -------------------------------------------------------------------------------- /pager/example_test.go: -------------------------------------------------------------------------------- 1 | package pager 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | func ExampleSetup() { 11 | // Use pager from PAGER env var or default (more -f) 12 | Setup() 13 | 14 | // Or provide specific command. 15 | Setup("less -MQR") 16 | 17 | // Complete must be called at the end of the program work. You can call it with defer 18 | // in your main function. 19 | defer Complete() 20 | } 21 | -------------------------------------------------------------------------------- /pager/pager_stubs.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !darwin && !freebsd 2 | // +build !linux,!darwin,!freebsd 3 | 4 | // Package pager provides methods for pager setup (more/less) 5 | package pager 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | import "errors" 15 | 16 | // ////////////////////////////////////////////////////////////////////////////////// // 17 | 18 | var ( 19 | ErrAlreadySet = errors.New("Pager already set") 20 | ErrNoPager = errors.New("There is no pager on the system") 21 | ErrStdinPipe = errors.New("Can't get pager stdin") 22 | ) 23 | 24 | // AllowEnv is a flag that allows to user to define pager binary using PAGER environment 25 | // variable 26 | var AllowEnv bool 27 | 28 | // ////////////////////////////////////////////////////////////////////////////////// // 29 | 30 | // ❗ Setup set up pager for work. After calling this method, any data sent to Stdout and 31 | // Stderr (using fmt, fmtc, or terminal packages) will go to the pager. 32 | func Setup(pager ...string) error { 33 | return nil 34 | } 35 | 36 | // ❗ Complete finishes output redirect to pager 37 | func Complete() { 38 | return 39 | } 40 | -------------------------------------------------------------------------------- /path/path_posix.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | // +build !windows 3 | 4 | package path 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | import "strings" 14 | 15 | // ////////////////////////////////////////////////////////////////////////////////// // 16 | 17 | // unsafePaths is slice with unsafe paths 18 | var unsafePaths = []string{ 19 | "/lost+found", 20 | "/bin", 21 | "/boot", 22 | "/etc", 23 | "/dev", 24 | "/lib", 25 | "/lib64", 26 | "/proc", 27 | "/root", 28 | "/sbin", 29 | "/selinux", 30 | "/sys", 31 | "/usr/bin", 32 | "/usr/lib", 33 | "/usr/lib64", 34 | "/usr/libexec", 35 | "/usr/sbin", 36 | "/usr/include", 37 | "/var/cache", 38 | "/var/db", 39 | "/var/lib", 40 | } 41 | 42 | // ////////////////////////////////////////////////////////////////////////////////// // 43 | 44 | // DirN returns first N elements of path 45 | func DirN(path string, n int) string { 46 | if strings.Count(path, pathSeparator) < 2 || n == 0 { 47 | return path 48 | } 49 | 50 | if n > 0 { 51 | return dirNRight(path, n) 52 | } 53 | 54 | return dirNLeft(path, n*-1) 55 | } 56 | 57 | // ////////////////////////////////////////////////////////////////////////////////// // 58 | 59 | func isSafePath(path string) bool { 60 | for _, p := range unsafePaths { 61 | if strings.HasPrefix(path, p) { 62 | return false 63 | } 64 | } 65 | 66 | return true 67 | } 68 | 69 | // ////////////////////////////////////////////////////////////////////////////////// // 70 | -------------------------------------------------------------------------------- /path/path_test.go: -------------------------------------------------------------------------------- 1 | package path 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "testing" 12 | 13 | . "github.com/essentialkaos/check" 14 | ) 15 | 16 | // ////////////////////////////////////////////////////////////////////////////////// // 17 | 18 | func Test(t *testing.T) { TestingT(t) } 19 | 20 | type PathUtilSuite struct{} 21 | 22 | // ////////////////////////////////////////////////////////////////////////////////// // 23 | 24 | var _ = Suite(&PathUtilSuite{}) 25 | 26 | // ////////////////////////////////////////////////////////////////////////////////// // 27 | -------------------------------------------------------------------------------- /path/path_windows.go: -------------------------------------------------------------------------------- 1 | package path 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import "strings" 11 | 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | // unsafePaths is slice with unsafe paths 15 | var unsafePaths = []string{ 16 | `\Recovery`, 17 | `\Windows`, 18 | `\ProgramData`, 19 | `\Program Files (x86)`, 20 | `\Program Files`, 21 | } 22 | 23 | // ////////////////////////////////////////////////////////////////////////////////// // 24 | 25 | // DirN returns first N elements of path 26 | func DirN(path string, n int) string { 27 | if strings.Count(path, pathSeparator) < 2 || n == 0 { 28 | return path 29 | } 30 | 31 | disk, p, ok := strings.Cut(path, ":") 32 | 33 | if !ok { 34 | p = path 35 | disk = "" 36 | } else { 37 | disk += ":" 38 | } 39 | 40 | if n > 0 { 41 | return disk + dirNRight(p, n) 42 | } 43 | 44 | return disk + dirNLeft(p, n*-1) 45 | } 46 | 47 | // ////////////////////////////////////////////////////////////////////////////////// // 48 | 49 | func isSafePath(path string) bool { 50 | for _, p := range unsafePaths { 51 | if strings.ContainsRune(path, ':') { 52 | _, path, _ = strings.Cut(path, ":") 53 | } 54 | 55 | if strings.HasPrefix(path, p) { 56 | return false 57 | } 58 | } 59 | 60 | return true 61 | } 62 | -------------------------------------------------------------------------------- /pid/example_test.go: -------------------------------------------------------------------------------- 1 | package pid 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | func ExampleCreate() { 17 | // You can set default directory for pid files 18 | Dir = "/home/user/my-pids" 19 | 20 | err := Create("servicename") 21 | 22 | if err != nil { 23 | fmt.Printf("Error: %v\n", err) 24 | } 25 | 26 | fmt.Println("PID file created!") 27 | } 28 | 29 | func ExampleRemove() { 30 | err := Remove("servicename") 31 | 32 | if err != nil { 33 | fmt.Printf("Error: %v\n", err) 34 | } 35 | 36 | fmt.Println("PID file removed!") 37 | } 38 | 39 | func ExampleGet() { 40 | pid := Get("servicename") 41 | 42 | if pid == -1 { 43 | fmt.Println("Can't read PID from PID file") 44 | } 45 | 46 | fmt.Printf("PID is %d\n", pid) 47 | } 48 | 49 | func ExampleRead() { 50 | pid := Read("/var/run/httpd.pid") 51 | 52 | if pid == -1 { 53 | fmt.Println("Can't read PID from PID file") 54 | } 55 | 56 | fmt.Printf("PID is %d\n", pid) 57 | } 58 | 59 | func ExampleIsProcessWorks() { 60 | pid := 1234 61 | 62 | if IsProcessWorks(pid) { 63 | fmt.Printf("Process with PID %d is works\n", pid) 64 | } else { 65 | fmt.Printf("Process with PID %d isn't working\n", pid) 66 | } 67 | } 68 | 69 | func ExampleIsWorks() { 70 | if IsWorks("servicename") { 71 | fmt.Println("Process is works") 72 | } else { 73 | fmt.Println("Process isn't working") 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /pid/pid_darwin.go: -------------------------------------------------------------------------------- 1 | package pid 2 | 3 | import ( 4 | "os" 5 | "syscall" 6 | ) 7 | 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | // // 10 | // Copyright (c) 2025 ESSENTIAL KAOS // 11 | // Apache License, Version 2.0 // 12 | // // 13 | // ////////////////////////////////////////////////////////////////////////////////// // 14 | 15 | // IsWorks returns true if process with PID from PID file is works 16 | func IsWorks(name string) bool { 17 | pid := Get(name) 18 | 19 | if pid == -1 { 20 | return false 21 | } 22 | 23 | return IsProcessWorks(pid) 24 | } 25 | 26 | // IsProcessWorks returns true if process with given PID is works 27 | func IsProcessWorks(pid int) bool { 28 | // On Unix systems, FindProcess always succeeds and returns a Process 29 | // for the given pid, regardless of whether the process exists. 30 | pr, _ := os.FindProcess(pid) 31 | return pr.Signal(syscall.Signal(0)) == nil 32 | } 33 | -------------------------------------------------------------------------------- /pid/pid_darwin_test.go: -------------------------------------------------------------------------------- 1 | //go:build darwin 2 | // +build darwin 3 | 4 | package pid 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | import ( 14 | "os" 15 | 16 | . "github.com/essentialkaos/check" 17 | ) 18 | 19 | // ////////////////////////////////////////////////////////////////////////////////// // 20 | 21 | func (s *PidSuite) TestIsWorks(c *C) { 22 | Dir = s.Dir 23 | 24 | err := Create("test") 25 | 26 | c.Assert(err, IsNil) 27 | 28 | c.Assert(IsWorks("test"), Equals, true) 29 | 30 | Remove("test") 31 | 32 | c.Assert(IsWorks("test"), Equals, false) 33 | 34 | // Write fake pid to pid file 35 | os.WriteFile(s.Dir+"/test.pid", []byte("999999\n"), 0644) 36 | 37 | c.Assert(IsWorks("test"), Equals, false) 38 | } 39 | 40 | func (s *PidSuite) TestIsProcessWorks(c *C) { 41 | c.Assert(IsProcessWorks(os.Getpid()), Equals, true) 42 | c.Assert(IsProcessWorks(999999), Equals, false) 43 | } 44 | -------------------------------------------------------------------------------- /pid/pid_freebsd.go: -------------------------------------------------------------------------------- 1 | package pid 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "os/exec" 12 | "strconv" 13 | ) 14 | 15 | // ////////////////////////////////////////////////////////////////////////////////// // 16 | 17 | // IsWorks returns true if process with PID from PID file is works 18 | func IsWorks(name string) bool { 19 | pid := Get(name) 20 | 21 | if pid == -1 { 22 | return false 23 | } 24 | 25 | return IsProcessWorks(pid) 26 | } 27 | 28 | // IsProcessWorks returns true if process with given PID is works 29 | func IsProcessWorks(pid int) bool { 30 | return exec.Command("/usr/bin/procstat", strconv.Itoa(pid)).Run() == nil 31 | } 32 | -------------------------------------------------------------------------------- /pid/pid_linux.go: -------------------------------------------------------------------------------- 1 | package pid 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | "os" 13 | "syscall" 14 | 15 | "github.com/essentialkaos/ek/v13/fsutil" 16 | ) 17 | 18 | // ////////////////////////////////////////////////////////////////////////////////// // 19 | 20 | // procfsDir is path to procfs directory 21 | var procfsDir = "/proc" 22 | 23 | // ////////////////////////////////////////////////////////////////////////////////// // 24 | 25 | // IsWorks returns true if process with PID from PID file is works 26 | func IsWorks(name string) bool { 27 | pid := Get(name) 28 | 29 | if pid == -1 { 30 | return false 31 | } 32 | 33 | if !fsutil.IsExist(fmt.Sprintf("%s/%d", procfsDir, pid)) { 34 | return false 35 | } 36 | 37 | _, _, initCDate, _ := fsutil.GetTimestamps(fmt.Sprintf("%s/%d", procfsDir, 1)) 38 | _, _, procCDate, _ := fsutil.GetTimestamps(fmt.Sprintf("%s/%d", procfsDir, pid)) 39 | 40 | if initCDate != -1 && procCDate != -1 && initCDate > procCDate { 41 | return false 42 | } 43 | 44 | return IsProcessWorks(pid) 45 | } 46 | 47 | // IsProcessWorks returns true if process with given PID is works 48 | func IsProcessWorks(pid int) bool { 49 | // On Unix systems, FindProcess always succeeds and returns a Process 50 | // for the given pid, regardless of whether the process exists. 51 | pr, _ := os.FindProcess(pid) 52 | return pr.Signal(syscall.Signal(0)) == nil 53 | } 54 | -------------------------------------------------------------------------------- /pid/pid_linux_test.go: -------------------------------------------------------------------------------- 1 | //go:build linux || freebsd 2 | // +build linux freebsd 3 | 4 | package pid 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | import ( 14 | "fmt" 15 | "os" 16 | "time" 17 | 18 | . "github.com/essentialkaos/check" 19 | ) 20 | 21 | // ////////////////////////////////////////////////////////////////////////////////// // 22 | 23 | func (s *PidSuite) TestIsWorks(c *C) { 24 | Dir = s.Dir 25 | 26 | err := Create("test") 27 | 28 | c.Assert(err, IsNil) 29 | c.Assert(IsWorks("test"), Equals, true) 30 | 31 | Remove("test") 32 | 33 | c.Assert(IsWorks("test"), Equals, false) 34 | 35 | // Write fake pid to pid file 36 | os.WriteFile(s.Dir+"/test.pid", []byte("69999\n"), 0644) 37 | 38 | c.Assert(IsWorks("test"), Equals, false) 39 | 40 | procfsDir = c.MkDir() 41 | err = os.Mkdir(procfsDir+"/69999", 0755) 42 | 43 | if err != nil { 44 | c.Fatal(fmt.Sprintf("Can't create directory %s", procfsDir+"/69999")) 45 | } 46 | 47 | time.Sleep(2 * time.Second) 48 | 49 | err = os.Mkdir(procfsDir+"/1", 0755) 50 | 51 | if err != nil { 52 | c.Fatal(fmt.Sprintf("Can't create directory %s", procfsDir+"/1")) 53 | } 54 | 55 | c.Assert(IsWorks("test"), Equals, false) 56 | } 57 | 58 | func (s *PidSuite) TestIsProcessWorks(c *C) { 59 | c.Assert(IsProcessWorks(os.Getpid()), Equals, true) 60 | c.Assert(IsProcessWorks(999999), Equals, false) 61 | } 62 | -------------------------------------------------------------------------------- /pid/pid_stubs.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !darwin && !freebsd 2 | // +build !linux,!darwin,!freebsd 3 | 4 | // Package pid provides methods for working with PID files 5 | package pid 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | // ❗ IsWorks returns true if process with PID from PID file is works 15 | func IsWorks(name string) bool { 16 | panic("UNSUPPORTED") 17 | return false 18 | } 19 | 20 | // ❗ IsProcessWorks returns true if process with given PID is works 21 | func IsProcessWorks(pid int) bool { 22 | panic("UNSUPPORTED") 23 | return false 24 | } 25 | -------------------------------------------------------------------------------- /pluralize/examples_test.go: -------------------------------------------------------------------------------- 1 | package pluralize 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | func ExampleP() { 17 | fmt.Println(P("I have %d %s", 1, "apple", "apples")) 18 | fmt.Println(P("I have %d %s", 5, "apple", "apples")) 19 | // Output: I have 1 apple 20 | // I have 5 apples 21 | } 22 | 23 | func ExamplePS() { 24 | fmt.Println(PS(Ru, "У меня %d %s", 1, "яблоко", "яблока", "яблок")) 25 | fmt.Println(PS(Ru, "У меня %d %s", 5, "яблоко", "яблока", "яблок")) 26 | // Output: У меня 1 яблоко 27 | // У меня 5 яблок 28 | } 29 | 30 | func ExamplePluralize() { 31 | fmt.Println(Pluralize(1, "apple", "apples")) 32 | fmt.Println(Pluralize(5, "apple", "apples")) 33 | // Output: apple 34 | // apples 35 | } 36 | func ExamplePluralizeSpecial() { 37 | fmt.Println(PluralizeSpecial(Ru, 1, "яблоко", "яблока", "яблок")) 38 | fmt.Println(PluralizeSpecial(Ru, 5, "яблоко", "яблока", "яблок")) 39 | // Output: яблоко 40 | // яблок 41 | } 42 | -------------------------------------------------------------------------------- /protip/example_test.go: -------------------------------------------------------------------------------- 1 | package protip 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | func ExampleAdd() { 11 | // Add simple tip 12 | Add(&Tip{ 13 | Title: "Tip #1", 14 | Message: `Tip message`, 15 | }) 16 | 17 | // Add tip with custom weight (≠ 0.5) 18 | Add(&Tip{ 19 | Title: "Tip #2", 20 | Message: `Tip message`, 21 | Weight: 0.1, 22 | }) 23 | 24 | // Add tip with custom weight (≠ 0.5) and color 25 | Add(&Tip{ 26 | Title: "Tip #3", 27 | Message: `Tip message`, 28 | Weight: 0.8, 29 | ColorTag: "{b}", 30 | }) 31 | } 32 | 33 | func ExampleShow() { 34 | // Add simple tip 35 | Add(&Tip{ 36 | Title: "Tip #1", 37 | Message: `Tip message`, 38 | }) 39 | 40 | // Increase default probability to 50% 41 | Probability = 0.5 42 | 43 | // Set default color to green 44 | ColorTag = "{g}" 45 | 46 | // Try to show tip 47 | Show(false) 48 | 49 | // Force show 50 | Show(true) 51 | } 52 | -------------------------------------------------------------------------------- /rand/rand.go: -------------------------------------------------------------------------------- 1 | // Package rand provides methods for generating random data 2 | package rand 3 | 4 | // ////////////////////////////////////////////////////////////////////////////////// // 5 | // // 6 | // Copyright (c) 2025 ESSENTIAL KAOS // 7 | // Apache License, Version 2.0 // 8 | // // 9 | // ////////////////////////////////////////////////////////////////////////////////// // 10 | 11 | import ( 12 | "math/rand" 13 | "time" 14 | ) 15 | 16 | // ////////////////////////////////////////////////////////////////////////////////// // 17 | 18 | var symbols = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890" 19 | 20 | // ////////////////////////////////////////////////////////////////////////////////// // 21 | 22 | // String returns string with random chars 23 | func String(length int) string { 24 | if length <= 0 { 25 | return "" 26 | } 27 | 28 | rnd := rand.New(rand.NewSource(time.Now().UTC().UnixNano())) 29 | symbolsLength := len(symbols) 30 | result := make([]byte, length) 31 | 32 | for i := range length { 33 | result[i] = symbols[rnd.Intn(symbolsLength)] 34 | } 35 | 36 | return string(result) 37 | } 38 | 39 | // Slice returns slice with random chars 40 | func Slice(length int) []string { 41 | if length == 0 { 42 | return []string{} 43 | } 44 | 45 | rnd := rand.New(rand.NewSource(time.Now().UTC().UnixNano())) 46 | symbolsLength := len(symbols) 47 | result := make([]string, length) 48 | 49 | for i := range length { 50 | result[i] = string(symbols[rnd.Intn(symbolsLength)]) 51 | } 52 | 53 | return result 54 | } 55 | 56 | // ////////////////////////////////////////////////////////////////////////////////// // 57 | -------------------------------------------------------------------------------- /rand/rand_test.go: -------------------------------------------------------------------------------- 1 | package rand 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "strings" 12 | "testing" 13 | 14 | . "github.com/essentialkaos/check" 15 | ) 16 | 17 | // ////////////////////////////////////////////////////////////////////////////////// // 18 | 19 | func Test(t *testing.T) { TestingT(t) } 20 | 21 | type RandSuite struct{} 22 | 23 | // ////////////////////////////////////////////////////////////////////////////////// // 24 | 25 | var _ = Suite(&RandSuite{}) 26 | 27 | // ////////////////////////////////////////////////////////////////////////////////// // 28 | 29 | func (s *RandSuite) TestString(c *C) { 30 | c.Assert(len(String(100)), Equals, 100) 31 | c.Assert(len(String(1)), Equals, 1) 32 | c.Assert(len(String(0)), Equals, 0) 33 | c.Assert(len(String(-100)), Equals, 0) 34 | } 35 | 36 | func (s *RandSuite) TestSlice(c *C) { 37 | t1 := strings.Join(Slice(256), "") 38 | t2 := strings.Join(Slice(256), "") 39 | 40 | c.Assert(t1, Not(Equals), t2) 41 | c.Assert(Slice(0), HasLen, 0) 42 | } 43 | -------------------------------------------------------------------------------- /req/headers.go: -------------------------------------------------------------------------------- 1 | package req 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | // Headers is a map[string]string used for headers 11 | type Headers map[string]string 12 | 13 | // ////////////////////////////////////////////////////////////////////////////////// // 14 | 15 | // Set sets header value 16 | func (h Headers) Set(name, value string) bool { 17 | if h == nil || name == "" || value == "" { 18 | return false 19 | } 20 | 21 | h[name] = value 22 | 23 | return true 24 | } 25 | 26 | // SetIf sets header value if given condition is true 27 | func (h Headers) SetIf(cond bool, name, value string) bool { 28 | if h == nil || name == "" || !cond { 29 | return false 30 | } 31 | 32 | h[name] = value 33 | 34 | return true 35 | } 36 | 37 | // Get returns header with given name 38 | func (h Headers) Get(name string) string { 39 | if h == nil || name == "" { 40 | return "" 41 | } 42 | 43 | return h[name] 44 | } 45 | 46 | // Delete deletes parameter with given name 47 | func (h Headers) Delete(name string) bool { 48 | if h == nil || name == "" { 49 | return false 50 | } 51 | 52 | delete(h, name) 53 | 54 | return true 55 | } 56 | 57 | // DeleteIf deletes parameter with given name if condition is true 58 | func (h Headers) DeleteIf(cond bool, name string) bool { 59 | if h == nil || name == "" || !cond { 60 | return false 61 | } 62 | 63 | if h[name] != "" { 64 | delete(h, name) 65 | } 66 | 67 | return true 68 | } 69 | 70 | // ////////////////////////////////////////////////////////////////////////////////// // 71 | -------------------------------------------------------------------------------- /req/limiter.go: -------------------------------------------------------------------------------- 1 | package req 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import "time" 11 | 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | // Limiter is request limiter 15 | type Limiter struct { 16 | lastCall time.Time 17 | delay time.Duration 18 | } 19 | 20 | // ////////////////////////////////////////////////////////////////////////////////// // 21 | 22 | // NewLimiter creates a new limiter. If rps is less than or equal to 0, it returns nil. 23 | func NewLimiter(rps float64) *Limiter { 24 | if rps <= 0 { 25 | return nil 26 | } 27 | 28 | return &Limiter{ 29 | delay: time.Duration(float64(time.Second) / rps), 30 | } 31 | } 32 | 33 | // ////////////////////////////////////////////////////////////////////////////////// // 34 | 35 | // Wait blocks current goroutine execution until next time slot become available 36 | func (l *Limiter) Wait() { 37 | if l == nil { 38 | return 39 | } 40 | 41 | if l.lastCall.IsZero() { 42 | l.lastCall = time.Now() 43 | return 44 | } 45 | 46 | w := time.Since(l.lastCall) 47 | 48 | if w < l.delay { 49 | time.Sleep(l.delay - w) 50 | } 51 | 52 | l.lastCall = time.Now() 53 | } 54 | -------------------------------------------------------------------------------- /reutil/example_test.go: -------------------------------------------------------------------------------- 1 | package reutil 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | "regexp" 13 | ) 14 | 15 | // ////////////////////////////////////////////////////////////////////////////////// // 16 | 17 | func ExampleReplace() { 18 | re := regexp.MustCompile(`([a-zA-Z0-9_.]+)@([a-zA-Z0-9-_.]+\.[a-z]{2,3})`) 19 | mails := "jdoe@yahoo.com bob.entus@gmail.com dina@mail.org" 20 | mappings := map[string]string{ 21 | "yahoo.com": "YH", 22 | "gmail.com": "GML", 23 | "mail.org": "ML", 24 | } 25 | 26 | repl, err := Replace(re, mails, func(found string, submatch []string) string { 27 | return submatch[0] + ":" + mappings[submatch[1]] 28 | }) 29 | 30 | if err != nil { 31 | fmt.Println(err) 32 | return 33 | } 34 | 35 | fmt.Printf("%s → %s\n", mails, repl) 36 | 37 | // Output: 38 | // jdoe@yahoo.com bob.entus@gmail.com dina@mail.org → jdoe:YH bob.entus:GML dina:ML 39 | } 40 | -------------------------------------------------------------------------------- /secstr/example_test.go: -------------------------------------------------------------------------------- 1 | package secstr 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | func ExampleNewSecureString() { 17 | passwd := "MySuppaPassword12345" 18 | ss, err := NewSecureString(&passwd) 19 | 20 | if err != nil { 21 | panic(err) 22 | } 23 | 24 | fmt.Printf("Password: %s", string(ss.Data)) 25 | } 26 | -------------------------------------------------------------------------------- /secstr/secstring_stubs.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !darwin 2 | // +build !linux,!darwin 3 | 4 | // Package secstr provides methods and structs for working with protected (secure) strings 5 | package secstr 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | // ❗ String contains protected data 15 | type String struct { 16 | Data []byte 17 | } 18 | 19 | // ////////////////////////////////////////////////////////////////////////////////// // 20 | 21 | // ❗ NewSecureString creates new secure string 22 | func NewSecureString(data any) (*String, error) { 23 | panic("UNSUPPORTED") 24 | return nil, nil 25 | } 26 | 27 | // ////////////////////////////////////////////////////////////////////////////////// // 28 | 29 | // ❗ IsEmpty returns false if string is empty 30 | func (s *String) IsEmpty() bool { 31 | panic("UNSUPPORTED") 32 | return false 33 | } 34 | 35 | // ❗ Destroy destroys data 36 | func (s *String) Destroy() error { 37 | panic("UNSUPPORTED") 38 | return nil 39 | } 40 | -------------------------------------------------------------------------------- /signal/example_test.go: -------------------------------------------------------------------------------- 1 | package signal 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | "time" 13 | ) 14 | 15 | // ////////////////////////////////////////////////////////////////////////////////// // 16 | 17 | func ExampleHandlers_Track() { 18 | hupHandler := func() { 19 | fmt.Println("Got HUP signal") 20 | } 21 | 22 | usr1Handler := func() { 23 | fmt.Println("Got USR1 signal") 24 | } 25 | 26 | Handlers{ 27 | HUP: hupHandler, 28 | USR1: usr1Handler, 29 | }.Track() 30 | } 31 | 32 | func ExampleHandlers_TrackAsync() { 33 | hupHandler := func() { 34 | fmt.Println("Got HUP signal") 35 | } 36 | 37 | usr1Handler := func() { 38 | fmt.Println("Got USR1 signal") 39 | } 40 | 41 | Handlers{ 42 | HUP: hupHandler, 43 | USR1: usr1Handler, 44 | }.TrackAsync() 45 | 46 | time.Sleep(time.Hour) 47 | } 48 | -------------------------------------------------------------------------------- /sortutil/example_test.go: -------------------------------------------------------------------------------- 1 | package sortutil 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | func ExampleVersions() { 17 | versionSlice := []string{ 18 | "2.0-5", 19 | "1.3b", 20 | "1.1", 21 | "1.3", 22 | "1.1.6", 23 | "1", 24 | "2.0", 25 | "2.0-1", 26 | } 27 | 28 | Versions(versionSlice) 29 | 30 | fmt.Println(versionSlice) 31 | 32 | // Output: 33 | // [1 1.1 1.1.6 1.3 1.3b 2.0 2.0-1 2.0-5] 34 | } 35 | 36 | func ExampleStrings() { 37 | stringSlice := []string{ 38 | "Alisa", 39 | "Luna", 40 | "remedios", 41 | "Ona", 42 | "Eugene", 43 | "lorriane", 44 | "Zachariah", 45 | "cecily", 46 | "eleonora", 47 | "Dotty", 48 | } 49 | 50 | // Case insensitive sorting 51 | Strings(stringSlice, false) 52 | 53 | fmt.Println(stringSlice) 54 | 55 | // Case sensitive sorting 56 | Strings(stringSlice, true) 57 | 58 | fmt.Println(stringSlice) 59 | 60 | // Output: 61 | // [Alisa Dotty Eugene Luna Ona Zachariah cecily eleonora lorriane remedios] 62 | // [Alisa cecily Dotty eleonora Eugene lorriane Luna Ona remedios Zachariah] 63 | } 64 | -------------------------------------------------------------------------------- /spellcheck/example_test.go: -------------------------------------------------------------------------------- 1 | package spellcheck 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | func ExampleTrain() { 17 | name := "Frida" 18 | names := []string{"Jakalyn", "Freda", "Micayla", "Knightley", "Shun"} 19 | 20 | model := Train(names) 21 | 22 | fmt.Printf("%s → %s\n", name, model.Correct(name)) 23 | // Output: Frida → Freda 24 | } 25 | 26 | func ExampleModel_Correct() { 27 | name := "Frida" 28 | names := []string{"Jakalyn", "Freda", "Micayla", "Knightley", "Shun"} 29 | 30 | model := Train(names) 31 | 32 | fmt.Printf("%s → %s\n", name, model.Correct(name)) 33 | // Output: Frida → Freda 34 | } 35 | 36 | func ExampleModel_Suggest() { 37 | name := "azi" 38 | names := []string{"Thorin", "Akhai", "Payden", "Ghazi", "Rey", "Axel", "Sahily", "Azriel"} 39 | 40 | model := Train(names) 41 | 42 | fmt.Printf("%s → %s\n", name, model.Suggest(name, 3)) 43 | } 44 | -------------------------------------------------------------------------------- /spinner/examples_test.go: -------------------------------------------------------------------------------- 1 | package spinner 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "time" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | func ExampleShow() { 17 | file := "file.txt" 18 | 19 | // Customize design 20 | OkSymbol = "🤟" // Set success status symbol 21 | OkColorTag = "{b}" // Set success status symbol color 22 | 23 | Show("Removing file %s", file) 24 | time.Sleep(time.Second) 25 | Done(true) 26 | } 27 | 28 | func ExampleUpdate() { 29 | Show("My long running task") 30 | time.Sleep(time.Second) 31 | Show("My long running task still working") 32 | time.Sleep(time.Second) 33 | Done(true) 34 | } 35 | 36 | func ExampleDone() { 37 | Show("My long running task with good result") 38 | time.Sleep(time.Second) 39 | Done(true) 40 | 41 | Show("My long running task with bad result") 42 | time.Sleep(time.Second) 43 | Done(false) 44 | } 45 | 46 | func ExampleSkip() { 47 | Show("My skipped running task") 48 | time.Sleep(time.Second) 49 | Skip() 50 | } 51 | -------------------------------------------------------------------------------- /spinner/spinner_test.go: -------------------------------------------------------------------------------- 1 | package spinner 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "testing" 12 | "time" 13 | 14 | . "github.com/essentialkaos/check" 15 | ) 16 | 17 | // ////////////////////////////////////////////////////////////////////////////////// // 18 | 19 | func Test(t *testing.T) { TestingT(t) } 20 | 21 | type SpinnerSuite struct{} 22 | 23 | // ////////////////////////////////////////////////////////////////////////////////// // 24 | 25 | var _ = Suite(&SpinnerSuite{}) 26 | 27 | // ////////////////////////////////////////////////////////////////////////////////// // 28 | 29 | func (s *SpinnerSuite) TestSpinner(c *C) { 30 | Done(true) // skipped 31 | Show("ABCD") 32 | Show("ABCD") // skipped 33 | time.Sleep(time.Millisecond * 800) 34 | Update("ABCD") 35 | time.Sleep(time.Millisecond * 100) 36 | Done(true) 37 | Update("ABCD") // skipped 38 | Show("ABCD") 39 | time.Sleep(time.Millisecond * 10) 40 | Done(false) 41 | Show("ABCD") 42 | time.Sleep(time.Millisecond * 10) 43 | Skip() 44 | 45 | DisableAnimation = true 46 | Show("ABCD") 47 | Done(true) 48 | 49 | Skip() 50 | } 51 | -------------------------------------------------------------------------------- /strutil/fuzz.go: -------------------------------------------------------------------------------- 1 | //go:build gofuzz 2 | // +build gofuzz 3 | 4 | package strutil 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | func Fuzz(data []byte) int { 14 | Fields(string(data)) 15 | return 0 16 | } 17 | -------------------------------------------------------------------------------- /support/apps/example_test.go: -------------------------------------------------------------------------------- 1 | package apps 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import "fmt" 11 | 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | func ExampleExtractVersion() { 15 | // Get Ruby version from 'ruby --version' command (line: 0, field: 1) 16 | rubyVersion := ExtractVersion("ruby --version", 0, 1) 17 | fmt.Println(rubyVersion) 18 | 19 | // Get Java version from 'java -version' command (line: 1, field: 3) 20 | javaVersion := ExtractVersion("java -version", 1, 3) 21 | fmt.Println(javaVersion) 22 | } 23 | -------------------------------------------------------------------------------- /support/fs/fs.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | // +build !windows 3 | 4 | // Package pkgs provides methods for collecting information about filesystem 5 | package fs 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | import ( 15 | "github.com/essentialkaos/ek/v13/system" 16 | 17 | "github.com/essentialkaos/ek/v13/support" 18 | ) 19 | 20 | // ////////////////////////////////////////////////////////////////////////////////// // 21 | 22 | // Collect collects info about filesystem 23 | func Collect() []support.FSInfo { 24 | fsInfo, err := system.GetFSUsage() 25 | 26 | if err != nil { 27 | return nil 28 | } 29 | 30 | var info []support.FSInfo 31 | 32 | for mPath, mInfo := range fsInfo { 33 | info = append(info, support.FSInfo{ 34 | Path: mPath, 35 | Device: mInfo.Device, 36 | Type: mInfo.Type, 37 | Used: mInfo.Used, 38 | Free: mInfo.Free, 39 | }) 40 | } 41 | 42 | return info 43 | } 44 | -------------------------------------------------------------------------------- /support/fs/fs_windows.go: -------------------------------------------------------------------------------- 1 | // Package pkgs provides methods for collecting information about filesystem 2 | package fs 3 | 4 | // ////////////////////////////////////////////////////////////////////////////////// // 5 | // // 6 | // Copyright (c) 2025 ESSENTIAL KAOS // 7 | // Apache License, Version 2.0 // 8 | // // 9 | // ////////////////////////////////////////////////////////////////////////////////// // 10 | 11 | import ( 12 | "github.com/essentialkaos/ek/v13/support" 13 | ) 14 | 15 | // ////////////////////////////////////////////////////////////////////////////////// // 16 | 17 | // Collect collects info about filesystem 18 | func Collect() []support.FSInfo { 19 | return nil 20 | } 21 | -------------------------------------------------------------------------------- /support/kernel/kernel.go: -------------------------------------------------------------------------------- 1 | //go:build linux || darwin 2 | // +build linux darwin 3 | 4 | // Package kernel provides methods for collecting information from OS kernel 5 | package kernel 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | import ( 15 | "strings" 16 | 17 | "github.com/essentialkaos/ek/v13/strutil" 18 | "github.com/essentialkaos/ek/v13/support" 19 | "github.com/essentialkaos/ek/v13/system/sysctl" 20 | ) 21 | 22 | // ////////////////////////////////////////////////////////////////////////////////// // 23 | 24 | // Collect collects info from OS kernel 25 | func Collect(params ...string) []support.KernelParam { 26 | kernelParams, err := sysctl.All() 27 | 28 | if err != nil { 29 | return nil 30 | } 31 | 32 | var result []support.KernelParam 33 | 34 | for _, param := range params { 35 | isGlob := strings.HasSuffix(param, "*") 36 | param = strings.TrimRight(param, "*") 37 | 38 | for k, v := range kernelParams { 39 | if isGlob { 40 | if !strings.HasPrefix(k, param) { 41 | continue 42 | } 43 | } else { 44 | if k != param { 45 | continue 46 | } 47 | } 48 | 49 | value := strings.ReplaceAll(v, "\t", " ") 50 | value = strutil.SqueezeRepeats(value, " ") 51 | 52 | result = append(result, support.KernelParam{ 53 | Key: k, 54 | Value: value, 55 | }) 56 | } 57 | } 58 | 59 | return result 60 | } 61 | -------------------------------------------------------------------------------- /support/kernel/kernel_windows.go: -------------------------------------------------------------------------------- 1 | // Package kernel provides methods for collecting information from OS kernel 2 | package kernel 3 | 4 | // ////////////////////////////////////////////////////////////////////////////////// // 5 | // // 6 | // Copyright (c) 2025 ESSENTIAL KAOS // 7 | // Apache License, Version 2.0 // 8 | // // 9 | // ////////////////////////////////////////////////////////////////////////////////// // 10 | 11 | import "github.com/essentialkaos/ek/v13/support" 12 | 13 | // ////////////////////////////////////////////////////////////////////////////////// // 14 | 15 | // Collect collects info from OS kernel 16 | func Collect(params ...string) []support.KernelParam { 17 | return nil 18 | } 19 | -------------------------------------------------------------------------------- /support/network/network_windows.go: -------------------------------------------------------------------------------- 1 | // Package network provides methods for collecting information about machine network 2 | package network 3 | 4 | // ////////////////////////////////////////////////////////////////////////////////// // 5 | // // 6 | // Copyright (c) 2025 ESSENTIAL KAOS // 7 | // Apache License, Version 2.0 // 8 | // // 9 | // ////////////////////////////////////////////////////////////////////////////////// // 10 | 11 | import ( 12 | "github.com/essentialkaos/ek/v13/support" 13 | 14 | "golang.org/x/sys/windows" 15 | ) 16 | 17 | // ////////////////////////////////////////////////////////////////////////////////// // 18 | 19 | // Collect collects network info 20 | func Collect(ipResolverURL ...string) *support.NetworkInfo { 21 | info := &support.NetworkInfo{} 22 | 23 | info.Hostname, _ = windows.ComputerName() 24 | 25 | if len(ipResolverURL) != 0 { 26 | info.PublicIP = resolvePublicIP(ipResolverURL[0]) 27 | } 28 | 29 | if info.Hostname == "" && info.PublicIP == "" { 30 | return nil 31 | } 32 | 33 | return info 34 | } 35 | -------------------------------------------------------------------------------- /support/pkgs/pkgs_darwin.go: -------------------------------------------------------------------------------- 1 | // Package pkgs provides methods for collecting information about installed packages 2 | package pkgs 3 | 4 | // ////////////////////////////////////////////////////////////////////////////////// // 5 | // // 6 | // Copyright (c) 2025 ESSENTIAL KAOS // 7 | // Apache License, Version 2.0 // 8 | // // 9 | // ////////////////////////////////////////////////////////////////////////////////// // 10 | 11 | import "github.com/essentialkaos/ek/v13/support" 12 | 13 | // ////////////////////////////////////////////////////////////////////////////////// // 14 | 15 | // Collect collect info about packages 16 | func Collect(pkgs ...string) []support.Pkg { 17 | return nil 18 | } 19 | -------------------------------------------------------------------------------- /support/pkgs/pkgs_windows.go: -------------------------------------------------------------------------------- 1 | // Package pkgs provides methods for collecting information about installed packages 2 | package pkgs 3 | 4 | // ////////////////////////////////////////////////////////////////////////////////// // 5 | // // 6 | // Copyright (c) 2025 ESSENTIAL KAOS // 7 | // Apache License, Version 2.0 // 8 | // // 9 | // ////////////////////////////////////////////////////////////////////////////////// // 10 | 11 | import ( 12 | "github.com/essentialkaos/ek/v13/support" 13 | ) 14 | 15 | // ////////////////////////////////////////////////////////////////////////////////// // 16 | 17 | // Collect collect info about packages 18 | func Collect(pkgs ...string) []support.Pkg { 19 | return nil 20 | } 21 | -------------------------------------------------------------------------------- /support/resources/resources.go: -------------------------------------------------------------------------------- 1 | //go:build linux || darwin 2 | // +build linux darwin 3 | 4 | // Package resources provides methods for collecting information about system 5 | // resources (cpu/memory) 6 | package resources 7 | 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | // // 10 | // Copyright (c) 2025 ESSENTIAL KAOS // 11 | // Apache License, Version 2.0 // 12 | // // 13 | // ////////////////////////////////////////////////////////////////////////////////// // 14 | 15 | import ( 16 | "github.com/essentialkaos/ek/v13/support" 17 | "github.com/essentialkaos/ek/v13/system" 18 | ) 19 | 20 | // ////////////////////////////////////////////////////////////////////////////////// // 21 | 22 | // Collect collects info about CPU and memory 23 | func Collect() *support.ResourcesInfo { 24 | result := &support.ResourcesInfo{} 25 | 26 | cpuInfo, err1 := system.GetCPUInfo() 27 | 28 | if err1 == nil { 29 | for _, p := range cpuInfo { 30 | result.CPU = append(result.CPU, support.CPUInfo{ 31 | Model: p.Model, 32 | Cores: p.Cores, 33 | Threads: p.Siblings / p.Cores, 34 | }) 35 | } 36 | } 37 | 38 | memInfo, err2 := system.GetMemUsage() 39 | 40 | if err2 == nil { 41 | result.MemTotal = memInfo.MemTotal 42 | result.MemFree = memInfo.MemFree 43 | result.MemUsed = memInfo.MemUsed 44 | result.SwapTotal = memInfo.SwapTotal 45 | result.SwapFree = memInfo.SwapFree 46 | result.SwapUsed = memInfo.SwapUsed 47 | } 48 | 49 | if err1 != nil && err2 != nil { 50 | return nil 51 | } 52 | 53 | return result 54 | } 55 | -------------------------------------------------------------------------------- /support/resources/resources_windows.go: -------------------------------------------------------------------------------- 1 | // Package resources provides methods for collecting information about system 2 | // resources (cpu/memory) 3 | package resources 4 | 5 | // ////////////////////////////////////////////////////////////////////////////////// // 6 | // // 7 | // Copyright (c) 2025 ESSENTIAL KAOS // 8 | // Apache License, Version 2.0 // 9 | // // 10 | // ////////////////////////////////////////////////////////////////////////////////// // 11 | 12 | import ( 13 | "github.com/essentialkaos/ek/v13/support" 14 | ) 15 | 16 | // ////////////////////////////////////////////////////////////////////////////////// // 17 | 18 | // Collect collects info about CPU and memory 19 | func Collect() *support.ResourcesInfo { 20 | return nil 21 | } 22 | -------------------------------------------------------------------------------- /support/services/services.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | // +build !windows 3 | 4 | // Package services provides methods for collecting information about system services 5 | package services 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | import ( 15 | "github.com/essentialkaos/ek/v13/initsystem" 16 | "github.com/essentialkaos/ek/v13/support" 17 | ) 18 | 19 | // ////////////////////////////////////////////////////////////////////////////////// // 20 | 21 | // Collect collects info about services 22 | func Collect(services ...string) []support.Service { 23 | var result []support.Service 24 | 25 | for _, s := range services { 26 | service := support.Service{Name: s, Status: support.STATUS_UNKNOWN} 27 | 28 | if initsystem.IsPresent(s) { 29 | service.IsPresent = true 30 | service.IsEnabled, _ = initsystem.IsEnabled(s) 31 | 32 | isWorks, err := initsystem.IsWorks(s) 33 | 34 | switch { 35 | case err == nil && isWorks: 36 | service.Status = support.STATUS_WORKS 37 | case err == nil && !isWorks: 38 | service.Status = support.STATUS_STOPPED 39 | } 40 | } 41 | 42 | result = append(result, service) 43 | } 44 | 45 | return result 46 | } 47 | -------------------------------------------------------------------------------- /support/services/services_windows.go: -------------------------------------------------------------------------------- 1 | // Package services provides methods for collecting information about system services 2 | package services 3 | 4 | // ////////////////////////////////////////////////////////////////////////////////// // 5 | // // 6 | // Copyright (c) 2025 ESSENTIAL KAOS // 7 | // Apache License, Version 2.0 // 8 | // // 9 | // ////////////////////////////////////////////////////////////////////////////////// // 10 | 11 | import "github.com/essentialkaos/ek/v13/support" 12 | 13 | // ////////////////////////////////////////////////////////////////////////////////// // 14 | 15 | // Collect collect info about services 16 | func Collect(services ...string) []support.Service { 17 | return nil 18 | } 19 | -------------------------------------------------------------------------------- /support/support_darwin.go: -------------------------------------------------------------------------------- 1 | package support 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import "github.com/essentialkaos/ek/v13/system" 11 | 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | // appendSystemInfo appends system info 15 | func (i *Info) appendSystemInfo() { 16 | systemInfo, err := system.GetSystemInfo() 17 | 18 | if err != nil { 19 | return 20 | } 21 | 22 | i.System = &SystemInfo{ 23 | Name: systemInfo.OS, 24 | ID: systemInfo.ID, 25 | Arch: systemInfo.Arch, 26 | Kernel: systemInfo.Kernel, 27 | } 28 | } 29 | 30 | // appendOSInfo appends OS info 31 | func (i *Info) appendOSInfo() { 32 | osInfo, err := system.GetOSInfo() 33 | 34 | if err != nil { 35 | return 36 | } 37 | 38 | i.OS = &OSInfo{ 39 | Name: osInfo.Name, 40 | Version: osInfo.VersionID, 41 | Build: osInfo.Build, 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /support/support_linux.go: -------------------------------------------------------------------------------- 1 | package support 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "github.com/essentialkaos/ek/v13/system" 12 | "github.com/essentialkaos/ek/v13/system/container" 13 | ) 14 | 15 | // ////////////////////////////////////////////////////////////////////////////////// // 16 | 17 | // appendSystemInfo appends system info 18 | func (i *Info) appendSystemInfo() { 19 | systemInfo, err := system.GetSystemInfo() 20 | 21 | if err != nil { 22 | return 23 | } 24 | 25 | i.System = &SystemInfo{ 26 | Name: systemInfo.OS, 27 | ID: systemInfo.ID, 28 | Arch: systemInfo.Arch, 29 | Kernel: systemInfo.Kernel, 30 | } 31 | 32 | if i.OS != nil { 33 | i.System.Name = i.OS.Name 34 | } 35 | 36 | i.System.ContainerEngine = container.GetEngine() 37 | } 38 | 39 | // appendOSInfo appends OS info 40 | func (i *Info) appendOSInfo() { 41 | osInfo, err := system.GetOSInfo() 42 | 43 | if err != nil { 44 | return 45 | } 46 | 47 | i.OS = &OSInfo{ 48 | Name: osInfo.Name, 49 | PrettyName: osInfo.PrettyName, 50 | Version: osInfo.Version, 51 | ID: osInfo.ID, 52 | IDLike: osInfo.IDLike, 53 | VersionID: osInfo.VersionID, 54 | VersionCode: osInfo.VersionCodename, 55 | PlatformID: osInfo.PlatformID, 56 | CPE: osInfo.CPEName, 57 | 58 | coloredName: osInfo.ColoredName(), 59 | coloredPrettyName: osInfo.ColoredPrettyName(), 60 | } 61 | } 62 | 63 | // ////////////////////////////////////////////////////////////////////////////////// // 64 | -------------------------------------------------------------------------------- /system/container/example_test.go: -------------------------------------------------------------------------------- 1 | package container 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | func ExampleGetEngine() { 17 | fmt.Printf("Container engine: %s\n", GetEngine()) 18 | } 19 | 20 | func ExampleIsContainer() { 21 | if !IsContainer() { 22 | fmt.Println("It's not containerized") 23 | } else { 24 | fmt.Printf("It's containerized using %s engine\n", GetEngine()) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /system/exec/examples_test.go: -------------------------------------------------------------------------------- 1 | package exec 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | func ExampleRun() { 17 | err := Run("/bin/echo", "abc", "123") 18 | 19 | if err != nil { 20 | fmt.Printf("Error: %v", err) 21 | } 22 | } 23 | 24 | func ExampleSudo() { 25 | err := Sudo("/bin/echo", "abc", "123") 26 | 27 | if err != nil { 28 | fmt.Printf("Error: %v", err) 29 | } 30 | } 31 | 32 | func ExampleRunAsUser() { 33 | // run echo as user some user and redirect output to /var/log/output.log 34 | err := RunAsUser("someuser", "/var/log/output.log", "/bin/echo", "abc", "123") 35 | 36 | if err != nil { 37 | fmt.Printf("Error: %v", err) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /system/exec/exec_stubs.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !darwin && !freebsd 2 | // +build !linux,!darwin,!freebsd 3 | 4 | // Package exec provides methods for executing commands 5 | package exec 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | // ❗ Sudo executes command with sudo 15 | func Sudo(user string, args ...string) error { 16 | panic("UNSUPPORTED") 17 | return nil 18 | } 19 | 20 | // ❗ Run executes command 21 | func Run(command string, args ...string) error { 22 | panic("UNSUPPORTED") 23 | return nil 24 | } 25 | 26 | // ❗ RunAsUser runs command as a given user 27 | func RunAsUser(user, logFile string, command string, args ...string) error { 28 | panic("UNSUPPORTED") 29 | return nil 30 | } 31 | 32 | // ////////////////////////////////////////////////////////////////////////////////// // 33 | -------------------------------------------------------------------------------- /system/info_fs_darwin.go: -------------------------------------------------------------------------------- 1 | package system 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "time" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | // ❗ GetFSUsage returns info about mounted filesystems 17 | func GetFSUsage() (map[string]*FSUsage, error) { 18 | panic("UNSUPPORTED") 19 | return map[string]*FSUsage{"/": {}}, nil 20 | } 21 | 22 | // ❗ GetIOStats returns I/O stats 23 | func GetIOStats() (map[string]*IOStats, error) { 24 | panic("UNSUPPORTED") 25 | return map[string]*IOStats{"/dev/sda1": {}}, nil 26 | } 27 | 28 | // ❗ GetIOUtil returns IO utilization 29 | func GetIOUtil(duration time.Duration) (map[string]float64, error) { 30 | panic("UNSUPPORTED") 31 | return map[string]float64{"/": 0}, nil 32 | } 33 | 34 | // ❗ CalculateIOUtil calculates IO utilization for all devices 35 | func CalculateIOUtil(io1, io2 map[string]*IOStats, duration time.Duration) map[string]float64 { 36 | panic("UNSUPPORTED") 37 | return map[string]float64{"/": 0} 38 | } 39 | -------------------------------------------------------------------------------- /system/info_linux_arm.go: -------------------------------------------------------------------------------- 1 | //go:build linux && arm 2 | // +build linux,arm 3 | 4 | package system 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | // byteSliceToString convert byte slice to string 14 | func byteSliceToString(s [65]uint8) string { 15 | result := "" 16 | 17 | for _, r := range s { 18 | if r == 0 { 19 | break 20 | } 21 | 22 | result += string(rune(r)) 23 | } 24 | 25 | return result 26 | } 27 | -------------------------------------------------------------------------------- /system/info_linux_basic.go: -------------------------------------------------------------------------------- 1 | //go:build linux && (386 || arm64 || amd64) 2 | // +build linux 3 | // +build 386 arm64 amd64 4 | 5 | package system 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | // byteSliceToString convert byte slice to string 15 | func byteSliceToString(s [65]int8) string { 16 | result := "" 17 | 18 | for _, r := range s { 19 | if r == 0 { 20 | break 21 | } 22 | 23 | result += string(rune(r)) 24 | } 25 | 26 | return result 27 | } 28 | -------------------------------------------------------------------------------- /system/info_net_darwin.go: -------------------------------------------------------------------------------- 1 | package system 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "time" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | // ❗ GetInterfacesStats returns info about network interfaces 17 | func GetInterfacesStats() (map[string]*InterfaceStats, error) { 18 | panic("UNSUPPORTED") 19 | return map[string]*InterfaceStats{"eth0": {}}, nil 20 | } 21 | 22 | // ❗ GetNetworkSpeed returns input/output speed in bytes per second 23 | func GetNetworkSpeed(duration time.Duration) (uint64, uint64, error) { 24 | panic("UNSUPPORTED") 25 | return 0, 0, nil 26 | } 27 | 28 | // ❗ CalculateNetworkSpeed calculates network input/output speed in bytes per second for 29 | // all network interfaces 30 | func CalculateNetworkSpeed(ii1, ii2 map[string]*InterfaceStats, duration time.Duration) (uint64, uint64) { 31 | panic("UNSUPPORTED") 32 | return 0, 0 33 | } 34 | -------------------------------------------------------------------------------- /system/info_uptime_darwin.go: -------------------------------------------------------------------------------- 1 | package system 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "golang.org/x/sys/unix" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | // GetUptime returns uptime in seconds from 1/1/1970 17 | func GetUptime() (uint64, error) { 18 | tv, err := unix.SysctlTimeval("kern.boottime") 19 | 20 | if err != nil { 21 | return 0, err 22 | } 23 | 24 | return uint64(tv.Sec), nil 25 | } 26 | -------------------------------------------------------------------------------- /system/info_uptime_linux.go: -------------------------------------------------------------------------------- 1 | package system 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "syscall" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | // GetUptime returns system uptime in seconds 17 | func GetUptime() (uint64, error) { 18 | info := &syscall.Sysinfo_t{} 19 | err := syscall.Sysinfo(info) 20 | 21 | return uint64(info.Uptime), err 22 | } 23 | -------------------------------------------------------------------------------- /system/process/processes_darwin.go: -------------------------------------------------------------------------------- 1 | package process 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | // ❗ ProcessInfo contains basic info about process 11 | type ProcessInfo struct { 12 | Command string // ❗ Full command 13 | User string // ❗ Username 14 | PID int // ❗ PID 15 | IsThread bool // ❗ True if process is thread 16 | Parent int // ❗ Parent process PID 17 | Children []*ProcessInfo // ❗ Slice with child processes 18 | } 19 | 20 | // ////////////////////////////////////////////////////////////////////////////////// // 21 | 22 | // ❗ GetTree returns root process with all subprocesses on the system 23 | func GetTree(pid ...int) (*ProcessInfo, error) { 24 | panic("UNSUPPORTED") 25 | return nil, nil 26 | } 27 | 28 | // ❗ GetList returns slice with all active processes on the system 29 | func GetList() ([]*ProcessInfo, error) { 30 | panic("UNSUPPORTED") 31 | return nil, nil 32 | } 33 | -------------------------------------------------------------------------------- /system/process/processes_stubs.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !darwin 2 | // +build !linux,!darwin 3 | 4 | package process 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | // ❗ ProcessInfo contains basic info about process 14 | type ProcessInfo struct { 15 | Command string // ❗ Full command 16 | User string // ❗ Username 17 | PID int // ❗ PID 18 | IsThread bool // ❗ True if process is thread 19 | Parent int // ❗ Parent process PID 20 | Children []*ProcessInfo // ❗ Slice with child processes 21 | } 22 | 23 | // ////////////////////////////////////////////////////////////////////////////////// // 24 | 25 | // ❗ GetTree returns root process with all subprocesses on the system 26 | func GetTree(pid ...int) (*ProcessInfo, error) { 27 | panic("UNSUPPORTED") 28 | return nil, nil 29 | } 30 | 31 | // ❗ GetList returns slice with all active processes on the system 32 | func GetList() ([]*ProcessInfo, error) { 33 | panic("UNSUPPORTED") 34 | return nil, nil 35 | } 36 | -------------------------------------------------------------------------------- /system/procname/examples_test.go: -------------------------------------------------------------------------------- 1 | package procname 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | "os" 13 | "strings" 14 | ) 15 | 16 | // ////////////////////////////////////////////////////////////////////////////////// // 17 | 18 | func ExampleSet() { 19 | args := os.Args 20 | 21 | // Mask first argument 22 | args[1] = strings.Repeat("*", len(args[1])) 23 | 24 | err := Set(args) 25 | 26 | if err != nil { 27 | fmt.Printf("Error: %v\n", err) 28 | } 29 | } 30 | 31 | func ExampleReplace() { 32 | password := "mySuppaPass" 33 | 34 | // Replacing known password to asterisks 35 | err := Replace(password, "*****************") 36 | 37 | if err != nil { 38 | fmt.Printf("Error: %v\n", err) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /system/procname/setprocname_stubs.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !darwin 2 | // +build !linux,!darwin 3 | 4 | package procname 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | import ( 14 | "errors" 15 | ) 16 | 17 | // ////////////////////////////////////////////////////////////////////////////////// // 18 | 19 | var ( 20 | // ❗ ErrWrongSize is returned if given slice have the wrong size 21 | ErrWrongSize = errors.New("Given slice must have same size as os.Arg") 22 | 23 | // ❗ ErrWrongArguments is returned if one of given arguments is empty 24 | ErrWrongArguments = errors.New("Arguments can't be empty") 25 | ) 26 | 27 | // ////////////////////////////////////////////////////////////////////////////////// // 28 | 29 | // ❗ Set changes current process command in process tree 30 | func Set(args []string) error { 31 | panic("UNSUPPORTED") 32 | return nil 33 | } 34 | 35 | // ❗ Replace replaces one argument in process command 36 | // 37 | // WARNING: Be careful with using os.Args or options.Parse result 38 | // as 'from' argument. After using this method given variable content 39 | // will be replaced. Use strutil.Copy method in this case. 40 | func Replace(from, to string) error { 41 | panic("UNSUPPORTED") 42 | return nil 43 | } 44 | -------------------------------------------------------------------------------- /system/sensors/sensors_darwin.go: -------------------------------------------------------------------------------- 1 | // Package sensors provide methods for collecting sensors information 2 | package sensors 3 | 4 | // ////////////////////////////////////////////////////////////////////////////////// // 5 | // // 6 | // Copyright (c) 2025 ESSENTIAL KAOS // 7 | // Apache License, Version 2.0 // 8 | // // 9 | // ////////////////////////////////////////////////////////////////////////////////// // 10 | 11 | // ❗ Device contains info from different device sensors 12 | type Device struct { 13 | Name string 14 | TempSensors []TempSensor 15 | } 16 | 17 | // ❗ TempSensor contains info from temperature sensor 18 | type TempSensor struct { 19 | Name string 20 | Cur float64 21 | Min float64 22 | Max float64 23 | Crit float64 24 | } 25 | 26 | // ////////////////////////////////////////////////////////////////////////////////// // 27 | 28 | // ❗ Collect collects sensors information 29 | func Collect() ([]*Device, error) { 30 | panic("UNSUPPORTED") 31 | return nil, nil 32 | } 33 | 34 | // ////////////////////////////////////////////////////////////////////////////////// // 35 | 36 | // ❗ Temperature returns min, max and average temperature 37 | func (d *Device) Temperature() (float64, float64, float64) { 38 | panic("UNSUPPORTED") 39 | return 0.0, 0.0, 0.0 40 | } 41 | 42 | // ❗ String formats sensor data as a string 43 | func (s TempSensor) String() string { 44 | panic("UNSUPPORTED") 45 | return "" 46 | } 47 | 48 | // ////////////////////////////////////////////////////////////////////////////////// // 49 | -------------------------------------------------------------------------------- /system/sensors/sensors_stubs.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !darwin 2 | // +build !linux,!darwin 3 | 4 | // Package sensors provide methods for collecting sensors information 5 | package sensors 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | // ❗ Device contains info from different device sensors 15 | type Device struct { 16 | Name string 17 | TempSensors []TempSensor 18 | } 19 | 20 | // ❗ TempSensor contains info from temperature sensor 21 | type TempSensor struct { 22 | Name string 23 | Cur float64 24 | Min float64 25 | Max float64 26 | Crit float64 27 | } 28 | 29 | // ////////////////////////////////////////////////////////////////////////////////// // 30 | 31 | // ❗ Collect collects sensors information 32 | func Collect() ([]*Device, error) { 33 | panic("UNSUPPORTED") 34 | return nil, nil 35 | } 36 | 37 | // ////////////////////////////////////////////////////////////////////////////////// // 38 | 39 | // ❗ Temperature returns min, max and average temperature 40 | func (d *Device) Temperature() (float64, float64, float64) { 41 | panic("UNSUPPORTED") 42 | return 0.0, 0.0, 0.0 43 | } 44 | 45 | // ❗ String formats sensor data as a string 46 | func (s TempSensor) String() string { 47 | panic("UNSUPPORTED") 48 | return "" 49 | } 50 | 51 | // ////////////////////////////////////////////////////////////////////////////////// // 52 | -------------------------------------------------------------------------------- /system/sysctl/sysctl_darwin.go: -------------------------------------------------------------------------------- 1 | package sysctl 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "bytes" 12 | "fmt" 13 | "os/exec" 14 | "strings" 15 | ) 16 | 17 | // ////////////////////////////////////////////////////////////////////////////////// // 18 | 19 | // getParam reads kernel parameter from procfs 20 | func getParam(param string) (string, error) { 21 | output, err := exec.Command(binary, "-n", param).Output() 22 | 23 | if err != nil { 24 | return "", fmt.Errorf("Can't get kernel parameters from sysctl") 25 | } 26 | 27 | return strings.Trim(string(output), "\n\r"), err 28 | } 29 | 30 | // getParams reads all kernel parameters 31 | func getParams() (Params, error) { 32 | output, err := exec.Command(binary, "-a").Output() 33 | 34 | if err != nil { 35 | return nil, fmt.Errorf("Can't get kernel parameters from sysctl") 36 | } 37 | 38 | params := make(Params) 39 | buf := bytes.NewBuffer(output) 40 | 41 | for { 42 | line, err := buf.ReadString('\n') 43 | 44 | if err != nil { 45 | break 46 | } 47 | 48 | name, value, ok := strings.Cut(strings.Trim(line, "\n\r"), ": ") 49 | 50 | if ok { 51 | params[name] = value 52 | } 53 | } 54 | 55 | return params, nil 56 | } 57 | -------------------------------------------------------------------------------- /system/sysctl/sysctl_linux.go: -------------------------------------------------------------------------------- 1 | package sysctl 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "bytes" 12 | "fmt" 13 | "os" 14 | "os/exec" 15 | "strings" 16 | 17 | "github.com/essentialkaos/ek/v13/path" 18 | ) 19 | 20 | // ////////////////////////////////////////////////////////////////////////////////// // 21 | 22 | // getParam reads kernel parameter from procfs 23 | func getParam(param string) (string, error) { 24 | p, err := os.ReadFile(path.Clean(path.Join( 25 | procFS, strings.ReplaceAll(param, ".", "/"), 26 | ))) 27 | 28 | if err != nil { 29 | return "", fmt.Errorf("Can't read parameter %q: %w", param, err) 30 | } 31 | 32 | return strings.Trim(string(p), "\n\r"), nil 33 | } 34 | 35 | // getParams reads all kernel parameters 36 | func getParams() (Params, error) { 37 | output, err := exec.Command(binary, "-a").Output() 38 | 39 | if err != nil { 40 | return nil, fmt.Errorf("Can't get kernel parameters from sysctl") 41 | } 42 | 43 | params := make(Params) 44 | buf := bytes.NewBuffer(output) 45 | 46 | for { 47 | line, err := buf.ReadString('\n') 48 | 49 | if err != nil { 50 | break 51 | } 52 | 53 | name, value, ok := strings.Cut(strings.Trim(line, "\n\r"), " = ") 54 | 55 | if ok { 56 | params[name] = value 57 | } 58 | } 59 | 60 | return params, nil 61 | } 62 | -------------------------------------------------------------------------------- /system/sysctl/sysctl_stubs.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !darwin 2 | // +build !linux,!darwin 3 | 4 | // Package sysctl provides methods for reading kernel parameters 5 | package sysctl 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | // Params contains all kernel parameters 15 | type Params map[string]string 16 | 17 | // ////////////////////////////////////////////////////////////////////////////////// // 18 | 19 | // All returns all kernel parameters 20 | func All() (Params, error) { 21 | return nil, nil 22 | } 23 | 24 | // Get returns kernel parameter value as a string 25 | func Get(param string) (string, error) { 26 | return "", nil 27 | } 28 | 29 | // GetI returns kernel parameter value as an int 30 | func GetI(param string) (int, error) { 31 | return 0, nil 32 | } 33 | 34 | // GetI64 returns kernel parameter value as an int64 35 | func GetI64(param string) (int64, error) { 36 | return 0, nil 37 | } 38 | 39 | // ////////////////////////////////////////////////////////////////////////////////// // 40 | 41 | // Get returns kernel parameter value as a string 42 | func (p Params) Get(name string) string { 43 | return "" 44 | } 45 | 46 | // GetI returns kernel parameter value as an int 47 | func (p Params) GetI(param string) (int, error) { 48 | return 0, nil 49 | } 50 | 51 | // GetI64 returns kernel parameter value as an int64 52 | func (p Params) GetI64(param string) (int64, error) { 53 | return 0, nil 54 | } 55 | -------------------------------------------------------------------------------- /system/user_bsd.go: -------------------------------------------------------------------------------- 1 | //go:build darwin || freebsd 2 | // +build darwin freebsd 3 | 4 | package system 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | import ( 14 | "syscall" 15 | "time" 16 | ) 17 | 18 | // ////////////////////////////////////////////////////////////////////////////////// // 19 | 20 | // getTimes is copy of fsutil.GetTimes 21 | func getTimes(path string) (time.Time, time.Time, time.Time, error) { 22 | if path == "" { 23 | return time.Time{}, time.Time{}, time.Time{}, ErrEmptyPath 24 | } 25 | 26 | var stat = &syscall.Stat_t{} 27 | 28 | err := syscall.Stat(path, stat) 29 | 30 | if err != nil { 31 | return time.Time{}, time.Time{}, time.Time{}, err 32 | } 33 | 34 | return time.Unix(int64(stat.Atimespec.Sec), int64(stat.Atimespec.Nsec)), 35 | time.Unix(int64(stat.Mtimespec.Sec), int64(stat.Mtimespec.Nsec)), 36 | time.Unix(int64(stat.Ctimespec.Sec), int64(stat.Ctimespec.Nsec)), 37 | nil 38 | } 39 | -------------------------------------------------------------------------------- /system/user_linux.go: -------------------------------------------------------------------------------- 1 | package system 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "syscall" 12 | "time" 13 | ) 14 | 15 | // ////////////////////////////////////////////////////////////////////////////////// // 16 | 17 | // getTimes is copy of fsutil.GetTimes 18 | func getTimes(path string) (time.Time, time.Time, time.Time, error) { 19 | if path == "" { 20 | return time.Time{}, time.Time{}, time.Time{}, ErrEmptyPath 21 | } 22 | 23 | var stat = &syscall.Stat_t{} 24 | 25 | err := syscall.Stat(path, stat) 26 | 27 | if err != nil { 28 | return time.Time{}, time.Time{}, time.Time{}, err 29 | } 30 | 31 | return time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec)), 32 | time.Unix(int64(stat.Mtim.Sec), int64(stat.Mtim.Nsec)), 33 | time.Unix(int64(stat.Ctim.Sec), int64(stat.Ctim.Nsec)), 34 | nil 35 | } 36 | -------------------------------------------------------------------------------- /terminal/terminal_test.go: -------------------------------------------------------------------------------- 1 | package terminal 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | "testing" 13 | 14 | . "github.com/essentialkaos/check" 15 | ) 16 | 17 | // ////////////////////////////////////////////////////////////////////////////////// // 18 | 19 | func Test(t *testing.T) { TestingT(t) } 20 | 21 | type TerminalSuite struct{} 22 | 23 | // ////////////////////////////////////////////////////////////////////////////////// // 24 | 25 | var _ = Suite(&TerminalSuite{}) 26 | 27 | // ////////////////////////////////////////////////////////////////////////////////// // 28 | 29 | func (s *TerminalSuite) TestMessage(c *C) { 30 | Error("Test %s", "Error") 31 | Warn("Test %s", "Warn") 32 | Info("Test %s", "Info") 33 | 34 | Error(fmt.Errorf("Error")) 35 | Error([]string{"Error"}) 36 | } 37 | 38 | func (s *TerminalSuite) TestMessageWithPrefix(c *C) { 39 | ErrorPrefix = "▲ " 40 | WarnPrefix = "▲ " 41 | InfoPrefix = "▲ " 42 | 43 | Error("Test %s\nMessage\n", "Error") 44 | Warn("Test %s\nMessage\n", "Warn") 45 | Info("Test %s\nMessage\n", "Info") 46 | 47 | ErrorPrefix = "" 48 | WarnPrefix = "" 49 | InfoPrefix = "" 50 | } 51 | 52 | func (s *TerminalSuite) TestAction(c *C) { 53 | PrintActionMessage("Testing") 54 | PrintActionStatus(0) 55 | 56 | PrintActionMessage("Testing") 57 | PrintActionStatus(1) 58 | 59 | PrintActionMessage("Testing") 60 | PrintActionStatus(2) 61 | 62 | PrintActionMessage("Testing") 63 | PrintActionStatus(3) 64 | } 65 | -------------------------------------------------------------------------------- /terminal/tty/example_test.go: -------------------------------------------------------------------------------- 1 | package tty 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | func ExampleIsTTY() { 17 | if IsTTY() { 18 | fmt.Println("Output is TTY") 19 | } else { 20 | fmt.Println("Output is not TTY") 21 | } 22 | } 23 | 24 | func ExampleIsTMUX() { 25 | isTmux, err := IsTMUX() 26 | 27 | if err != nil { 28 | panic(err.Error()) 29 | } 30 | 31 | if isTmux { 32 | fmt.Println("App works in tmux") 33 | } else { 34 | fmt.Println("App works in bare terminal") 35 | } 36 | } 37 | 38 | func ExampleIsSystemd() { 39 | if IsSystemd() { 40 | fmt.Println("This process started by systemd") 41 | } 42 | } 43 | 44 | func ExampleGetSize() { 45 | width, height := GetSize() 46 | 47 | if width == -1 && height == -1 { 48 | fmt.Println("Can't detect window size") 49 | return 50 | } 51 | 52 | fmt.Printf("Window size: %d x %d\n", width, height) 53 | } 54 | 55 | func ExampleGetWidth() { 56 | width := GetWidth() 57 | 58 | if width == -1 { 59 | fmt.Println("Can't detect window size") 60 | return 61 | } 62 | 63 | fmt.Printf("Window width: %d\n", width) 64 | } 65 | 66 | func ExampleGetHeight() { 67 | height := GetHeight() 68 | 69 | if height == -1 { 70 | fmt.Println("Can't detect window size") 71 | return 72 | } 73 | 74 | fmt.Printf("Window height: %d\n", height) 75 | } 76 | -------------------------------------------------------------------------------- /terminal/tty/size_posix.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | // +build !windows 3 | 4 | package tty 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | import ( 14 | "os" 15 | "syscall" 16 | "unsafe" 17 | ) 18 | 19 | // ////////////////////////////////////////////////////////////////////////////////// // 20 | 21 | type winsize struct { 22 | rows uint16 23 | cols uint16 24 | xpixels uint16 25 | ypixels uint16 26 | } 27 | 28 | // ////////////////////////////////////////////////////////////////////////////////// // 29 | 30 | // tty is a path to TTY device file 31 | var tty = "/dev/tty" 32 | 33 | // ////////////////////////////////////////////////////////////////////////////////// // 34 | 35 | // GetSize returns window width and height 36 | func GetSize() (int, int) { 37 | t, err := os.OpenFile(tty, syscall.O_RDONLY, 0) 38 | 39 | if err != nil { 40 | return -1, -1 41 | } 42 | 43 | var sz winsize 44 | 45 | _, _, _ = syscall.Syscall( 46 | syscall.SYS_IOCTL, t.Fd(), 47 | uintptr(syscall.TIOCGWINSZ), 48 | uintptr(unsafe.Pointer(&sz)), 49 | ) 50 | 51 | return int(sz.cols), int(sz.rows) 52 | } 53 | 54 | // GetWidth returns window width 55 | func GetWidth() int { 56 | w, _ := GetSize() 57 | return w 58 | } 59 | 60 | // GetHeight returns window height 61 | func GetHeight() int { 62 | _, h := GetSize() 63 | return h 64 | } 65 | -------------------------------------------------------------------------------- /terminal/tty/tmux_darwin.go: -------------------------------------------------------------------------------- 1 | //go:build darwin 2 | // +build darwin 3 | 4 | package tty 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | // isTmuxAncestor returns true if the current process is an ancestor of tmux 14 | func isTmuxAncestor() (bool, error) { 15 | return false, nil 16 | } 17 | -------------------------------------------------------------------------------- /terminal/tty/tmux_linux.go: -------------------------------------------------------------------------------- 1 | //go:build linux 2 | // +build linux 3 | 4 | package tty 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | import ( 14 | "errors" 15 | "os" 16 | "strconv" 17 | "strings" 18 | 19 | "github.com/essentialkaos/ek/v13/strutil" 20 | ) 21 | 22 | // ////////////////////////////////////////////////////////////////////////////////// // 23 | 24 | var procFS = "/proc" 25 | 26 | // ////////////////////////////////////////////////////////////////////////////////// // 27 | 28 | // isTmuxAncestor returns true if the current process is an ancestor of tmux 29 | func isTmuxAncestor() (bool, error) { 30 | pid := strconv.Itoa(os.Getppid()) 31 | 32 | for { 33 | statFile := procFS + "/" + pid + "/stat" 34 | statData, err := os.ReadFile(statFile) 35 | 36 | if err != nil { 37 | return false, errors.New("Can't check process tree for tmux server") 38 | } 39 | 40 | statString := string(statData) 41 | processName := strutil.ReadField(statString, 1, false, ' ') 42 | 43 | if strings.HasPrefix(processName, "(tmux:") { 44 | return true, nil 45 | } 46 | 47 | parentPID := strutil.ReadField(statString, 3, false, ' ') 48 | 49 | if parentPID == "1" || parentPID == "0" { 50 | break 51 | } 52 | 53 | pid = parentPID 54 | } 55 | 56 | return false, nil 57 | } 58 | -------------------------------------------------------------------------------- /terminal/tty/tty_posix.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | // +build !windows 3 | 4 | // Package tty provides methods for working with TTY 5 | package tty 6 | 7 | // ////////////////////////////////////////////////////////////////////////////////// // 8 | // // 9 | // Copyright (c) 2025 ESSENTIAL KAOS // 10 | // Apache License, Version 2.0 // 11 | // // 12 | // ////////////////////////////////////////////////////////////////////////////////// // 13 | 14 | import ( 15 | "os" 16 | ) 17 | 18 | // ////////////////////////////////////////////////////////////////////////////////// // 19 | 20 | var stdout, _ = os.Stdout.Stat() 21 | 22 | // ////////////////////////////////////////////////////////////////////////////////// // 23 | 24 | // IsTTY returns true if current output device is TTY 25 | func IsTTY() bool { 26 | if stdout.Mode()&os.ModeCharDevice == 0 && !IsFakeTTY() { 27 | return false 28 | } 29 | 30 | return true 31 | } 32 | 33 | // IsTMUX returns true if we are currently working in tmux 34 | func IsTMUX() (bool, error) { 35 | if os.Getenv("TMUX") != "" { 36 | return true, nil 37 | } 38 | 39 | return isTmuxAncestor() 40 | } 41 | 42 | // IsFakeTTY returns true is fake TTY is used 43 | func IsFakeTTY() bool { 44 | return os.Getenv("FAKETTY") != "" 45 | } 46 | 47 | // IsSystemd returns true if process started by systemd 48 | func IsSystemd() bool { 49 | return os.Getppid() == 1 50 | } 51 | 52 | // ////////////////////////////////////////////////////////////////////////////////// // 53 | -------------------------------------------------------------------------------- /terminal/tty/tty_stubs.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !darwin 2 | // +build !linux,!darwin 3 | 4 | package tty 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | // ❗ IsTTY returns true if current output device is TTY 14 | func IsTTY() bool { 15 | panic("UNSUPPORTED") 16 | } 17 | 18 | // ❗ IsFakeTTY returns true is fake TTY is used 19 | func IsFakeTTY() bool { 20 | panic("UNSUPPORTED") 21 | } 22 | 23 | // ❗ IsTMUX returns true if we are currently working in tmux 24 | func IsTMUX() (bool, error) { 25 | panic("UNSUPPORTED") 26 | } 27 | 28 | // ❗ IsSystemd returns true if process started by systemd 29 | func IsSystemd() bool { 30 | panic("UNSUPPORTED") 31 | } 32 | 33 | // ❗ GetSize returns window width and height 34 | func GetSize() (int, int) { 35 | panic("UNSUPPORTED") 36 | } 37 | 38 | // ❗ GetWidth returns window width 39 | func GetWidth() int { 40 | panic("UNSUPPORTED") 41 | } 42 | 43 | // ❗ GetHeight returns window height 44 | func GetHeight() int { 45 | panic("UNSUPPORTED") 46 | } 47 | -------------------------------------------------------------------------------- /timeutil/fuzz.go: -------------------------------------------------------------------------------- 1 | //go:build gofuzz 2 | // +build gofuzz 3 | 4 | package timeutil 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | import ( 14 | "time" 15 | ) 16 | 17 | // ////////////////////////////////////////////////////////////////////////////////// // 18 | 19 | var fuzzTestDate = time.Now() 20 | 21 | // ////////////////////////////////////////////////////////////////////////////////// // 22 | 23 | func Fuzz(data []byte) int { 24 | f := Format(fuzzTestDate, string(data)) 25 | 26 | if f != "" { 27 | return 0 28 | } 29 | 30 | return 1 31 | } 32 | -------------------------------------------------------------------------------- /timeutil/timeutil_unix.go: -------------------------------------------------------------------------------- 1 | //go:build linux || freebsd || darwin 2 | // +build linux freebsd darwin 3 | 4 | package timeutil 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | import ( 14 | "os" 15 | "strings" 16 | ) 17 | 18 | // ////////////////////////////////////////////////////////////////////////////////// // 19 | 20 | // localZoneFile is path to link to current tz info file 21 | var localZoneFile = "/etc/localtime" 22 | 23 | // ////////////////////////////////////////////////////////////////////////////////// // 24 | 25 | // LocalTimezone returns name of local timezone 26 | func LocalTimezone() string { 27 | tzName := os.Getenv("TZ") 28 | 29 | if tzName != "" { 30 | return tzName 31 | } 32 | 33 | zoneFile, err := os.Readlink(localZoneFile) 34 | 35 | if err != nil { 36 | return "Local" 37 | } 38 | 39 | index := strings.Index(zoneFile, "zoneinfo/") 40 | 41 | if index == -1 { 42 | return "Local" 43 | } 44 | 45 | return zoneFile[index+9:] 46 | } 47 | -------------------------------------------------------------------------------- /timeutil/timeutil_unix_test.go: -------------------------------------------------------------------------------- 1 | //go:build linux || freebsd || darwin 2 | // +build linux freebsd darwin 3 | 4 | package timeutil 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | import ( 14 | "os" 15 | 16 | . "github.com/essentialkaos/check" 17 | ) 18 | 19 | // ////////////////////////////////////////////////////////////////////////////////// // 20 | 21 | func (s *TimeUtilSuite) TestLocalTimezone(c *C) { 22 | os.Unsetenv("TZ") 23 | c.Assert(LocalTimezone(), Not(Equals), "Local") 24 | 25 | os.Setenv("TZ", "Europe/Zurich") 26 | c.Assert(LocalTimezone(), Equals, "Europe/Zurich") 27 | os.Unsetenv("TZ") 28 | 29 | testDir := c.MkDir() 30 | os.Symlink("/usr/share/unknown", testDir+"/localtime") 31 | localZoneFile = testDir + "/localtime" 32 | 33 | c.Assert(LocalTimezone(), Equals, "Local") 34 | 35 | localZoneFile = "/_unknown_" 36 | c.Assert(LocalTimezone(), Equals, "Local") 37 | } 38 | -------------------------------------------------------------------------------- /timeutil/timeutil_windows.go: -------------------------------------------------------------------------------- 1 | package timeutil 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "golang.org/x/sys/windows/registry" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | // registryKey is key of registry record with TZ data 17 | var registryKey = `SYSTEM\CurrentControlSet\Control\TimeZoneInformation` 18 | 19 | // registryKeyName is name of registry key record 20 | var registryKeyName = "TimeZoneKeyName" 21 | 22 | // ////////////////////////////////////////////////////////////////////////////////// // 23 | 24 | // LocalTimezone returns name of local timezone 25 | func LocalTimezone() string { 26 | key, err := registry.OpenKey(registry.LOCAL_MACHINE, registryKey, registry.QUERY_VALUE) 27 | 28 | if err != nil { 29 | return "Local" 30 | } 31 | 32 | tzName, _, err := key.GetStringValue(registryKeyName) 33 | 34 | if err != nil { 35 | return "Local" 36 | } 37 | 38 | return tzName 39 | } 40 | -------------------------------------------------------------------------------- /timeutil/timeutil_windows_test.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | // +build windows 3 | 4 | package timeutil 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | import ( 14 | . "github.com/essentialkaos/check" 15 | ) 16 | 17 | // ////////////////////////////////////////////////////////////////////////////////// // 18 | 19 | func (s *TimeUtilSuite) TestLocalTimezone(c *C) { 20 | c.Assert(LocalTimezone(), Not(Equals), "Local") 21 | 22 | registryKeyName = "Unknown" 23 | c.Assert(LocalTimezone(), Equals, "Local") 24 | 25 | registryKey = "Unknown" 26 | c.Assert(LocalTimezone(), Equals, "Local") 27 | } 28 | -------------------------------------------------------------------------------- /timeutil/tinydate.go: -------------------------------------------------------------------------------- 1 | package timeutil 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "time" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | // Date is tiny date 17 | type Date uint32 18 | 19 | // ////////////////////////////////////////////////////////////////////////////////// // 20 | 21 | // StartDate contains start date timestamp 22 | var StartDate = uint32(1322611200) 23 | 24 | // ////////////////////////////////////////////////////////////////////////////////// // 25 | 26 | // TinyDate creates tiny date struct by timestamp 27 | func TinyDate(t int64) Date { 28 | return Date(uint32(t) - StartDate) 29 | } 30 | 31 | // Unix returns unix timestamp 32 | func (d Date) Unix() int64 { 33 | return int64(StartDate + uint32(d)) 34 | } 35 | 36 | // Time returns time struct 37 | func (d Date) Time() time.Time { 38 | return time.Unix(int64(uint32(d)+StartDate), 0) 39 | } 40 | -------------------------------------------------------------------------------- /usage/completion/bash/examples_test.go: -------------------------------------------------------------------------------- 1 | package bash 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | 13 | "github.com/essentialkaos/ek/v13/usage" 14 | ) 15 | 16 | // ////////////////////////////////////////////////////////////////////////////////// // 17 | 18 | func ExampleGenerate() { 19 | info := usage.NewInfo() 20 | 21 | info.AddCommand("test", "Test data") 22 | info.AddCommand("clean", "Clean data") 23 | 24 | info.AddOption("d:dir", "Path to working directory", "dir") 25 | 26 | info.BoundOptions("test", "d:dir") 27 | info.BoundOptions("clean", "d:dir") 28 | 29 | info.AddOption("nc:no-color", "Disable colors in output") 30 | info.AddOption("h:help", "Show this help message") 31 | info.AddOption("v:version", "Show version") 32 | 33 | fmt.Println(Generate(info, "app", "txt")) 34 | } 35 | -------------------------------------------------------------------------------- /usage/completion/fish/examples_test.go: -------------------------------------------------------------------------------- 1 | package fish 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | 13 | "github.com/essentialkaos/ek/v13/usage" 14 | ) 15 | 16 | // ////////////////////////////////////////////////////////////////////////////////// // 17 | 18 | func ExampleGenerate() { 19 | info := usage.NewInfo() 20 | 21 | info.AddCommand("test", "Test data") 22 | info.AddCommand("clean", "Clean data") 23 | 24 | info.AddOption("d:dir", "Path to working directory", "dir") 25 | 26 | info.BoundOptions("test", "d:dir") 27 | info.BoundOptions("clean", "d:dir") 28 | 29 | info.AddOption("nc:no-color", "Disable colors in output") 30 | info.AddOption("h:help", "Show this help message") 31 | info.AddOption("v:version", "Show version") 32 | 33 | fmt.Println(Generate(info, "app")) 34 | } 35 | -------------------------------------------------------------------------------- /usage/completion/zsh/examples_test.go: -------------------------------------------------------------------------------- 1 | package zsh 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | 13 | "github.com/essentialkaos/ek/v13/options" 14 | "github.com/essentialkaos/ek/v13/usage" 15 | ) 16 | 17 | // ////////////////////////////////////////////////////////////////////////////////// // 18 | 19 | func ExampleGenerate() { 20 | info := usage.NewInfo() 21 | 22 | info.AddCommand("test", "Test data") 23 | info.AddCommand("clean", "Clean data") 24 | 25 | info.AddOption("d:dir", "Path to working directory", "dir") 26 | 27 | info.BoundOptions("test", "d:dir") 28 | info.BoundOptions("clean", "d:dir") 29 | 30 | info.AddOption("nc:no-color", "Disable colors in output") 31 | info.AddOption("h:help", "Show this help message") 32 | info.AddOption("v:version", "Show version") 33 | 34 | opts := options.Map{ 35 | "d:dir": {}, 36 | "nc:no-color": {Type: options.BOOL}, 37 | "h:help": {Type: options.BOOL}, 38 | "v:version": {Type: options.BOOL}, 39 | } 40 | 41 | fmt.Println(Generate(info, opts, "app", "*.txt")) 42 | } 43 | -------------------------------------------------------------------------------- /uuid/example_test.go: -------------------------------------------------------------------------------- 1 | package uuid 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // ////////////////////////////////////////////////////////////////////////////////// // 15 | 16 | func ExampleUUID4() { 17 | fmt.Printf("UUID v4: %s\n", UUID4().String()) 18 | } 19 | 20 | func ExampleUUID5() { 21 | fmt.Printf("UUID v5: %s\n", UUID5(NsURL, "http://www.domain.com").String()) 22 | } 23 | 24 | func ExampleUUID7() { 25 | fmt.Printf("UUID v7: %s\n", UUID7().String()) 26 | } 27 | -------------------------------------------------------------------------------- /uuid/prefixed/example_test.go: -------------------------------------------------------------------------------- 1 | package prefixed 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "fmt" 12 | 13 | "github.com/essentialkaos/ek/v13/uuid" 14 | ) 15 | 16 | // ////////////////////////////////////////////////////////////////////////////////// // 17 | 18 | func ExampleEncode() { 19 | pu := Encode("user", uuid.UUID7()) 20 | 21 | fmt.Printf("UUID: %s\n", pu) 22 | } 23 | 24 | func ExampleDecode() { 25 | prefix, u, err := Decode("user.AZXm2EAle0im2Nloa94Wjg") 26 | 27 | fmt.Printf("Prefix: %s | UUID: %s | Error: %v\n", prefix, u, err) 28 | } 29 | -------------------------------------------------------------------------------- /uuid/prefixed/prefixed.go: -------------------------------------------------------------------------------- 1 | // Package prefixed contains methods for encoding/decoding prefixed UUID 2 | package prefixed 3 | 4 | // ////////////////////////////////////////////////////////////////////////////////// // 5 | // // 6 | // Copyright (c) 2025 ESSENTIAL KAOS // 7 | // Apache License, Version 2.0 // 8 | // // 9 | // ////////////////////////////////////////////////////////////////////////////////// // 10 | 11 | import ( 12 | "encoding/base64" 13 | "errors" 14 | "strings" 15 | 16 | "github.com/essentialkaos/ek/v13/uuid" 17 | ) 18 | 19 | // ////////////////////////////////////////////////////////////////////////////////// // 20 | 21 | // encoder is Base64 encoder 22 | var encoder = base64.StdEncoding.WithPadding(base64.NoPadding) 23 | 24 | // ////////////////////////////////////////////////////////////////////////////////// // 25 | 26 | // Encode creates Base64-encoded prefixed UUID 27 | func Encode(prefix string, uuid uuid.UUID) string { 28 | if prefix == "" || uuid.IsZero() { 29 | return "" 30 | } 31 | 32 | return prefix + "." + encoder.EncodeToString(uuid) 33 | } 34 | 35 | // Decode decodes prefixed UUID 36 | func Decode(prefixedUUID string) (string, uuid.UUID, error) { 37 | prefix, data, ok := strings.Cut(prefixedUUID, ".") 38 | 39 | switch { 40 | case !ok: 41 | return "", nil, errors.New("Prefixed UUID has no prefix") 42 | case prefix == "": 43 | return "", nil, errors.New("Prefixed UUID has empty prefix") 44 | case data == "": 45 | return "", nil, errors.New("Prefixed UUID has no UUID data") 46 | } 47 | 48 | u, err := encoder.DecodeString(data) 49 | 50 | if err != nil { 51 | return "", nil, errors.New("Can't decode UUID data: " + err.Error()) 52 | } 53 | 54 | return prefix, uuid.UUID(u), nil 55 | } 56 | -------------------------------------------------------------------------------- /uuid/uuid_test.go: -------------------------------------------------------------------------------- 1 | package uuid 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | import ( 11 | "testing" 12 | 13 | . "github.com/essentialkaos/check" 14 | ) 15 | 16 | // ////////////////////////////////////////////////////////////////////////////////// // 17 | 18 | func Test(t *testing.T) { TestingT(t) } 19 | 20 | type UUIDSuite struct{} 21 | 22 | // ////////////////////////////////////////////////////////////////////////////////// // 23 | 24 | var _ = Suite(&UUIDSuite{}) 25 | 26 | // ////////////////////////////////////////////////////////////////////////////////// // 27 | 28 | func (s *UUIDSuite) TestUUID4(c *C) { 29 | c.Assert(UUID4(), HasLen, 16) 30 | c.Assert(UUID4().String(), Not(Equals), "00000000-0000-0000-0000-000000000000") 31 | c.Assert(UUID4().IsZero(), Equals, false) 32 | } 33 | 34 | func (s *UUIDSuite) TestUUID5(c *C) { 35 | c.Assert(UUID5(NsURL, "TEST"), HasLen, 16) 36 | c.Assert(UUID5(NsURL, "TEST").String(), Not(Equals), "00000000-0000-0000-0000-000000000000") 37 | c.Assert(UUID5(NsURL, "TEST").IsZero(), Equals, false) 38 | } 39 | 40 | func (s *UUIDSuite) TestUUID7(c *C) { 41 | c.Assert(UUID7(), HasLen, 16) 42 | c.Assert(UUID7().String(), Not(Equals), "00000000-0000-0000-0000-000000000000") 43 | c.Assert(UUID7().IsZero(), Equals, false) 44 | } 45 | 46 | func (s *UUIDSuite) BenchmarkUUID4(c *C) { 47 | for range c.N { 48 | UUID4() 49 | } 50 | } 51 | 52 | func (s *UUIDSuite) BenchmarkUUID5(c *C) { 53 | for range c.N { 54 | UUID5(NsURL, "TEST") 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /version.go: -------------------------------------------------------------------------------- 1 | package ek 2 | 3 | // ////////////////////////////////////////////////////////////////////////////////// // 4 | // // 5 | // Copyright (c) 2025 ESSENTIAL KAOS // 6 | // Apache License, Version 2.0 // 7 | // // 8 | // ////////////////////////////////////////////////////////////////////////////////// // 9 | 10 | // VERSION is current ek package version 11 | const VERSION = "13.28.0" 12 | -------------------------------------------------------------------------------- /version/fuzz.go: -------------------------------------------------------------------------------- 1 | //go:build gofuzz 2 | // +build gofuzz 3 | 4 | package version 5 | 6 | // ////////////////////////////////////////////////////////////////////////////////// // 7 | // // 8 | // Copyright (c) 2025 ESSENTIAL KAOS // 9 | // Apache License, Version 2.0 // 10 | // // 11 | // ////////////////////////////////////////////////////////////////////////////////// // 12 | 13 | func Fuzz(data []byte) int { 14 | _, err := Parse(string(data)) 15 | 16 | if err != nil { 17 | return 0 18 | } 19 | 20 | return 1 21 | } 22 | --------------------------------------------------------------------------------