From 184144aa2ca1781992b56224879154d32df87d15 Mon Sep 17 00:00:00 2001 From: ge Date: Wed, 21 Jan 2026 20:58:29 +0300 Subject: [PATCH] init --- .editorconfig | 8 +++ .gitattributes | 8 +++ .github/workflows/docs.yaml | 48 +++++++++++++++ .github/workflows/test.yaml | 24 ++++++++ .gitignore | 24 ++++++++ README.md | 31 ++++++++++ UNLICENSE | 22 +++++++ pathstr.v | 116 ++++++++++++++++++++++++++++++++++++ v.mod | 7 +++ 9 files changed, 288 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/workflows/docs.yaml create mode 100644 .github/workflows/test.yaml create mode 100644 .gitignore create mode 100644 README.md create mode 100644 UNLICENSE create mode 100644 pathstr.v create mode 100644 v.mod diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..01072ca --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.v] +indent_style = tab diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9a98968 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,8 @@ +* text=auto eol=lf +*.bat eol=crlf + +*.v linguist-language=V +*.vv linguist-language=V +*.vsh linguist-language=V +v.mod linguist-language=V +.vdocignore linguist-language=ignore diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml new file mode 100644 index 0000000..8a753c0 --- /dev/null +++ b/.github/workflows/docs.yaml @@ -0,0 +1,48 @@ +name: Docs +on: + push: + branches: [ "master" ] + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup V + run: | + wget -qO /tmp/v.zip https://github.com/vlang/v/releases/latest/download/v_linux.zip + unzip -q /tmp/v.zip -d /tmp + echo /tmp/v >> "$GITHUB_PATH" + + - name: Build docs + run: | + v doc -f html -m . + pushd _docs + ln -vs ${{ github.event.repository.name }}.html index.html + ls -alFh + popd + + - name: Upload static files as artifact + id: deployment + uses: actions/upload-pages-artifact@v3 + with: + path: _docs/ + + deploy: + needs: build + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + +permissions: + contents: read + pages: write + id-token: write diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..f9d8c51 --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,24 @@ +name: Tests +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + workflow_dispatch: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup V + run: | + wget -qO /tmp/v.zip https://github.com/vlang/v/releases/latest/download/v_linux.zip + unzip -q /tmp/v.zip -d /tmp + echo /tmp/v >> "$GITHUB_PATH" + + - name: Run tests + run: | + v -stats test . diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7e96262 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Binaries for programs and plugins +main +pathstring +*.exe +*.exe~ +*.so +*.dylib +*.dll + +# Ignore binary output folders +bin/ + +# Ignore common editor/system specific metadata +.DS_Store +.idea/ +.vscode/ +*.iml + +# ENV +.env + +# vweb and database +*.db +*.js diff --git a/README.md b/README.md new file mode 100644 index 0000000..53f056a --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +# Path Manupulations + +The `pathstr` module is a wrapper around the standard `os` module for working with paths. + +The idea is to represent a path as a string alias, allowing strings to be cast to paths and +back, and also transparently using the `Path` type everywhere a string is expected. + +Corresponding methods: + +| os function | pathstr alternative | +| --------------------------- | ------------------------ | +| `os.join_path()` | `Path.join()` | +| `os.dir()` | `Path.dir()` | +| `os.file_name()` | `Path.name()` | +| `os.file_ext()` | `Path.ext()` | +| `os.split_path()` | `Path.split()` | +| `os.expand_tilde_to_home()` | `Path.expand_tilde()` | +| `os.norm_path()` | `Path.normalized()` | +| `os.quoted_path()` | `Path.quoted()` | +| `os.abs_path()` | `Path.abs()` | +| `os.real_path()` | `Path.real()` | +| `os.exists()` | `Path.exists()` | +| `os.existing_path()` | `Path.existing()` | +| `os.is_abs_path()` | `Path.is_abs()` | +| `os.is_file()` | `Path.is_file()` | +| `os.is_link()` | `Path.is_link()` | +| `os.is_dir()` | `Path.is_dir()` | +| `os.is_dir_empty()` | `Path.is_dir_empty()` | +| `os.is_readable()` | `Path.is_readable()` | +| `os.is_writable()` | `Path.is_writable()` | +| `os.is_executable()` | `Path.is_executable()` | diff --git a/UNLICENSE b/UNLICENSE new file mode 100644 index 0000000..c91541e --- /dev/null +++ b/UNLICENSE @@ -0,0 +1,22 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. + +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and +successors. We intend this dedication to be an overt act of relinquishment in +perpetuity of all present and future rights to this software under copyright +law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/pathstr.v b/pathstr.v new file mode 100644 index 0000000..ed4e6e3 --- /dev/null +++ b/pathstr.v @@ -0,0 +1,116 @@ +module pathstr + +import os + +pub type Path = string + +// join joins the path parts with platform specific path separator. +pub fn (p Path) join(path ...string) Path { + return Path(os.join_path(p, ...path)) +} + +// dir returns a directory path from path e.g. `/a/b` from `/a/b/c`. +pub fn (p Path) dir() Path { + return Path(os.dir(p)) +} + +// name return a file or directory base name from path e.g. `c` from `/a/b/c/`, `b.txt` from `/a/b.txt`. +pub fn (p Path) name() string { + if p == '' { + return '.' + } + if p.contains_only(os.path_separator) { + return os.path_separator + } + if p.ends_with(os.path_separator) { + return os.base(p) + } + return os.file_name(p) +} + +// ext returns a file extension from path e.g. `.txt` from `/a/b.txt` +pub fn (p Path) ext() string { + return Path(os.file_ext(p)) +} + +// split splits path to dir, file name and extension (with dot). +pub fn (p Path) split() (string, string, string) { + return os.split_path(p) +} + +// expand_tilde expands tilde to absolute path of user home directory. +pub fn (p Path) expand_tilde() Path { + return Path(os.expand_tilde_to_home(p)) +} + +// normalized returns the path normalized by resolving backlinks (..), turning forward slashes +// into back slashes on a Windows system and eliminating: references to current directories (.), +// redundant path separators, the last path separator. +pub fn (p Path) normalized() Path { + return Path(os.norm_path(p)) +} + +// quoted returns a quoted version of the path, depending on the platform. +pub fn (p Path) quoted() string { + return os.quoted_path(p) +} + +// abs returns the absolute path. +pub fn (p Path) abs() Path { + return Path(os.abs_path(p)) +} + +// real returns the full absolute path for path, with all relative '../../', symlinks and so on resolved. +pub fn (p Path) real() Path { + return Path(os.real_path(p)) +} + +// exists returns true if file or directory exists in filesystem. +pub fn (p Path) exists() bool { + return os.exists(p) +} + +// existing returns the existing part of the given path. +pub fn (p Path) existing() !Path { + return Path(os.existing_path(p)) +} + +// is_abs returns true if path is absolute. +pub fn (p Path) is_abs() bool { + return os.is_abs_path(p) +} + +// is_file returns true if the path is file. +pub fn (p Path) is_file() bool { + return os.is_file(p) +} + +// is_file returns true if the path is symbolic link. +pub fn (p Path) is_symlink() bool { + return os.is_link(p) +} + +// is_dir returns true if the path is directory. +pub fn (p Path) is_dir() bool { + return os.is_dir(p) +} + +// is_dir_empty returns true if the directory in path is empty. +pub fn (p Path) is_dir_empty() bool { + return os.is_dir_empty(p) +} + +// is_readable returns true if the path can be accessed with read access mode. +pub fn (p Path) is_readable() bool { + return os.is_readable(p) +} + +// is_writable returns true if the path can be accessed with write access mode. +pub fn (p Path) is_writable() bool { + return os.is_writable(p) +} + +// is_executable returns true if the path can be accessed with execute access mode. +pub fn (p Path) is_executable() bool { + return os.is_executable(p) +} diff --git a/v.mod b/v.mod new file mode 100644 index 0000000..05e8497 --- /dev/null +++ b/v.mod @@ -0,0 +1,7 @@ +Module { + name: 'pathstr' + description: 'Path manipulations' + version: '0.1.0' + license: 'Unlicense' + dependencies: [] +}