From 9aaa198b6fb24c760fa0fbb3cb74ce4e2eb51c00 Mon Sep 17 00:00:00 2001 From: llerandi Date: Sun, 26 Jul 2026 13:47:25 +0200 Subject: [PATCH 1/2] feat: add basic java compile and run flow --- examples/HelloWorld.java | 6 ++ runner.bat | 108 +++++++++++++++++++++++++++++ runner.sh | 145 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 259 insertions(+) diff --git a/examples/HelloWorld.java b/examples/HelloWorld.java index e69de29..7423ef3 100644 --- a/examples/HelloWorld.java +++ b/examples/HelloWorld.java @@ -0,0 +1,6 @@ +public class HelloWorld { + public static void main(String[] args) { + System.out.println("Hello, World!"); + System.out.println("java-runner is working correctly."); + } +} diff --git a/runner.bat b/runner.bat index e69de29..dd77cd2 100644 --- a/runner.bat +++ b/runner.bat @@ -0,0 +1,108 @@ +@echo off +REM ───────────────────────────────────────────────────────────── +REM java-runner - run Java exercises without an IDE (Windows) +REM Usage: runner.bat [File.java] [--watch] +REM ───────────────────────────────────────────────────────────── + +setlocal EnableDelayedExpansion + +set "FILE=" +set "WATCH=false" + +REM ── Parse arguments ─────────────────────────────────────────── +for %%A in (%*) do ( + if "%%A"=="--watch" set "WATCH=true" + if "%%~xA"==".java" set "FILE=%%A" + if "%%A"=="--help" goto :help + if "%%A"=="-h" goto :help +) + +REM ── Auto-detect .java file ──────────────────────────────────── +if "%FILE%"=="" ( + set "count=0" + for %%F in (*.java) do ( + set "FILE=%%F" + set /a count+=1 + ) + + REM If none found in current dir, fall back to examples\ + if "!count!"=="0" ( + if exist examples\ ( + echo [INFO] No .java in current dir, searching examples\ + for %%F in (examples\*.java) do ( + set "FILE=%%F" + set /a count+=1 + ) + ) + ) + + if "!count!"=="0" ( + echo [ERROR] No .java file found in current directory or examples\ + exit /b 1 + ) + if !count! GTR 1 ( + echo [WARNING] Multiple .java files found. Please specify one: + for %%F in (*.java) do echo %%F + if exist examples\ for %%F in (examples\*.java) do echo %%F + exit /b 1 + ) +) + +REM ── Validate file exists ────────────────────────────────────── +if not exist "%FILE%" ( + echo [ERROR] File not found: %FILE% + exit /b 1 +) + +REM ── Watch mode ──────────────────────────────────────────────── +if "%WATCH%"=="true" ( + echo [WATCH] Watch mode enabled - save the file to rerun + :watchloop + call :run + echo [WATCH] Waiting for changes... Press Ctrl+C to stop. + REM Poll every 2 seconds (Windows has no native inotify) + timeout /t 2 /nobreak >nul + goto :watchloop +) + +call :run +exit /b + +REM ── Help ────────────────────────────────────────────────────── +:help +echo Usage: runner.bat [File.java] [--watch] +echo File.java Java file to compile and run +echo --watch Recompile and rerun every 2 seconds +exit /b + +REM ── Main run function ───────────────────────────────────────── +:run + for %%F in ("%FILE%") do set "CLASSNAME=%%~nF" + set "TMPDIR=%TEMP%\java-runner-%RANDOM%" + mkdir "%TMPDIR%" 2>nul + + echo. + echo [....] Compiling %CLASSNAME%.java... + + javac -d "%TMPDIR%" "%FILE%" 2>"%TMPDIR%\errors.txt" + if errorlevel 1 ( + echo [FAIL] Compilation failed: + echo. + type "%TMPDIR%\errors.txt" + rmdir /s /q "%TMPDIR%" + exit /b 1 + ) + + echo [ OK ] Compiled successfully + echo ───────────────────────── output ───────────────────────── + + set "START_TIME=%TIME%" + java -cp "%TMPDIR%" "%CLASSNAME%" + set "END_TIME=%TIME%" + + echo ─────────────────────────────────────────────────────────── + echo [ OK ] Done + echo. + + rmdir /s /q "%TMPDIR%" + exit /b diff --git a/runner.sh b/runner.sh index e69de29..237ba8b 100644 --- a/runner.sh +++ b/runner.sh @@ -0,0 +1,145 @@ +#!/usr/bin/env bash +# ───────────────────────────────────────────────────────────── +# java-runner - run Java exercises without an IDE +# Usage: ./runner.sh [File.java] [--watch] +# ───────────────────────────────────────────────────────────── + +set -euo pipefail + +# ── Colors ──────────────────────────────────────────────────── +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +CYAN='\033[0;36m' +RESET='\033[0m' + +# ── Detect OS ───────────────────────────────────────────────── +OS="$(uname -s)" +case "$OS" in + Linux*) PLATFORM="linux" ;; + Darwin*) PLATFORM="mac" ;; + *) PLATFORM="unknown" ;; +esac + +# ── Arguments ───────────────────────────────────────────────── +FILE="" +WATCH=false + +for arg in "$@"; do + case $arg in + --watch) WATCH=true ;; + *.java) FILE="$arg" ;; + --help|-h) + echo -e "Usage: ./runner.sh [File.java] [--watch]" + echo -e " File.java Java file to compile and run (optional if only one .java exists)" + echo -e " --watch Recompile and rerun on every file save" + exit 0 + ;; + esac +done + +# ── Auto-detect .java file ──────────────────────────────────── +if [[ -z "$FILE" ]]; then + mapfile -t found < <(find . -maxdepth 1 -name "*.java") + + # If none in current dir, fall back to examples/ + if [[ ${#found[@]} -eq 0 ]] && [[ -d "./examples" ]]; then + mapfile -t found < <(find ./examples -maxdepth 1 -name "*.java") + [[ ${#found[@]} -gt 0 ]] && echo -e "${YELLOW}⚠ No .java in current dir, searching examples/${RESET}" + fi + + if [[ ${#found[@]} -eq 1 ]]; then + FILE="${found[0]}" + elif [[ ${#found[@]} -eq 0 ]]; then + echo -e "${RED}✗ No .java file found in current directory or examples/${RESET}" + exit 1 + else + echo -e "${YELLOW}⚠ Multiple .java files found. Please specify one:${RESET}" + printf ' %s\n' "${found[@]}" + exit 1 + fi +fi + +# ── Validate file exists ────────────────────────────────────── +if [[ ! -f "$FILE" ]]; then + echo -e "${RED}✗ File not found: $FILE${RESET}" + exit 1 +fi + +# ── Main run function ───────────────────────────────────────── +run() { + local classname + classname=$(basename "$FILE" .java) + local tmpdir + tmpdir=$(mktemp -d) + + echo -e "" + echo -e "${CYAN}▶ Compiling ${classname}.java...${RESET}" + + # Compile - capture errors + if ! javac -d "$tmpdir" "$FILE" 2>"$tmpdir/errors.txt"; then + echo -e "${RED}✗ Compilation failed:${RESET}\n" + # Strip absolute path noise + sed "s|$PWD/||g" "$tmpdir/errors.txt" + rm -rf "$tmpdir" + return 1 + fi + + echo -e "${GREEN}✓ Compiled successfully${RESET}" + echo -e "${CYAN}───────────────────────── output ─────────────────────────${RESET}" + + # Run and measure time + local start + start=$(date +%s%N 2>/dev/null || date +%s) + java -cp "$tmpdir" "$classname" + local end + end=$(date +%s%N 2>/dev/null || date +%s) + + # Calculate elapsed (nanoseconds if available, else seconds) + local elapsed + if [[ ${#start} -gt 10 ]]; then + elapsed=$(( (end - start) / 1000000 )) + echo -e "${CYAN}───────────────────────────────────────────────────────────${RESET}" + echo -e "${GREEN}✓ Finished in ${elapsed}ms${RESET}\n" + else + elapsed=$(( end - start )) + echo -e "${CYAN}───────────────────────────────────────────────────────────${RESET}" + echo -e "${GREEN}✓ Finished in ${elapsed}s${RESET}\n" + fi + + rm -rf "$tmpdir" +} + +# ── Watch mode ──────────────────────────────────────────────── +if $WATCH; then + echo -e "${YELLOW}👁 Watch mode enabled - save the file to rerun${RESET}" + run || true + + if [[ "$PLATFORM" == "linux" ]]; then + if ! command -v inotifywait &>/dev/null; then + echo -e "${RED}✗ inotifywait not found. Install it with: sudo apt install inotify-tools${RESET}" + exit 1 + fi + while inotifywait -q -e close_write "$FILE"; do + echo -e "\n${YELLOW}↻ Change detected...${RESET}" + run || true + done + + elif [[ "$PLATFORM" == "mac" ]]; then + if ! command -v fswatch &>/dev/null; then + echo -e "${RED}✗ fswatch not found. Install it with: brew install fswatch${RESET}" + exit 1 + fi + fswatch -o "$FILE" | while read -r; do + echo -e "\n${YELLOW}↻ Change detected...${RESET}" + run || true + done + + else + echo -e "${RED}✗ Watch mode is not supported on this platform${RESET}" + exit 1 + fi + +else + run +fi From c4009e9b8697454e34ab2b1c728fa3a705889693 Mon Sep 17 00:00:00 2001 From: llerandi Date: Sun, 26 Jul 2026 13:47:45 +0200 Subject: [PATCH 2/2] feat: ci --- .github/workflows/ci.yaml | 93 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 .github/workflows/ci.yaml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..4d01a2d --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,93 @@ +name: CI + +on: + push: + branches: [ main, dev ] + pull_request: + branches: [ main ] + +jobs: + + # ── Linux ──────────────────────────────────────────────────── + test-linux: + name: Test on Linux + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + - name: Make runner executable + run: chmod +x runner.sh + + - name: Run HelloWorld + run: ./runner.sh examples/HelloWorld.java + + - name: Run FizzBuzz + run: ./runner.sh examples/FizzBuzz.java + + - name: Run auto-detect from examples/ + run: | + mkdir -p /tmp/test-autodetect + cp examples/HelloWorld.java /tmp/test-autodetect/ + cd /tmp/test-autodetect + bash "$GITHUB_WORKSPACE/runner.sh" + + # ── macOS ──────────────────────────────────────────────────── + test-macos: + name: Test on macOS + runs-on: macos-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + - name: Make runner executable + run: chmod +x runner.sh + + - name: Run HelloWorld + run: ./runner.sh examples/HelloWorld.java + + - name: Run FizzBuzz + run: ./runner.sh examples/FizzBuzz.java + + # ── Windows ────────────────────────────────────────────────── + test-windows: + name: Test on Windows + runs-on: windows-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + - name: Run HelloWorld + run: .\runner.bat examples\HelloWorld.java + + - name: Run FizzBuzz + run: .\runner.bat examples\FizzBuzz.java + + - name: Run auto-detect from examples\ + run: | + New-Item -ItemType Directory -Force -Path "$env:TEMP\test-autodetect" + Copy-Item examples\HelloWorld.java "$env:TEMP\test-autodetect\" + Set-Location "$env:TEMP\test-autodetect" + & "$env:GITHUB_WORKSPACE\runner.bat" + shell: pwsh