gui: support text input scrolling and rich text rise #464
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI Checks | |
| on: | |
| push: | |
| paths: | |
| - "**.v" | |
| - "**.vsh" | |
| - "**.c" | |
| - "**.h" | |
| - "**.m" | |
| - "**.md" | |
| - "**/ci.yml" | |
| - ".github/workflows/*.yml" | |
| pull_request: | |
| paths: | |
| - "**.v" | |
| - "**.vsh" | |
| - "**.c" | |
| - "**.h" | |
| - "**.m" | |
| - "**.md" | |
| - "**/ci.yml" | |
| - ".github/workflows/*.yml" | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} | |
| cancel-in-progress: true | |
| jobs: | |
| linting: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 25 | |
| env: | |
| VFLAGS: -no-parallel | |
| steps: | |
| - name: Install V | |
| id: install-v | |
| uses: vlang/setup-v@v1.4 | |
| with: | |
| check-latest: true | |
| - name: Install vglyph | |
| run: v install vglyph | |
| - name: Install C development dependencies (headers and libs) | |
| if: runner.os == 'Linux' | |
| run: v retry -- sudo apt -qq update && v retry -- sudo apt install libpango1.0-dev libfontconfig1-dev libfribidi-dev libharfbuzz-dev libfreetype-dev libgl1-mesa-dri xvfb libxcursor-dev libxi-dev libxrandr-dev freeglut3-dev dbus libdbus-1-dev libdbus-glib-1-2 libdbus-glib-1-dev | |
| - name: Install development dependencies on macos (headers and libs) | |
| if: runner.os == 'macOS' | |
| run: v retry -- brew install pango harfbuzz freetype2 | |
| - name: Checkout the gui module | |
| uses: actions/checkout@v6 | |
| with: | |
| path: gui | |
| fetch-depth: 0 | |
| - name: Verify formatting of changed V files | |
| if: github.event_name == 'pull_request' | |
| working-directory: gui | |
| run: | | |
| base_ref="${{ github.base_ref }}" | |
| git fetch --no-tags origin "$base_ref:refs/remotes/origin/$base_ref" | |
| git diff --name-only -z --diff-filter=ACMRT "origin/${base_ref}...HEAD" -- '*.v' '*.vsh' > /tmp/vfmt-files | |
| if [ ! -s /tmp/vfmt-files ]; then | |
| echo "No changed V/VSH files to format-check." | |
| exit 0 | |
| fi | |
| xargs -0 v fmt -verify -inprocess < /tmp/vfmt-files | |
| - name: Verify formatting | |
| if: github.event_name != 'pull_request' | |
| run: v fmt -verify -inprocess gui/ | |
| - name: Check formatting of MD files | |
| run: v check-md gui/ | |
| - name: Check syntax of changed example scripts | |
| if: github.event_name == 'pull_request' | |
| working-directory: gui | |
| run: | | |
| base_ref="${{ github.base_ref }}" | |
| files_list="${RUNNER_TEMP}/gui-example-syntax-files" | |
| git fetch --no-tags origin "$base_ref:refs/remotes/origin/$base_ref" | |
| git diff --name-only -z --diff-filter=ACMRT "origin/${base_ref}...HEAD" -- 'examples/*.vsh' > "$files_list" | |
| if [ ! -s "$files_list" ]; then | |
| echo "No changed example VSH scripts to syntax-check." | |
| exit 0 | |
| fi | |
| while IFS= read -r -d '' file; do | |
| v -check -W "$file" | |
| done < "$files_list" | |
| - name: Skip full examples syntax lint | |
| if: github.event_name != 'pull_request' | |
| run: echo "Skipping full examples syntax lint; example .v files are covered by compilation checks." | |
| compiling: | |
| strategy: | |
| matrix: | |
| os: [ubuntu-latest, macos-latest] | |
| fail-fast: true | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 25 | |
| env: | |
| VFLAGS: -no-parallel | |
| steps: | |
| - name: Install V | |
| id: install-v | |
| uses: vlang/setup-v@v1.4 | |
| with: | |
| check-latest: true | |
| - name: Install vglyph | |
| run: v install vglyph | |
| - name: Install X11/GL development dependencies (headers and libs) | |
| if: runner.os == 'Linux' | |
| run: v retry -- sudo apt -qq update && v retry -- sudo apt install libpango1.0-dev libfontconfig1-dev libfribidi-dev libharfbuzz-dev libfreetype-dev libgl1-mesa-dri xvfb libxcursor-dev libxi-dev libxrandr-dev freeglut3-dev dbus libdbus-1-dev libdbus-glib-1-2 libdbus-glib-1-dev | |
| - name: Install development dependencies on macos (headers and libs) | |
| if: runner.os == 'macOS' | |
| run: v retry -- brew install pango harfbuzz freetype2 | |
| - name: Checkout the gui module | |
| uses: actions/checkout@v6 | |
| with: | |
| path: gui | |
| fetch-depth: 0 | |
| - name: Run tests | |
| env: | |
| VFLAGS: -no-parallel -cc clang | |
| run: | | |
| test_manifest="${RUNNER_TEMP}/gui-test-files" | |
| git -C gui ls-files '*_test.v' | LC_ALL=C sort > "$test_manifest" | |
| test_count="$(wc -l < "$test_manifest" | tr -d ' ')" | |
| echo "Test files: $test_count" | |
| i=0 | |
| while IFS= read -r file; do | |
| i=$((i + 1)) | |
| echo "[$i/$test_count] gui/$file" | |
| done < "$test_manifest" | |
| v test gui/ | |
| - name: Check compilation of examples | |
| if: github.event_name == 'pull_request' | |
| env: | |
| VFLAGS: -no-parallel -cc clang | |
| run: v should-compile-all gui/examples/ | |
| - name: Check compilation of changed examples with -W | |
| if: github.event_name == 'pull_request' | |
| env: | |
| VFLAGS: -no-parallel -cc clang | |
| working-directory: gui | |
| run: | | |
| base_ref="${{ github.base_ref }}" | |
| files_list="${RUNNER_TEMP}/gui-example-compile-files" | |
| git fetch --no-tags origin "$base_ref:refs/remotes/origin/$base_ref" | |
| git diff --name-only -z --diff-filter=ACMRT "origin/${base_ref}...HEAD" -- 'examples/*.v' > "$files_list" | |
| if [ ! -s "$files_list" ]; then | |
| echo "No changed example .v files to compile with -W." | |
| exit 0 | |
| fi | |
| mkdir -p examples/bin | |
| while IFS= read -r -d '' file; do | |
| output_file="examples/bin/$(basename "${file%.v}")" | |
| if [ "$file" = "examples/showcase.v" ]; then | |
| v -no-parallel -o "$output_file" "$file" | |
| else | |
| v -no-parallel -W -o "$output_file" "$file" | |
| fi | |
| done < "$files_list" | |
| - name: Check compilation of examples without warning-fatal mode | |
| if: github.event_name != 'pull_request' | |
| env: | |
| VFLAGS: -no-parallel -cc clang | |
| run: v gui/examples/_build.vsh --no-warnings | |
| compiling-on-windows: | |
| runs-on: windows-latest | |
| timeout-minutes: 70 | |
| env: | |
| VFLAGS: -no-parallel | |
| VCPKG_BINARY_CACHE: ${{ github.workspace }}\vcpkg-binary-cache | |
| VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}\vcpkg-binary-cache,readwrite | |
| steps: | |
| - name: Resolve V revision | |
| id: v | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| $revision = (git ls-remote https://github.com/vlang/v HEAD).Split()[0] | |
| "revision=$revision" | Add-Content -Path $env:GITHUB_OUTPUT | |
| - name: Restore V compiler cache | |
| id: restore-v-cache | |
| uses: actions/cache/restore@v4 | |
| with: | |
| path: v | |
| key: windows-v-compiler-${{ steps.v.outputs.revision }}-v1 | |
| - name: Install V | |
| id: install-v | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| function Assert-NativeCommand($Message) { | |
| if ($LASTEXITCODE -ne 0) { | |
| throw $Message | |
| } | |
| } | |
| $expectedRevision = '${{ steps.v.outputs.revision }}' | |
| if (Test-Path .\v\v.exe) { | |
| $cachedRevision = (& git -C v rev-parse HEAD).Trim() | |
| Assert-NativeCommand "Could not inspect cached V revision" | |
| if ($cachedRevision -ne $expectedRevision) { | |
| Write-Host "Cached V revision $cachedRevision does not match expected $expectedRevision; rebuilding." | |
| Remove-Item -Recurse -Force .\v | |
| } | |
| } | |
| if (-not (Test-Path .\v\v.exe)) { | |
| if (Test-Path .\v) { | |
| Remove-Item -Recurse -Force .\v | |
| } | |
| git init v | |
| Assert-NativeCommand "git init failed" | |
| git -C v remote add origin https://github.com/vlang/v | |
| Assert-NativeCommand "git remote add failed" | |
| git -C v fetch --depth 1 origin $expectedRevision | |
| Assert-NativeCommand "git fetch failed" | |
| git -C v checkout --detach FETCH_HEAD | |
| Assert-NativeCommand "git checkout failed" | |
| Push-Location v | |
| cmd /c makev.bat | |
| if ($LASTEXITCODE -ne 0) { | |
| throw "makev.bat failed" | |
| } | |
| Pop-Location | |
| } | |
| $vPath = (Resolve-Path .\v).Path | |
| Add-Content -Path $env:GITHUB_PATH -Value $vPath | |
| $version = (& .\v\v.exe version).Trim() | |
| $revision = (& git -C v rev-parse HEAD).Trim() | |
| Assert-NativeCommand "Could not inspect V revision" | |
| "version=$version" | Add-Content -Path $env:GITHUB_OUTPUT | |
| "revision=$revision" | Add-Content -Path $env:GITHUB_OUTPUT | |
| - name: Log V version | |
| run: v version | |
| - name: Save V compiler cache | |
| if: ${{ steps.restore-v-cache.outputs.cache-hit != 'true' }} | |
| uses: actions/cache/save@v4 | |
| with: | |
| path: v | |
| key: ${{ steps.restore-v-cache.outputs.cache-primary-key }} | |
| - name: Resolve vglyph revision | |
| id: vglyph | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| $revision = (git ls-remote https://github.com/vlang/vglyph HEAD).Split()[0] | |
| if ($LASTEXITCODE -ne 0) { | |
| throw "Could not resolve vglyph revision" | |
| } | |
| "revision=$revision" | Add-Content -Path $env:GITHUB_OUTPUT | |
| - name: Restore vcpkg binary cache | |
| id: restore-vcpkg-cache | |
| uses: actions/cache/restore@v4 | |
| with: | |
| path: ${{ env.VCPKG_BINARY_CACHE }} | |
| key: windows-vcpkg-x64-windows-pango-freetype-${{ steps.install-v.outputs.revision }}-v2 | |
| restore-keys: | | |
| windows-vcpkg-x64-windows-pango-freetype- | |
| - name: Restore V module cache | |
| id: restore-vglyph-cache | |
| uses: actions/cache/restore@v4 | |
| with: | |
| path: ~/.vmodules/vglyph | |
| key: windows-vmodules-vglyph-${{ steps.install-v.outputs.revision }}-${{ steps.vglyph.outputs.revision }}-v2 | |
| - name: Install pango and freetype | |
| shell: pwsh | |
| run: | | |
| New-Item -ItemType Directory -Force -Path "$env:VCPKG_BINARY_CACHE" | Out-Null | |
| vcpkg install pango freetype | |
| - name: Save vcpkg binary cache | |
| if: ${{ steps.restore-vcpkg-cache.outputs.cache-hit != 'true' }} | |
| uses: actions/cache/save@v4 | |
| with: | |
| path: ${{ env.VCPKG_BINARY_CACHE }} | |
| key: ${{ steps.restore-vcpkg-cache.outputs.cache-primary-key }} | |
| - name: Expose vcpkg pkg-config paths | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| $triplet = 'x64-windows' | |
| $vcpkgExe = (Get-Command vcpkg -ErrorAction Stop).Source | |
| $roots = @() | |
| if ($vcpkgExe) { | |
| $roots += Split-Path -Parent $vcpkgExe | |
| } | |
| if ($env:VCPKG_ROOT) { | |
| $roots += $env:VCPKG_ROOT | |
| } | |
| $vcpkgRoot = $null | |
| foreach ($root in ($roots | Select-Object -Unique)) { | |
| if (Test-Path (Join-Path $root "installed\$triplet")) { | |
| $vcpkgRoot = $root | |
| break | |
| } | |
| } | |
| if (-not $vcpkgRoot) { | |
| throw "Could not find vcpkg installed\$triplet from vcpkg.exe or VCPKG_ROOT" | |
| } | |
| $tripletRoot = Join-Path $vcpkgRoot "installed\$triplet" | |
| $pkgConfigDirs = @( | |
| (Join-Path $tripletRoot 'lib\pkgconfig'), | |
| (Join-Path $tripletRoot 'share\pkgconfig') | |
| ) | Where-Object { Test-Path $_ } | |
| if ($pkgConfigDirs.Count -eq 0) { | |
| throw "No pkgconfig directories found under $tripletRoot" | |
| } | |
| $pkgConfigPath = $pkgConfigDirs -join ';' | |
| "PKG_CONFIG_PATH=$pkgConfigPath" | Add-Content -Path $env:GITHUB_ENV | |
| $env:PKG_CONFIG_PATH = $pkgConfigPath | |
| $pathEntries = @() | |
| $binDir = Join-Path $tripletRoot 'bin' | |
| if (Test-Path $binDir) { | |
| $pathEntries += $binDir | |
| } | |
| $pkgconfDir = Join-Path $tripletRoot 'tools\pkgconf' | |
| if (Test-Path $pkgconfDir) { | |
| $pathEntries += $pkgconfDir | |
| } | |
| foreach ($entry in $pathEntries) { | |
| $entry | Add-Content -Path $env:GITHUB_PATH | |
| } | |
| if ($pathEntries.Count -gt 0) { | |
| $env:PATH = ($pathEntries + $env:PATH) -join ';' | |
| } | |
| if (-not (Get-Command pkg-config -ErrorAction SilentlyContinue)) { | |
| $pkgconf = Get-Command pkgconf -ErrorAction SilentlyContinue | |
| if ($pkgconf) { | |
| $shimDir = Join-Path $env:RUNNER_TEMP 'pkg-config-shim' | |
| New-Item -ItemType Directory -Force -Path $shimDir | Out-Null | |
| Set-Content -Path (Join-Path $shimDir 'pkg-config.cmd') -Encoding ascii -Value @( | |
| '@echo off', | |
| '"' + $pkgconf.Source + '" %*' | |
| ) | |
| $shimDir | Add-Content -Path $env:GITHUB_PATH | |
| $env:PATH = "$shimDir;$env:PATH" | |
| } | |
| } | |
| $pkgConfig = Get-Command pkg-config -ErrorAction Stop | |
| & $pkgConfig.Source --exists freetype2 pango pangoft2 | |
| if ($LASTEXITCODE -ne 0) { | |
| throw "pkg-config could not resolve freetype2 pango pangoft2" | |
| } | |
| - name: Ensure vglyph revision | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| function Assert-NativeCommand($Message) { | |
| if ($LASTEXITCODE -ne 0) { | |
| throw $Message | |
| } | |
| } | |
| $expectedRevision = '${{ steps.vglyph.outputs.revision }}' | |
| $vglyphPath = Join-Path $HOME '.vmodules\vglyph' | |
| if (Test-Path (Join-Path $vglyphPath '.git')) { | |
| $cachedRevision = (& git -C $vglyphPath rev-parse HEAD).Trim() | |
| Assert-NativeCommand "Could not inspect cached vglyph revision" | |
| if ($cachedRevision -ne $expectedRevision) { | |
| Write-Host "Cached vglyph revision $cachedRevision does not match expected $expectedRevision; rebuilding." | |
| Remove-Item -Recurse -Force $vglyphPath | |
| } | |
| } elseif (Test-Path $vglyphPath) { | |
| Remove-Item -Recurse -Force $vglyphPath | |
| } | |
| if (-not (Test-Path $vglyphPath)) { | |
| $vmodulesPath = Split-Path -Parent $vglyphPath | |
| New-Item -ItemType Directory -Force -Path $vmodulesPath | Out-Null | |
| git init $vglyphPath | |
| Assert-NativeCommand "git init vglyph failed" | |
| git -C $vglyphPath remote add origin https://github.com/vlang/vglyph | |
| Assert-NativeCommand "git remote add vglyph failed" | |
| git -C $vglyphPath fetch --depth 1 origin $expectedRevision | |
| Assert-NativeCommand "git fetch vglyph failed" | |
| git -C $vglyphPath checkout --detach FETCH_HEAD | |
| Assert-NativeCommand "git checkout vglyph failed" | |
| } | |
| - name: Save V module cache | |
| if: ${{ steps.restore-vglyph-cache.outputs.cache-hit != 'true' }} | |
| uses: actions/cache/save@v4 | |
| with: | |
| path: ~/.vmodules/vglyph | |
| key: ${{ steps.restore-vglyph-cache.outputs.cache-primary-key }} | |
| - name: Checkout the gui module | |
| uses: actions/checkout@v6 | |
| with: | |
| path: gui | |
| fetch-depth: 0 | |
| - name: Configure MSVC developer environment | |
| uses: ilammy/msvc-dev-cmd@v1 | |
| - name: Run Windows setup preflight | |
| env: | |
| GUI_WINDOWS_PREFLIGHT_CC: msvc | |
| run: v -cc msvc run gui/_windows_preflight.vsh | |
| - name: Run tests | |
| env: | |
| VFLAGS: -no-parallel -cc msvc | |
| VJOBS: 1 | |
| VTEST_ONLY_FN: test_* | |
| run: | | |
| $testFiles = @(git -C gui ls-files '*_test.v' | Sort-Object) | |
| Write-Host "Test files: $($testFiles.Count)" | |
| for ($i = 0; $i -lt $testFiles.Count; $i++) { | |
| Write-Host ("[{0}/{1}] gui/{2}" -f ($i + 1), $testFiles.Count, $testFiles[$i]) | |
| } | |
| v test gui/ | |
| - name: Check compilation of examples | |
| if: github.event_name == 'pull_request' | |
| env: | |
| VFLAGS: -no-parallel -cc msvc | |
| run: v gui/examples/_build.vsh --no-warnings --skip-missing-sqlite | |
| - name: Check compilation of changed examples with -W | |
| if: github.event_name == 'pull_request' | |
| env: | |
| VFLAGS: -no-parallel -cc msvc | |
| shell: pwsh | |
| working-directory: gui | |
| run: | | |
| $baseRef = '${{ github.base_ref }}' | |
| git fetch --no-tags origin "${baseRef}:refs/remotes/origin/${baseRef}" | |
| if ($LASTEXITCODE -ne 0) { | |
| exit $LASTEXITCODE | |
| } | |
| $files = @(git diff --name-only --diff-filter=ACMRT "origin/${baseRef}...HEAD" -- 'examples/*.v') | |
| if ($LASTEXITCODE -ne 0) { | |
| exit $LASTEXITCODE | |
| } | |
| if ($files.Count -eq 0) { | |
| Write-Host 'No changed example .v files to compile with -W.' | |
| exit 0 | |
| } | |
| v examples/_build.vsh --skip-missing-sqlite @files | |
| if ($LASTEXITCODE -ne 0) { | |
| exit $LASTEXITCODE | |
| } | |
| - name: Check compilation of examples without warning-fatal mode | |
| if: github.event_name != 'pull_request' | |
| env: | |
| VFLAGS: -no-parallel -cc msvc | |
| run: v gui/examples/_build.vsh --no-warnings --skip-missing-sqlite |