Full Code of jftuga/less-Windows for AI

master e25a4c83c8b9 cached
9 files
13.1 KB
3.6k tokens
9 symbols
1 requests
Download .txt
Repository: jftuga/less-Windows
Branch: master
Commit: e25a4c83c8b9
Files: 9
Total size: 13.1 KB

Directory structure:
gitextract_23kj5y12/

├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── comment.yml
│       └── nightly.yml
├── .gitignore
├── LICENSE
├── README.md
├── build.py
├── shared.py
└── version_compare.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "daily"



================================================
FILE: .github/workflows/comment.yml
================================================
on:
  workflow_dispatch:
    inputs:
      issue_number:
        required: true
      owner:
        required: true
      repo:
        required: true
      body:
        required: true

jobs:
  comment:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/github-script@v9
        with:
          github-token: ${{ secrets.WINGET_TOKEN }}
          script: |
            github.rest.issues.createComment({
              issue_number: ${{ github.event.inputs.issue_number }},
              owner: '${{ github.event.inputs.owner }}',
              repo: '${{ github.event.inputs.repo }}',
              body: '${{ github.event.inputs.body }}'
            })


================================================
FILE: .github/workflows/nightly.yml
================================================
name: nightly

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]
  schedule:
    - cron: '0 0 * * *'
  workflow_dispatch:

jobs:
  checkver:
    runs-on: ubuntu-latest

    outputs:
      new_version: ${{ steps.check_new_version.outputs.new_version }}

    steps:
    - uses: actions/checkout@v6
    - uses: actions/setup-python@v6
    - name: Compare versions
      run: python version_compare.py
    - name: Check if new version exists
      id: check_new_version
      run: |
        # If new.txt exists and is not empty
        if [ -s "new.txt"  ]; then
          NEW_VERSION=$(cat new.txt)
          echo "New version is $NEW_VERSION"
          echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
        fi

  build:
    runs-on: windows-${{ matrix.arch == 'arm' && '2022' || 'latest' }}
    needs: checkver
    if: ${{ needs.checkver.outputs.new_version }}
    strategy:
      matrix:
        arch: [x64, x86, arm64, arm]

    steps:
    - uses: actions/checkout@v6
    - uses: actions/setup-python@v6
    - uses: ilammy/msvc-dev-cmd@v1
      with:
        arch: ${{ matrix.arch != 'x64' && 'amd64_' || '' }}${{ matrix.arch }}
        sdk: ${{ matrix.arch == 'arm' && '10.0.22621.0' || '' }}

    - name: Build
      run: python .\build.py

    - name: Upload less to artifact
      uses: actions/upload-artifact@v7
      with:
        name: less-${{ matrix.arch }}
        path: |
          less.exe
          lesskey.exe

  release:
    needs: [checkver, build]
    if: ${{ github.event_name != 'pull_request' }}
    runs-on: ubuntu-latest
    permissions:
      contents: write
      discussions: write

    steps:
    - name: Get all artifacts
      uses: actions/download-artifact@v8
    - name: Zip each artifact
      run: find . -type d ! -path . -execdir zip -9 -rj "{}.zip" "{}" \;

    - uses: octokit/request-action@v2.x
      id: get_workflow_runtime
      with:
        route: GET /repos/{owner}/{repo}/actions/runs/{run_id}
        owner: ${{ github.repository_owner }}
        repo: less-Windows
        run_id: ${{ github.run_id }}
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    - id: extract_major_version
      run: |
        MAJOR_VERSION=$(echo ${{ needs.checkver.outputs.new_version }} | cut -d. -f1)
        echo "major_version=$MAJOR_VERSION" >> $GITHUB_OUTPUT

    - uses: softprops/action-gh-release@v3
      with:
        files: '*.zip'
        body: |
          Built with GitHub Actions at ${{ fromJson(steps.get_workflow_runtime.outputs.data).updated_at }}

          Release notes can be found [here](http://greenwoodsoftware.com/less/news.${{ steps.extract_major_version.outputs.major_version }}.html).
        tag_name: less-v${{ needs.checkver.outputs.new_version }}
        discussion_category_name: Announcements
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  winget:
    name: Publish to WinGet
    needs: [checkver, release]
    runs-on: ubuntu-latest

    steps:
    - uses: vedantmgoyal9/winget-releaser@main
      with:
        identifier: jftuga.less
        version: ${{ needs.checkver.outputs.new_version }}
        release-tag: less-v${{ needs.checkver.outputs.new_version }}
        installers-regex: '\.zip$'
        token: ${{ secrets.WINGET_TOKEN }}


================================================
FILE: .gitignore
================================================
less-*/
less*.zip
compile.bat
download.html
__pycache__/


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2020 J Taylor

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# less-Windows [![nightly](https://github.com/jftuga/less-Windows/actions/workflows/nightly.yml/badge.svg)](https://github.com/jftuga/less-Windows/actions/workflows/nightly.yml)

GNU [less](https://en.wikipedia.org/wiki/Less_\(Unix\)) compiled for Windows from the [less source](http://greenwoodsoftware.com/less/) via GitHub Actions. New versions are being checked daily, and builds are compiled with the latest version of Visual Studio.

## Installation

Binaries for `less.exe` (and `lesskey.exe`) are provided on the [Releases Page](https://github.com/jftuga/less-Windows/releases). Download the appropriate one for your system. If you prefer to install less via a package manager, you can choose one of the following options:

### Winget

A new version is pushed to the upstream [winget-pkgs](https://github.com/microsoft/winget-pkgs) for every release:

```powershell
winget install jftuga.less
```

### Chocolatey

[less](https://community.chocolatey.org/packages/less) is available in the Community Repository:
```powershell
choco install less
```

### Scoop

[less](https://scoop.sh/#/apps?q=main%2Fless&s=0&d=1&o=true) is available in the Main bucket:
```powershell
scoop install less
```


================================================
FILE: build.py
================================================
#!/usr/bin/env python3

r"""
builder.py
-John Taylor
May-13-2020

Download and compile GNU less with Visual Studio
less.exe and lesskey.exe are created
"""

import os
import os.path
import shutil
import subprocess
import sys
import time
import urllib.request
import zipfile
from shared import download_less_web_page, get_latest_version_url, LESSURL


def download_and_save(url: str) -> bool:
    """Download the less .zip file and save it to the current directory
    """

    # something like less-561.zip
    archive = url.split("/")[-1]
    if os.path.exists(archive):
        sz = os.stat(archive).st_size
        print("File already exists: %s with size: %d" % (archive, sz))
        return archive

    try:
        urllib.request.urlretrieve(url, archive)
    except:
        return False

    return archive


def extract_archive(archive: str) -> str:
    """Unzip the archive file, remove preexisting directory
    """

    # given "less-561.zip", return "less-561
    zip_dest = os.path.splitext(archive)[0]

    if os.path.exists(zip_dest):
        print("Removing preexisting directory: %s" % (zip_dest))
        try:
            shutil.rmtree(zip_dest)
            time.sleep(1)
        except:
            return False
    try:
        with zipfile.ZipFile(archive, "r") as z:
            z.extractall(".")
    except:
        return False

    return zip_dest


def create_compile_batchfile(archive_dest: str):
    """Create a .bat file containing environment setup
    and nmake compile commands
    """

    bat = "compile.bat"
    try:
        with open(bat, "w") as fp:
            fp.write("@echo off\n")
            fp.write("cd %s\n" % (archive_dest))
            fp.write("nmake /f Makefile.wnm\n")
            fp.write("copy /y less.exe ..\n")
            fp.write("copy /y lesskey.exe ..\n")
    except:
        return False

    return bat


def main():
    if not (page := download_less_web_page()):
        print("Unable to download URL: %s" % (LESSURL))
        sys.exit(10)
        return

    version, url = get_latest_version_url(page)
    if version is None:
        print("Unable to extract version from: %s" % (LESSURL), file=sys.stderr)
        sys.exit(20)

    if not (archive := download_and_save(url)):
        print("Unable to download file: %s" % (url), file=sys.stderr)
        sys.exit(30)

    if not (archive_dest := extract_archive(archive)):
        print("Unable to unzip archive: %s" % (archive), file=sys.stderr)
        sys.exit(40)

    if not (cmd := create_compile_batchfile(archive_dest)):
        print("Unable to create batch file", file=sys.stderr)
        sys.exit(50)

    result = subprocess.run((cmd,), shell=True, capture_output=True)
    if result.returncode > 0:
        err = result.stderr.decode("utf-8")
        out = result.stdout.decode("utf-8")
        print("Compile failed:\n%s\n\n%s\n" % (out, err))
        sys.exit(60)


if "__main__" == __name__:
    main()

# end of script


================================================
FILE: shared.py
================================================
#!/usr/bin/env python3

r"""
shared.py
-John Taylor
May-14-2020

Functions shared between build.py and version_compare.py
"""

import re
import time
import urllib.request

LESSURL = "http://greenwoodsoftware.com/less/download.html"
version_url_re = re.compile(r"""Download <strong>RECOMMENDED</strong> version (.*?) """, re.M | re.S | re.I)
NEWFILE = "new.txt"


def download_less_web_page() -> str:
    """Download LESSURL and save the contents to fname

    Returns:
        An in-memory version of the downloaded web page
    """

    fname = "download.html"
    try:
        urllib.request.urlretrieve(LESSURL, fname)
        time.sleep(1)
    except:
        return False

    try:
        with open(fname) as fp:
            page = fp.read()
    except:
        return False

    return page


def get_latest_version_url(page: str) -> tuple:
    """Return the URL for the "RECOMMENDED version"

    Args:
        page: an HTML web page, provided in LESSURL

    Returns:
        A tuple containing: (version number, zip archive URL)
        Ex: 551, http://greenwoodsoftware.com/less/less-551.zip
    """

    match = version_url_re.findall(page)
    if not len(match):
        return (None, None)

    version = match[0]
    archive = "less-%s.zip" % version
    url = LESSURL.replace("download.html", archive)
    return version, url


================================================
FILE: version_compare.py
================================================
#!/usr/bin/env python3

r"""
version_compare.py
-John Taylor
May-14-2020

Compare local github version with less web site
"""

import json
import urllib.request
import re
import sys
from shared import download_less_web_page, get_latest_version_url, LESSURL, NEWFILE

LOCALURL = "https://api.github.com/repos/jftuga/less-Windows/releases"


def download_local_web_page() -> str:
    """Download and return JSON from LOCALURL
    """
    try:
        with urllib.request.urlopen(LOCALURL) as f:
            page = f.read()
    except:
        return False

    page = page.decode("utf-8")
    return page


def get_latest_local_version(page: str) -> str:
    """Extract and return the lastest release version from a JSON page
       Ex: 561
    """
    try:
        j = json.loads(page)
    except:
        return False

    if not len(j):
        return "500"

    newest = j[0]
    print(f'{newest["tag_name"]=}')
    # The initial version is different than future versions
    if "v560" == newest["tag_name"]:
        return "560"

    # given less-v561.17, return 561
    release_version = newest["tag_name"][6:11]
    if release_version.endswith(".0"):
        release_version = re.sub(r"\.0$", "", release_version)
    print(f'{release_version=}')
    return release_version


def main():
    """Write to new.txt when a new version needs to be downloaded
    """
    if not (page := download_local_web_page()):
        print("Unable to download URL: %s" % (LOCALURL))
        sys.exit(10)

    if not (local_version := get_latest_local_version(page)):
        print("Unable to extract version from URL: %s" % (LOCALURL))
        sys.exit(20)

    if not (page := download_less_web_page()):
        print("Unable to download URL: %s" % (LESSURL))
        sys.exit(30)
        return

    remote_version, _ = get_latest_version_url(page)
    if remote_version is None:
        print("Unable to extract version from: %s" % (LESSURL), file=sys.stderr)
        sys.exit(40)

    if remote_version == local_version:
        print(f"Versions are the same: remote_version: {remote_version}   local_version: {local_version}")
        return

    if float(local_version) >= float(remote_version):
        print(f"Local version is newer: local_version: {local_version}   remote_version: {remote_version}")
        sys.exit(120)

    print(f"Remote version is newer: remote_version: {remote_version}   local_version: {local_version}")
    print(f"Saving new version to file: {NEWFILE}")
    try:
        with open(NEWFILE, mode="w") as fp:
            fp.write("%s\n" % remote_version)
    except:
        print(f"Unable able to open file for writing: {NEWFILE}")
        sys.exit(50)


if "__main__" == __name__:
    main()
Download .txt
gitextract_23kj5y12/

├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── comment.yml
│       └── nightly.yml
├── .gitignore
├── LICENSE
├── README.md
├── build.py
├── shared.py
└── version_compare.py
Download .txt
SYMBOL INDEX (9 symbols across 3 files)

FILE: build.py
  function download_and_save (line 23) | def download_and_save(url: str) -> bool:
  function extract_archive (line 42) | def extract_archive(archive: str) -> str:
  function create_compile_batchfile (line 65) | def create_compile_batchfile(archive_dest: str):
  function main (line 84) | def main():

FILE: shared.py
  function download_less_web_page (line 20) | def download_less_web_page() -> str:
  function get_latest_version_url (line 43) | def get_latest_version_url(page: str) -> tuple:

FILE: version_compare.py
  function download_local_web_page (line 20) | def download_local_web_page() -> str:
  function get_latest_local_version (line 33) | def get_latest_local_version(page: str) -> str:
  function main (line 59) | def main():
Condensed preview — 9 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (14K chars).
[
  {
    "path": ".github/dependabot.yml",
    "chars": 125,
    "preview": "version: 2\r\nupdates:\r\n  - package-ecosystem: \"github-actions\"\r\n    directory: \"/\"\r\n    schedule:\r\n      interval: \"daily"
  },
  {
    "path": ".github/workflows/comment.yml",
    "chars": 664,
    "preview": "on:\n  workflow_dispatch:\n    inputs:\n      issue_number:\n        required: true\n      owner:\n        required: true\n    "
  },
  {
    "path": ".github/workflows/nightly.yml",
    "chars": 3268,
    "preview": "name: nightly\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n  schedule:\n    - cron: '0 "
  },
  {
    "path": ".gitignore",
    "chars": 57,
    "preview": "less-*/\nless*.zip\ncompile.bat\ndownload.html\n__pycache__/\n"
  },
  {
    "path": "LICENSE",
    "chars": 1065,
    "preview": "MIT License\n\nCopyright (c) 2020 J Taylor\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "README.md",
    "chars": 1199,
    "preview": "# less-Windows [![nightly](https://github.com/jftuga/less-Windows/actions/workflows/nightly.yml/badge.svg)](https://gith"
  },
  {
    "path": "build.py",
    "chars": 2953,
    "preview": "#!/usr/bin/env python3\n\nr\"\"\"\nbuilder.py\n-John Taylor\nMay-13-2020\n\nDownload and compile GNU less with Visual Studio\nless."
  },
  {
    "path": "shared.py",
    "chars": 1342,
    "preview": "#!/usr/bin/env python3\n\nr\"\"\"\nshared.py\n-John Taylor\nMay-14-2020\n\nFunctions shared between build.py and version_compare.p"
  },
  {
    "path": "version_compare.py",
    "chars": 2717,
    "preview": "#!/usr/bin/env python3\n\nr\"\"\"\nversion_compare.py\n-John Taylor\nMay-14-2020\n\nCompare local github version with less web sit"
  }
]

About this extraction

This page contains the full source code of the jftuga/less-Windows GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 9 files (13.1 KB), approximately 3.6k tokens, and a symbol index with 9 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!