├── .github └── workflows │ ├── docs.yml │ ├── tests.yml │ ├── ubuntu-build.yml │ └── windows-build.yml ├── .gitignore ├── CHANGES.md ├── LICENSE ├── Makefile ├── README.md ├── knotty-lib ├── chart-row.rkt ├── chart.rkt ├── cli.rkt ├── colors.rkt ├── course.rkt ├── demo.rkt ├── diophantine.rkt ├── garn.rkt ├── gauge.rkt ├── global.rkt ├── gui.rkt ├── html.rkt ├── info.rkt ├── knitgraph-viz.rkt ├── knitgraph.rkt ├── knitspeak-grammar.rkt ├── knitspeak-lexer.rkt ├── knitspeak-parser.rkt ├── knitspeak.rkt ├── loop.rkt ├── macros.rkt ├── main.rkt ├── options.rkt ├── pattern.rkt ├── png.rkt ├── pull-direction.rkt ├── repeats.rkt ├── resources │ ├── SaxonHE11-5J │ │ ├── lib │ │ │ ├── jline-2.14.6.jar │ │ │ ├── xmlresolver-4.6.4-data.jar │ │ │ └── xmlresolver-4.6.4.jar │ │ ├── notices │ │ │ ├── JAMESCLARK.txt │ │ │ ├── JLINE2.txt │ │ │ └── LICENSE.txt │ │ ├── saxon-he-11.5.jar │ │ ├── saxon-he-test-11.5.jar │ │ └── saxon-he-xqj-11.5.jar │ ├── css │ │ ├── knotty-manual.css │ │ ├── knotty.css │ │ └── scribble.css │ ├── example │ │ └── lattice.xml │ ├── font │ │ ├── StitchMasteryDash.ttf │ │ └── georgia.ttf │ ├── icon │ │ ├── favicon.ico │ │ ├── icon.png │ │ └── knotty.png │ ├── js │ │ └── knotty.js │ └── xml │ │ ├── knotty-make-xsd.xsl │ │ ├── knotty-stitch.xml │ │ └── knotty.xsd ├── rowcount.rkt ├── rowmap.rkt ├── rows.rkt ├── rowspec.rkt ├── serv.rkt ├── stitch-instructions.rkt ├── stitch.rkt ├── text.rkt ├── tree.rkt ├── util.rkt ├── xml.rkt └── yarn.rkt └── knotty ├── info.rkt ├── scribblings ├── cable-lattice.png ├── check-float.png ├── check.png ├── chessboard-squashed.png ├── chessboard.png ├── code.scrbl ├── danny-screenshot.png ├── danny.png ├── demo.png ├── demo.scrbl ├── example │ ├── index.html │ ├── index.xml │ └── lattice.png ├── fishtail-lace.png ├── garter.png ├── houndstooth.png ├── io.scrbl ├── knotty-screenshot.png ├── knotty.png ├── knotty.scrbl ├── lancellin.png ├── little-leaf-stripe.png ├── mario-screenshot.png ├── mario.png ├── megaman-screenshot.png ├── megaman.png ├── owl.png ├── pretzel.png ├── racket.png ├── ref.scrbl ├── sawtooth.png ├── short-rows.png ├── star.png ├── triangle-top.png └── tv.png └── tests ├── chart-row.rkt ├── chart.rkt ├── colors.rkt ├── course.rkt ├── diophantine.rkt ├── garn.rkt ├── gauge.rkt ├── html.rkt ├── knitgraph.rkt ├── knitspeak.rkt ├── loop.rkt ├── macros.rkt ├── mocks.rkt ├── options.rkt ├── pattern.rkt ├── png.rkt ├── pull-direction.rkt ├── repeats.rkt ├── rowcount.rkt ├── rowmap.rkt ├── rows.rkt ├── rowspec.rkt ├── simple-knitgraphs.rkt ├── stitch-instructions.rkt ├── stitch.rkt ├── text.rkt ├── tree.rkt ├── util.rkt ├── xml.rkt └── yarn.rkt /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: docs 2 | on: 3 | push: 4 | branches: 5 | - 'main' 6 | - 'dev*' 7 | paths: 8 | - 'knotty/scribblings/**' 9 | - '.github/workflows/docs.yml' 10 | permissions: 11 | contents: write 12 | defaults: 13 | run: 14 | shell: bash 15 | jobs: 16 | deploy-docs: 17 | runs-on: ubuntu-latest 18 | name: Build and deploy backup docs 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@master 22 | - name: Install Racket 23 | uses: Bogdanp/setup-racket@v1.11 24 | with: 25 | architecture: 'x64' 26 | distribution: 'full' 27 | version: 'stable' 28 | - name: Save Racket version 29 | run : racket --version > .racket-version 30 | - name: Install dependencies 31 | run: | 32 | echo "installing dependencies" 33 | raco pkg install --auto --batch --no-docs --skip-installed \ 34 | sweet-exp-lib threading-lib brag-lib br-parser-tools \ 35 | sxml html-template html-parsing \ 36 | mock mock-rackunit 37 | - name: (Re)install knotty from source 38 | run: | 39 | pkgs=$(raco pkg show | grep '^ [^[]' | grep -v '^ Package' | cut -d ' ' -f2) 40 | echo "packages:" $pkgs 41 | if [ $(echo $pkgs | grep -cw knotty-lib) -gt 0 ] 42 | then 43 | echo "updating knotty-lib" 44 | raco pkg update --auto --batch --no-docs --force --type dir knotty-lib 45 | else 46 | echo "installing knotty-lib" 47 | raco pkg install --auto --batch --no-docs --force --type dir knotty-lib 48 | fi 49 | if [ $(echo $pkgs | grep -cw knotty) -gt 0 ] 50 | then 51 | echo "updating knotty" 52 | raco pkg update --auto --batch --no-docs --force --type dir knotty 53 | else 54 | echo "installing knotty" 55 | raco pkg install --auto --batch --no-docs --force --type dir knotty 56 | fi 57 | - name: Build docs for hosting 58 | run: | 59 | mkdir -p manual/knotty/example/css 60 | mkdir -p manual/knotty/example/js 61 | mkdir -p manual/knotty/example/icon 62 | scribble +m --redirect-main http://pkg-build.racket-lang.org/doc/ --htmls --dest manual knotty/scribblings/knotty.scrbl 63 | cp knotty/scribblings/example/index.html manual/knotty/example/ 64 | cp knotty/scribblings/example/lattice.png manual/knotty/example/ 65 | cp knotty-lib/resources/css/knotty*.css manual/knotty/example/css/ 66 | cp knotty-lib/resources/js/knotty*.js manual/knotty/example/js/ 67 | cp knotty-lib/resources/icon/favicon.ico manual/knotty/example/icon/ 68 | #cp -R knotty/scribblings/leaf-chart/ manual/knotty 69 | ls -R manual 70 | - name: Push to GitHub Pages 71 | uses: JamesIves/github-pages-deploy-action@v4.4.1 72 | with: 73 | folder: 'manual/knotty' 74 | branch: 'pages' 75 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: tests 2 | on: 3 | push: 4 | branches: 5 | - 'main' 6 | - 'dev*' 7 | jobs: 8 | test: 9 | name: Run tests 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@main 14 | - name: Install Racket 15 | uses: Bogdanp/setup-racket@v1.11 16 | with: 17 | architecture: 'x64' 18 | distribution: 'full' 19 | version: 'stable' 20 | - name: Set variables 21 | id: vars 22 | run: | 23 | echo "racket-version=$(racket --version)" >> $GITHUB_OUTPUT 24 | - name: Cache Racket dependencies 25 | uses: actions/cache@v3 26 | with: 27 | path: | 28 | ~/.cache/racket 29 | ~/.local/share/racket 30 | key: ${{ runner.os }}-racket-${{ steps.vars.outputs.racket-version }} 31 | - name: Install dependencies 32 | run: | 33 | echo "installing dependencies" 34 | raco pkg install --auto --batch --no-docs --skip-installed \ 35 | sweet-exp-lib threading-lib brag-lib br-parser-tools \ 36 | sxml html-template html-parsing \ 37 | mock mock-rackunit 38 | - name: (Re)install knotty from source 39 | run: | 40 | pkgs=$(raco pkg show | grep '^ [^[]' | grep -v '^ Package' | cut -d ' ' -f2) 41 | echo "packages:" $pkgs 42 | if [ $(echo $pkgs | grep -cw knotty-lib) -gt 0 ] 43 | then 44 | echo "updating knotty-lib" 45 | raco pkg update --auto --batch --no-docs --force --type dir knotty-lib 46 | else 47 | echo "installing knotty-lib" 48 | raco pkg install --auto --batch --no-docs --force --type dir knotty-lib 49 | fi 50 | if [ $(echo $pkgs | grep -cw knotty) -gt 0 ] 51 | then 52 | echo "updating knotty" 53 | raco pkg update --auto --batch --no-docs --force --type dir knotty 54 | else 55 | echo "installing knotty" 56 | raco pkg install --auto --batch --no-docs --force --type dir knotty 57 | fi 58 | # - name: Run headless tests (to test GUI in DrRacket) 59 | # uses: coactions/setup-xvfb@v1.0.1 60 | # with: 61 | # run: raco test knotty 62 | - name: Run tests (omit scribblings directory) 63 | run: raco test knotty/tests/*.rkt 64 | 65 | coverage: 66 | needs: test 67 | runs-on: ubuntu-latest 68 | environment: test-env 69 | env: 70 | COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} 71 | steps: 72 | - name: Checkout 73 | uses: actions/checkout@main 74 | - name: Install Racket 75 | uses: Bogdanp/setup-racket@v1.11 76 | with: 77 | architecture: 'x64' 78 | distribution: 'full' 79 | version: 'stable' 80 | - name: Set variables 81 | id: vars 82 | run: | 83 | echo "racket-version=$(racket --version)" >> $GITHUB_OUTPUT 84 | - name: Cache Racket dependencies 85 | uses: actions/cache@v3 86 | with: 87 | path: | 88 | ~/.cache/racket 89 | ~/.local/share/racket 90 | key: ${{ runner.os }}-racket-${{ steps.vars.outputs.racket-version }} 91 | - name: Install dependencies 92 | run: | 93 | echo "installing dependencies" 94 | raco pkg install --auto --batch --no-docs --skip-installed \ 95 | sweet-exp-lib threading-lib brag-lib br-parser-tools \ 96 | sxml html-template html-parsing \ 97 | mock mock-rackunit \ 98 | cover-lib cover-coveralls 99 | # - name: Run headless coverage report 100 | # uses: coactions/setup-xvfb@v1.0.1 101 | # with: 102 | # run: raco cover -b -f coveralls -n knotty/scribblings -n knotty/test -p knotty knotty-lib 103 | - name: Run coverage report 104 | run: raco cover -bf coveralls -p knotty knotty-lib 105 | -------------------------------------------------------------------------------- /.github/workflows/ubuntu-build.yml: -------------------------------------------------------------------------------- 1 | name: 'ubuntu-build' 2 | on: 3 | push: 4 | tags: 5 | - 'v*' 6 | - 'test*' 7 | 8 | jobs: 9 | create-release: 10 | name: Create Ubuntu asset 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@main 15 | - name: Install Racket 16 | uses: Bogdanp/setup-racket@v1.11 17 | with: 18 | architecture: 'x64' 19 | distribution: 'full' 20 | version: 'stable' 21 | - name: Set variables 22 | id: vars 23 | run: | 24 | echo "sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT 25 | echo "racket-version=$(racket --version)" >> $GITHUB_OUTPUT 26 | echo "tag=$(git describe --tags)" >> $GITHUB_OUTPUT 27 | echo "draft=$(git describe --tags | sed -e 's/^test.*/true/;s/^v.*/false/')" >> $GITHUB_OUTPUT 28 | - name: Cache Racket dependencies 29 | uses: actions/cache@v3 30 | with: 31 | path: | 32 | ~/.cache/racket 33 | ~/.local/share/racket 34 | key: ${{ runner.os }}-racket-${{ steps.vars.outputs.racket-version }} 35 | - name: Install dependencies 36 | run: | 37 | echo "installing dependencies" 38 | raco pkg install --auto --batch --no-docs --skip-installed \ 39 | sweet-exp-lib threading-lib brag-lib br-parser-tools \ 40 | sxml html-template html-parsing 41 | - name: (Re)install knotty from source 42 | run: | 43 | pkgs=$(raco pkg show | grep '^ [^[]' | grep -v '^ Package' | cut -d ' ' -f2) 44 | echo "packages:" $pkgs 45 | if [ $(echo $pkgs | grep -cw knotty-lib) -gt 0 ] 46 | then 47 | echo "updating knotty-lib" 48 | raco pkg update --auto --batch --no-docs --force --type dir knotty-lib 49 | else 50 | echo "installing knotty-lib" 51 | raco pkg install --auto --batch --no-docs --force --type dir knotty-lib 52 | fi 53 | if [ $(echo $pkgs | grep -cw knotty) -gt 0 ] 54 | then 55 | echo "updating knotty" 56 | raco pkg update --auto --batch --no-docs --force --type dir knotty 57 | else 58 | echo "installing knotty" 59 | raco pkg install --auto --batch --no-docs --force --type dir knotty 60 | fi 61 | - name: Set knotty VERSION 62 | run: | 63 | sed -i 's/KNOTTY-VERSION/${{steps.vars.outputs.tag}}/' knotty-lib/global.rkt 64 | sed -i 's/KNOTTY-VERSION/${{steps.vars.outputs.tag}}/' knotty-lib/cli.rkt 65 | - name: Create executable 66 | run: | 67 | dir="knotty-${{ steps.vars.outputs.tag }}-amd64" 68 | mkdir -p build/linux 69 | cd build/linux 70 | raco exe -v -o knotty ../../knotty-lib/cli.rkt 71 | raco distribute $dir knotty 72 | tar -czvf $dir.tgz $dir 73 | cd ../.. 74 | # - name: Create .deb package 75 | # - uses: jiro4989/build-deb-action@v2 76 | # with: 77 | # package: knotty 78 | # package_root: build 79 | # maintainer: Tom Price 80 | # version: ${{ steps.vars.outputs.tag }} 81 | # arch: 'amd64' 82 | # depends: 'libc6 (>= 2.2.1), git' 83 | # desc: 'Utility for converting knitting patterns between different formats. See https://github.com/t0mpr1c3/knotty' 84 | - name: Archive asset 85 | uses: actions/upload-artifact@v3 86 | with: 87 | name: ubuntu-build 88 | path: build/linux/knotty-${{ steps.vars.outputs.tag }}-amd64.tgz 89 | 90 | upload-release: 91 | name: Upload Ubuntu asset 92 | needs: create-release 93 | runs-on: ubuntu-latest 94 | permissions: 95 | contents: write 96 | steps: 97 | - name: Checkout 98 | uses: actions/checkout@main 99 | - name: Set variables 100 | id: vars 101 | run: | 102 | echo "sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT 103 | echo "racket-version=$(racket --version)" >> $GITHUB_OUTPUT 104 | echo "tag=$(git describe --tags)" >> $GITHUB_OUTPUT 105 | echo "draft=$(git describe --tags | sed -e 's/^test.*/true/;s/^v.*/false/')" >> $GITHUB_OUTPUT 106 | - name: Download asset 107 | uses: actions/download-artifact@v3 108 | with: 109 | name: ubuntu-build 110 | - name: Upload asset 111 | uses: ncipollo/release-action@v1 112 | with: 113 | token: ${{ secrets.GITHUB_TOKEN }} 114 | tag: ${{ steps.vars.outputs.tag }} 115 | body: "" # release message, alternative to body_path 116 | draft: ${{ steps.vars.outputs.draft }} 117 | prerelease: false 118 | allowUpdates: true 119 | artifacts: knotty-${{ steps.vars.outputs.tag }}-amd64.tgz 120 | artifactContentType: executable 121 | replacesArtifacts: true 122 | -------------------------------------------------------------------------------- /.github/workflows/windows-build.yml: -------------------------------------------------------------------------------- 1 | name: 'windows-build' 2 | on: 3 | push: 4 | tags: 5 | - 'v*' 6 | - 'test*' 7 | jobs: 8 | create-release: 9 | name: Create Windows asset 10 | runs-on: windows-latest 11 | defaults: 12 | run: 13 | shell: bash 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@main 17 | - name: Install Racket 18 | uses: Bogdanp/setup-racket@v1.11 19 | with: 20 | architecture: 'x64' 21 | distribution: 'full' 22 | version: 'stable' 23 | - name: Set variables 24 | id: vars 25 | shell: bash 26 | run: | 27 | echo "sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT 28 | echo "racket-version=$(racket --version)" >> $GITHUB_OUTPUT 29 | echo "tag=$(git describe --tags)" >> $GITHUB_OUTPUT 30 | echo "draft=$(git describe --tags | sed -e 's/^test.*/true/;s/^v.*/false/')" >> $GITHUB_OUTPUT 31 | - name: Cache Racket dependencies 32 | uses: actions/cache@v3 33 | with: 34 | path: \Windows\Temp 35 | key: ${{ runner.os }}-racket-${{ steps.vars.outputs.racket-version }} 36 | - name: Install dependencies 37 | run: | 38 | echo "installing dependencies" 39 | raco pkg install --auto --batch --no-docs --skip-installed \ 40 | sweet-exp-lib threading-lib brag-lib br-parser-tools \ 41 | sxml html-template html-parsing \ 42 | - name: (Re)install knotty from source 43 | run: | 44 | pkgs=$(raco pkg show | grep '^ [^[]' | grep -v '^ Package' | cut -d ' ' -f2) 45 | echo "packages:" $pkgs 46 | if [ $(echo $pkgs | grep -cw knotty-lib) -gt 0 ] 47 | then 48 | echo "updating knotty-lib" 49 | raco pkg update --auto --batch --no-docs --force --type dir knotty-lib 50 | else 51 | echo "installing knotty-lib" 52 | raco pkg install --auto --batch --no-docs --force --type dir knotty-lib 53 | fi 54 | if [ $(echo $pkgs | grep -cw knotty) -gt 0 ] 55 | then 56 | echo "updating knotty" 57 | raco pkg update --auto --batch --no-docs --force --type dir knotty 58 | else 59 | echo "installing knotty" 60 | raco pkg install --auto --batch --no-docs --force --type dir knotty 61 | fi 62 | - name: Set knotty VERSION 63 | shell: bash 64 | run: | 65 | sed -i 's/KNOTTY-VERSION/${{steps.vars.outputs.tag}}/' knotty-lib/global.rkt 66 | sed -i 's/KNOTTY-VERSION/${{steps.vars.outputs.tag}}/' knotty-lib/cli.rkt 67 | - name: Create executable 68 | shell: bash 69 | run: | 70 | dir="knotty-${{ steps.vars.outputs.tag }}-win" 71 | mkdir -p build/windows 72 | cd build/windows 73 | raco exe -v -o knotty.exe ../../knotty-lib/cli.rkt 74 | raco distribute $dir knotty.exe 75 | cd ../.. 76 | - name: Zip folder 77 | shell: pwsh 78 | run: | 79 | Set-Variable dir "knotty-${{ steps.vars.outputs.tag }}-win" 80 | Set-Variable zip "$dir.zip" 81 | Compress-Archive -Path build/windows/$dir -DestinationPath build/windows/$zip 82 | - name: Archive asset 83 | uses: actions/upload-artifact@v3 84 | with: 85 | name: windows-build 86 | path: build/windows/knotty-${{ steps.vars.outputs.tag }}-win.zip 87 | 88 | upload-release: 89 | name: Upload Windows asset 90 | needs: create-release 91 | runs-on: windows-latest 92 | defaults: 93 | run: 94 | shell: bash 95 | permissions: 96 | contents: write 97 | steps: 98 | - name: Checkout 99 | uses: actions/checkout@main 100 | - name: Set variables 101 | id: vars 102 | shell: bash 103 | run: | 104 | echo "sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT 105 | echo "racket-version=$(racket --version)" >> $GITHUB_OUTPUT 106 | echo "tag=$(git describe --tags)" >> $GITHUB_OUTPUT 107 | echo "draft=$(git describe --tags | sed -e 's/^test.*/true/;s/^v.*/false/')" >> $GITHUB_OUTPUT 108 | - name: Download asset 109 | uses: actions/download-artifact@v3 110 | with: 111 | name: windows-build 112 | - name: Upload asset 113 | uses: ncipollo/release-action@v1 114 | with: 115 | token: ${{ secrets.GITHUB_TOKEN }} 116 | tag: ${{ steps.vars.outputs.tag }} 117 | body: "" # release message, alternative to body_path 118 | draft: ${{ steps.vars.outputs.draft }} 119 | prerelease: false 120 | allowUpdates: true 121 | artifacts: knotty-${{ steps.vars.outputs.tag }}-win.zip 122 | artifactContentType: executable 123 | replacesArtifacts: true 124 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.~ 2 | *.swp 3 | *.bak 4 | *.1 5 | *.2 6 | *.json 7 | build/ 8 | **/compiled 9 | **/doc 10 | **/coverage 11 | #**/sandbox 12 | 13 | manual/ 14 | *.html 15 | **/scribblings/*.js 16 | **/scribblings/racket.css 17 | **/scribblings/scribble.css 18 | **/scribblings/manual-*.css 19 | 20 | !knotty-lib/resources 21 | !knotty/scribblings/example 22 | 23 | knotty-lib/resources/backups 24 | *.xcf 25 | *.zip 26 | *.CHECKSUM 27 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | v1.0.0 2 | * Initial release 3 | 4 | v1.0.1 5 | * Fix logger #27 6 | 7 | v1.0.2 8 | * Use SAFE version of assert for importing XML #13 9 | 10 | v1.0.3 11 | * Add CLI info messages #12 12 | 13 | v1.0.4 14 | * Message log receiver thread to ensure everything has been logged before exiting 15 | 16 | v1.0.5 17 | * Replace edging in code example #22 18 | * Fix charts for short rows 19 | 20 | v1.0.6 21 | * Fix alignment for repeating patterns #32 22 | 23 | v1.0.7 24 | * Include fonts in distribution #33 25 | 26 | v1.0.8 27 | * Test side effects using mocks #34 28 | 29 | v.1.1.0 30 | * Add Garn, Loop, Course, and Knitgraph structs 31 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Adapted from: http://www.greghendershott.com/2017/04/racket-makefiles.html 2 | SHELL=/bin/sh 3 | 4 | PACKAGE-NAME=knotty 5 | 6 | DEPS-FLAGS=--check-pkg-deps --unused-pkg-deps 7 | 8 | help: 9 | @echo "install - install package along with dependencies" 10 | @echo "remove - remove package" 11 | @echo "build - compile libraries" 12 | @echo "build-docs - build self-contained docs that could be hosted somewhere" 13 | @echo "build-all - compile libraries, build docs, and check dependencies" 14 | @echo "clean - remove all build artifacts" 15 | @echo "check-deps - check dependencies" 16 | @echo "test - run tests" 17 | @echo "test-with-errortrace - run tests with error tracing" 18 | @echo "errortrace - alias for test-with-errortrace" 19 | @echo "cover - run test coverage checker and view report" 20 | @echo "cover-coveralls - run test coverage and upload to Coveralls" 21 | @echo "coverage-check - run test coverage checker" 22 | @echo "coverage-report - view test coverage report" 23 | @echo "docs - view docs in a browser" 24 | 25 | # Primarily for use by CI. 26 | # Install dependencies as well as linking this as a package. 27 | install: 28 | raco pkg install --deps search-auto --link $(PWD)/$(PACKAGE-NAME) $(PWD)/$(PACKAGE-NAME)-lib 29 | 30 | remove: 31 | raco pkg remove $(PACKAGE-NAME) $(PACKAGE-NAME)-lib 32 | 33 | # Primarily for day-to-day dev. 34 | # Build libraries from source. 35 | build: 36 | raco setup --no-docs --pkgs $(PACKAGE-NAME)-lib 37 | 38 | # Primarily for day-to-day dev. 39 | # Build libraries from source, build docs (if any), and check dependencies. 40 | build-all: 41 | raco setup $(DEPS-FLAGS) --pkgs $(PACKAGE-NAME) $(PACKAGE-NAME)-lib 42 | 43 | # Primarily for CI, for building backup docs that could be used in case 44 | # the main docs at docs.racket-lang.org become unavailable. 45 | build-docs: 46 | scribble +m --redirect-main http://pkg-build.racket-lang.org/doc/ --htmls --dest ./manual ./$(PACKAGE-NAME)/scribblings/$(PACKAGE-NAME).scrbl 47 | 48 | # Note: Each collection's info.rkt can say what to clean, for example 49 | # (define clean '("compiled" "doc" "doc/")) to clean 50 | # generated docs, too. 51 | clean: 52 | raco setup --fast-clean --pkgs $(PACKAGE-NAME)-lib $(PACKAGE-NAME)-test $(PACKAGE-NAME)-doc 53 | 54 | # Primarily for use by CI, after make install -- since that already 55 | # does the equivalent of make setup, this tries to do as little as 56 | # possible except checking deps. 57 | check-deps: 58 | raco setup --no-docs $(DEPS-FLAGS) $(PACKAGE-NAME) 59 | 60 | # Suitable for both day-to-day dev and CI 61 | test: 62 | raco test -exp $(PACKAGE-NAME) $(PACKAGE-NAME)-lib 63 | 64 | test-with-errortrace: 65 | racket -l errortrace -l racket -e '(require (submod "$(PACKAGE-NAME)/test/$(PACKAGE-NAME).rkt" test))' 66 | 67 | errortrace: test-with-errortrace 68 | 69 | docs: 70 | raco docs $(PACKAGE-NAME) 71 | 72 | coverage-check: 73 | raco cover -b -d ./coverage -p $(PACKAGE-NAME) $(PACKAGE-NAME)-lib 74 | 75 | coverage-report: 76 | open coverage/index.html 77 | 78 | cover: coverage-check coverage-report 79 | 80 | cover-coveralls: 81 | raco cover -b -f coveralls -p $(PACKAGE-NAME) $(PACKAGE-NAME)-lib 82 | 83 | .PHONY: help install remove build build-docs build-all clean check-deps test test-with-errortrace errortrace docs cover coverage-check coverage-report cover-coveralls 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Knotty 2 | 3 | Domain Specific Language for knitting patterns 4 | 5 | [![Coverage Status](https://coveralls.io/repos/github/t0mpr1c3/knotty/badge.svg?branch=main)](https://coveralls.io/github/t0mpr1c3/knotty?branch=main) 6 | 7 | [Documentation](https://t0mpr1c3.github.io/knotty/index.html) 8 | 9 | ## Description 10 | 11 | Grid-based editors are handy for colorwork. 12 | [Knitspeak](https://stitch-maps.com/about/knitspeak/) is great for lace. 13 | Knotty aims for the best of both worlds. It's a way to design knitting patterns 14 | that incorporate both textured stitches and multiple colors of yarn. 15 | 16 | ## Features 17 | 18 | Knotty patterns are encoded in a format that is easy for humans to write and parse, 19 | but is also highly structured. 20 | 21 | Patterns can be viewed and saved in an HTML format that contains an interactive 22 | knitting chart and written instructions. You can also import and export Knitspeak 23 | files, and create Fair Isle patterns directly from color graphics. 24 | 25 | Knotty has been coded as a module for 26 | [Typed Racket](https://docs.racket-lang.org/ts-guide/). Reference information 27 | is available in the [manual](https://t0mpr1c3.github.io/knotty/index.html). 28 | 29 | A [Knotty executable](https://github.com/t0mpr1c3/knotty/releases) is also 30 | available that can be used from the command line to convert knitting patterns from 31 | one format to another. 32 | 33 | ## Getting Started 34 | 35 | Clone [this repository](https://github.com/t0mpr1c3/knotty). 36 | 37 | Download the latest version of [Racket](https://download.racket-lang.org/) 38 | for your operating system. It comes with the graphical application DrRacket. 39 | Open DrRacket and select the menu option "File > Install Package". Type 40 | "knotty" into the text box and press "Install". 41 | 42 | Open the test script `demo.rkt` from the `knotty-lib` directory of the repository 43 | and press "Run" in the top right of the window. The demonstration script contains 44 | a very short knitting pattern, together with many lines of comments describing how 45 | to go about making your own. 46 | -------------------------------------------------------------------------------- /knotty-lib/chart-row.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (provide (all-defined-out)) 22 | 23 | (require threading 24 | racket/vector) ;; needed for `vector-map` 25 | (require "global.rkt" 26 | "stitch.rkt" 27 | "yarn.rkt") 28 | 29 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 30 | 31 | ;; Chart-row struct. 32 | 33 | (struct Chart-row 34 | ([stitches : (Vectorof Stitch)] 35 | [default-yarn : Byte] 36 | [rs? : Boolean] 37 | [r2l? : Boolean] 38 | [short? : Boolean] 39 | [align-left : Natural] 40 | [align-right : Natural]) 41 | #:transparent) 42 | 43 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 44 | 45 | ;; Changes stitches, retains other members of struct. 46 | (: chart-row-set-stitches : Chart-row (Vectorof Stitch) -> Chart-row) 47 | (define (chart-row-set-stitches self sts) 48 | (struct-copy Chart-row self 49 | [stitches sts])) 50 | 51 | ;; Calculates width of row. 52 | (: chart-row-width : Chart-row -> Natural) 53 | (define (chart-row-width self) 54 | (for/fold ([w : Natural 0]) 55 | ([st : Stitch (vector->list (Chart-row-stitches self))]) 56 | (+ w (Stitchtype-width (get-stitchtype (Stitch-symbol st)))))) 57 | 58 | ;; Returns yarns used in row as byte string. 59 | (: chart-row-colors : Chart-row -> Bytes) 60 | (define (chart-row-colors self) 61 | (let ([v (Chart-row-stitches self)] 62 | [default (Chart-row-default-yarn self)]) 63 | (list->bytes 64 | (for/list ([i (in-range (vector-length v))]) 65 | (~> v 66 | (vector-ref i) 67 | Stitch-yarn 68 | (or default)))))) 69 | 70 | ;; Returns stitchtypes used in row as list. 71 | (: chart-row-stitchtypes : Chart-row -> (Listof Symbol)) 72 | (define (chart-row-stitchtypes self) 73 | (let ([v (Chart-row-stitches self)]) 74 | (for/list ([i (in-range (vector-length v))]) 75 | (~> v 76 | (vector-ref i) 77 | Stitch-symbol)))) 78 | 79 | ;; end 80 | -------------------------------------------------------------------------------- /knotty-lib/course.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | 6 | MIT License 7 | 8 | Copyright (c) 2023 Tom Price. 9 | 10 | Incorporating concepts from https://pypi.org/project/knit-script/ 11 | Copyright (c) 2022 Megan Hofmann, Northeastern University Khoury College of 12 | Computer Sciences Accessible Creative Technologies (ACT) Lab and Contributors. 13 | 14 | Permission is hereby granted, free of charge, to any person obtaining a copy 15 | of this software and associated documentation files (the "Software"), to deal 16 | in the Software without restriction, including without limitation the rights 17 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | copies of the Software, and to permit persons to whom the Software is 19 | furnished to do so, subject to the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included in all 22 | copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 26 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 27 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 28 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | |# 31 | 32 | (provide (all-defined-out)) 33 | 34 | (require "util.rkt" 35 | "loop.rkt") 36 | 37 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 38 | 39 | ;; Course struct definition. 40 | ;; For organizing loops into knitted rows or rounds. 41 | ;; 42 | ;; Attributes: 43 | ;; loop-ids : (Listof Loop-Id) 44 | ;; List of Loop IDs, ordered by their sequence in the Course. 45 | (struct Course 46 | ([loop-ids : (Listof Loop-Id)]) 47 | #:prefab) 48 | 49 | ;; Alternative constructor. 50 | (: make-course : -> Course) 51 | (define (make-course) 52 | (Course null)) 53 | 54 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 55 | 56 | ;; Parameters: 57 | ;; self : Course 58 | ;; The Course. 59 | ;; loop : Loop 60 | ;; The Loop to be added to the Course. 61 | ;; idx : (Option Index) 62 | ;; The position in the Course at which to insert the Loop, or 63 | ;; False if adding to the end of the Course. 64 | ;; 65 | ;; Return: 66 | ;; The modified Course. 67 | (: course-add-loop (->* (Course Loop) ((Option Index)) Course)) 68 | (define (course-add-loop self loop [idx #f]) 69 | (for ([parent (in-list (Loop-parents loop))]) 70 | (when (course-has-loop? self parent) 71 | (error 'knotty "~a has parent ~a, cannot be added to same course" loop parent))) 72 | (let ([loop-id (Loop-id loop)] 73 | [loop-ids (Course-loop-ids self)]) 74 | (if (false? idx) 75 | (struct-copy Course self 76 | [loop-ids (append loop-ids (list loop-id))]) 77 | (let-values ([(before after) (split-at loop-ids idx)]) 78 | (struct-copy Course self 79 | [loop-ids (append before (list loop-id) after)]))))) 80 | 81 | ;; Parameters: 82 | ;; self : Course 83 | ;; The Course. 84 | ;; idx : Index 85 | ;; The position in the Course. 86 | ;; 87 | ;; Return: 88 | ;; The ID of the Loop at the specified position in the Course. 89 | (: course-ref : Course Index -> Natural) 90 | (define (course-ref self idx) 91 | (list-ref (Course-loop-ids self) idx)) 92 | 93 | ;; Parameters: 94 | ;; self : Course 95 | ;; The Course. 96 | ;; loop : (U Loop-Id Loop) 97 | ;; The ID of a Loop in the Course, or the Loop itself. 98 | ;; 99 | ;; Return: 100 | ;; The position of the Loop in the Course. 101 | (: course-index : Course (U Loop-Id Loop) -> (Option Index)) 102 | (define (course-index self item) 103 | (index-of (Course-loop-ids self) (loop->id item) eq?)) 104 | 105 | ;; Parameters: 106 | ;; self : Course 107 | ;; The Course. 108 | ;; loop : (U Loop-Id Loop) 109 | ;; The ID of a Loop, or the Loop itself. 110 | ;; 111 | ;; Return: 112 | ;; True if the Loop is in the Course, otherwise False. 113 | (: course-has-loop? : Course (U Loop-Id Loop) -> Boolean) 114 | (define (course-has-loop? self item) 115 | (truthy? (memq (loop->id item) (Course-loop-ids self)))) 116 | 117 | ;; Parameters: 118 | ;; self : Course 119 | ;; The Course. 120 | ;; 121 | ;; Return: 122 | ;; The number of Loops in the Course. 123 | (: course-length : Course -> Index) 124 | (define (course-length self) 125 | (length (Course-loop-ids self))) 126 | 127 | ;; end -------------------------------------------------------------------------------- /knotty-lib/demo.rkt: -------------------------------------------------------------------------------- 1 | #lang sweet-exp typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | require "main.rkt" 22 | 23 | #| 24 | KNOTTY 25 | ====== 26 | 27 | INTRODUCTION 28 | 29 | Knotty is a domain-specific language for designing knitting patterns. 30 | 31 | It's really just typed Racket with a few functions and macros thrown in. 32 | So you can do anything that you can do in any other programming language. 33 | You have complete flexibility in how you write and parameterize your designs. 34 | 35 | 36 | GETTING STARTED 37 | 38 | Download and install the lastest version of Racket from the homepage. 39 | The installation will include an application called 'DrRacket'. DrRacket 40 | is recommended as the best way to edit and run programs in Racket. 41 | 42 | Next, clone the Knotty github repository and follow the installation 43 | instructions in the document 'README.md'. The repository can be found at 44 | the following URL: https://github.com/t0mpr1c3/knotty 45 | 46 | 47 | ABOUT THIS DOCUMENT 48 | 49 | This document is a program written in Knotty. You can run it in DrRacket. 50 | It is also intended to be read by people who are learning to use Knotty. 51 | In this document you can find code examples that demonstrate some of the 52 | features implemented in Knotty. 53 | 54 | 55 | USING KNITSCHEME 56 | 57 | Eventually it will be possible to run Knotty as a stand-alone application. 58 | But for now, the best way to use Knotty is from within DrRacket. 59 | 60 | 61 | MAKING A NEW PROGRAM 62 | 63 | From the menu bar in DrRacket, select "File > New Tab". Edit the resulting 64 | file so that the first two lines read as follows: 65 | 66 | #lang sweet-exp typed/racket 67 | require "knotty.rkt" 68 | 69 | You will see the same two lines at the top of this file. What do they mean? 70 | 71 | The first line means that the program will be written in typed Racket. You 72 | can read all about this language in the Racket documentation: 73 | https://docs.racket-lang.org/ts-guide/index.html 74 | 75 | More specifically, it uses a variant of typed Racket specified by the module 76 | 'sweet-exp' that you should also have installed. For more information, see: 77 | https://github.com/takikawa/sweet-racket 78 | 79 | The second line loads the knotty module, assuming that it is located in 80 | the same directory as the program file itself. If your program file is saved 81 | elsewhere, adjust the relative path to wherever the knotty module can be 82 | found, e.g. `(require "../../somewhere/else/knotty.rkt")` 83 | 84 | 85 | MAKING A SIMPLE PATTERN 86 | 87 | The following snippet of code defines a pattern called `demo`, then draws a 88 | chart conforming to the pattern, and a set of instructions detailing how to 89 | knit it. 90 | |# 91 | 92 | define 93 | demo 94 | pattern 95 | [name "Demo"] 96 | rows(1 3) k8 97 | rows(2 4) p 98 | row(5) bo 99 | 100 | ;show demo 101 | text demo 102 | 103 | #| 104 | Let's go through the code line by line: 105 | 106 | 107 | define 108 | demo 109 | ... 110 | 111 | The `define` function takes two arguments: the name of the object to be 112 | defined, and an expression that determines its contents. 113 | 114 | 115 | pattern 116 | ... 117 | 118 | The `pattern` function creates the pattern object, and takes a variable number 119 | of arguments. Some of these may be keyword arguments, which are optional and 120 | specified using a square bracket notation. Here, the keyword `name` is given 121 | the value"demo". 122 | 123 | All the remaining arguments describe rows of stitches in the pattern. There are 124 | some common sense restrictions on the information that is acceptable. For example, 125 | there must be at least one row. Row numbers must form a consecutive sequence 126 | starting at 1. The number of stitches consumed by a row must equal the number of 127 | stitches produced by the previous row (except for short rows). And so on. 128 | 129 | 130 | row(...) ... 131 | rows(...) ... 132 | 133 | The `row` function (or, equivalently, `rows`) describes the stitches in one or 134 | more rows of the pattern. The function takes two sets of arguments. 135 | 136 | The first set of arguments must include at least one row number, or an expression 137 | that evaluates to a list of row numbers. It can include some optional keywords. 138 | 139 | The second set of arguments describes the stitches in the row. Various different 140 | kinds of stitches can be specified, as well as how many of each stitch, and the 141 | color of yarn used to knit them. The total number of stitches need not necessarily 142 | be made explicit if this can be inferred from other information in the pattern. 143 | 144 | The definitions for "demo" have the following meaning. Rows 1 and 3 are knit, and 145 | contain 8 stitches. Rows 2 and 4 are purled. Bind off in row 5. 146 | 147 | 148 | CHART OUTPUT 149 | 150 | The `show` function opens a web browser to display the pattern as a knitting chart. 151 | Stitches are displayed on a grid, with each horizontal line corresponding to a row 152 | in the pattern. Row numbers are displayed on either side of the grid. Rows that are 153 | knit from left to right have their corresponding row number printed on the left. 154 | Row numbers knit in the opposite direction are displayed on the right. 155 | 156 | A stitch may occupy one or more columns in the grid, depending on how many stitches 157 | it consumes and/or produces. Different symbols are used to represent the various 158 | types of stitch. The background color is determined by the color of the yarn used 159 | to knit each stitch. 160 | 161 | Note that the same symbol is used for knit stitches on odd-numbered rows and purl 162 | stitches on even-numbered rows. This is because the default pattern is set up for 163 | hand knitting, so that the direction of knitting switches at the end of each row. 164 | 165 | 166 | TEXT OUTPUT 167 | 168 | The `text` function displays written instructions for knitting the pattern. 169 | The introductory paragraph provides details on some of the main options that are 170 | specified using the `pattern` function keyword arguments. We can see that for 171 | our demonstration pattern, using the default arguments results in a hand 172 | knitting pattern instead of a machine knitting pattern. Other defaults include 173 | knitting flat rather than in the round, and knitting the first row on the RS 174 | (right side) of the workpiece from right to left. 175 | 176 | The second paragraph shows which yarns are used in the pattern. The default is 177 | to use a single yarn, called MC (main color), for everything. The default yarn 178 | color is white (#FFFFFF in RGB hex code). 179 | 180 | The rest of the pattern describes each row in turn in the order that the 181 | stitches are knitted. Stitches are abbreviated using standard notation, so that 182 | `k8` means knit 8 stitches, `p8` means purl 8 stitches, and `bo8` means bind 183 | off 8 stitches. In each case, the yarn used for the stitches is also specified. 184 | The description also specifies the number of stitches consumed by the first row, 185 | and the number of stitches produced by the final row. 186 | 187 | 188 | NEXT STEPS 189 | 190 | Try looking in the Knotty manual for more example files and documentation: 191 | https://docs.racket-lang.org/knotty/index.html 192 | 193 | |# 194 | -------------------------------------------------------------------------------- /knotty-lib/diophantine.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (provide diophantine 22 | diophantine-alt) 23 | (require "global.rkt") 24 | 25 | ;; Solves linear Diophantine equation ax + b = cy + d for non-negative integers x, y 26 | (: diophantine : Natural Natural Natural Natural -> (values (Option Natural) (Option Natural))) 27 | (define (diophantine a b c d) 28 | (dlog (format "Diophantine equation ~a * x + ~a = ~a * y + ~a" a b c d)) 29 | ;; rearrange to ax - cy = (d - b) 30 | (diophantine-alt a c (- d b))) 31 | 32 | ;; Solves linear Diophantine equation ax - cy = rhs for non-negative integers x, y 33 | (: diophantine-alt : Natural Natural Integer -> (values (Option Natural) (Option Natural))) 34 | (define (diophantine-alt a c rhs) 35 | (dlog (format "Reduced Diophantine equation ~a * x - ~a * y = ~a" a c rhs)) 36 | (if (zero? rhs) 37 | ;; trivially 38 | (solution 0 0) 39 | ;; there exist integral solutions <=> GCD(a,c) | rhs 40 | (let ([divisor (gcd a c)]) 41 | (if (zero? divisor) 42 | (result #f #f) 43 | (if (not (zero? (modulo rhs divisor))) 44 | ;; no solution 45 | (result #f #f) 46 | ;; divide through by GCD to get 47 | ;; ix - jy = k 48 | ;; where i, j are mutually prime 49 | (let* ([i (quotient a divisor)] 50 | [j (quotient c divisor)] 51 | [k (quotient rhs divisor)] 52 | [s (if (>= i j) 1 -1)] 53 | [t (* s k)]) 54 | ;; e is the greater of i and j, f is the smaller 55 | ;; if e = f = 1 56 | (let-values ([(e f) (if (>= i j) 57 | (values i j) 58 | (values j i))]) 59 | (dlog "Working values:") 60 | (dlog (format "a ~a" a)) 61 | (dlog (format "c ~a" c)) 62 | (dlog (format "rhs ~a" rhs)) 63 | (dlog (format "i ~a" i)) 64 | (dlog (format "j ~a" j)) 65 | (dlog (format "k ~a" k)) 66 | (dlog (format "e ~a" e)) 67 | (dlog (format "f ~a" f)) 68 | (dlog (format "s ~a" s)) 69 | (dlog (format "t ~a" t)) 70 | ;; solutions for e,f <= 1 71 | (if (zero? f) 72 | (if (negative? t) 73 | (result #f #f) 74 | (if (positive? s) 75 | (solution t 0) 76 | (solution 0 t))) 77 | (if (= 1 e) 78 | (if (positive? t) 79 | (solution t 0) 80 | (solution 0 (- t))) 81 | (if (= 1 f) 82 | (let ([u (- e t)]) 83 | (if (positive? s) 84 | (reduce 1 u i j) 85 | (reduce u 1 i j))) 86 | ;; solution for e,f > 1 87 | (let-values ([(p q) (euclidean e f)]) 88 | (reduce (* p t) (* q t) i j)))))))))))) 89 | 90 | ;; Reduce coefficients to lowest non-negative values. 91 | (: reduce : Integer Integer Natural Natural -> (values Natural Natural)) 92 | (define (reduce x y i j) 93 | (let* ([u (floor (/ x j))] 94 | [v (floor (/ y i))] 95 | [m (min u v)] 96 | [x~ (- x (* m j))] 97 | [y~ (- y (* m i))]) 98 | (assert (natural? x~)) 99 | (assert (natural? y~)) 100 | (solution x~ y~))) 101 | 102 | ;; Apply Euclidean algorithm to find GCD by repeated division 103 | ;; to solve e * x - f * y = 1 104 | (: euclidean : Integer Integer -> (values Integer Integer)) 105 | (define (euclidean e f) 106 | (if (zero? f) 107 | (values 0 0) 108 | (let*-values ([(q r) (quotient/remainder e f)] 109 | [(p~ q~) (euclidean f r)]) 110 | (substitute e f 1 q p~ q~)))) 111 | 112 | ;; Recursively substitute remainders to obtain equation for GCD 113 | ;; in terms of the original parameters. 114 | ;; Each equation is of the form p * e - q * f = r 115 | ;; p~, q~ are the coefficients from the next equation in the sequence. 116 | (: substitute : Integer Integer Integer Integer Integer Integer -> (values Integer Integer)) 117 | (define (substitute e f p q p~ q~) 118 | (let* ([r (- (* p e) (* q f))]) ;; remainder 119 | (if (< r 2) 120 | (begin 121 | (dlog (format "Working equation ~a * ~a - ~a * ~a = ~a" p e q f r)) 122 | (values p q)) 123 | (substitute e 124 | f 125 | (- (* p q~)) 126 | (- 0 p~ (* q q~)) 127 | 0 128 | 0)))) 129 | 130 | ;; Returns result 131 | (: result : (Option Natural) (Option Natural) -> (values (Option Natural) (Option Natural))) 132 | (define (result x y) 133 | (if (or (false? x) 134 | (false? y)) 135 | (begin 136 | (dlog "No solution") 137 | (values x y)) 138 | (solution x y))) 139 | 140 | ;; Returns solution 141 | (: solution : Natural Natural -> (values Natural Natural)) 142 | (define (solution x y) 143 | (dlog (format "Solution: x=~a, y=~a" x y)) 144 | (values x y)) 145 | -------------------------------------------------------------------------------- /knotty-lib/garn.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | 6 | MIT License 7 | 8 | Copyright (c) 2023 Tom Price. 9 | 10 | Incorporating concepts from https://pypi.org/project/knit-script/ 11 | Copyright (c) 2022 Megan Hofmann, Northeastern University Khoury College of 12 | Computer Sciences Accessible Creative Technologies (ACT) Lab and Contributors. 13 | 14 | Permission is hereby granted, free of charge, to any person obtaining a copy 15 | of this software and associated documentation files (the "Software"), to deal 16 | in the Software without restriction, including without limitation the rights 17 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | copies of the Software, and to permit persons to whom the Software is 19 | furnished to do so, subject to the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included in all 22 | copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 26 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 27 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 28 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | |# 31 | 32 | (provide (all-defined-out)) 33 | 34 | (require threading) 35 | (require "util.rkt" 36 | "loop.rkt") 37 | 38 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 39 | 40 | ;; Yarn struct definition. 41 | ;; 42 | ;; Attributes: 43 | ;; id : Yarn-Id 44 | ;; A maximum of 256 different yarns are permitted, not including cuts. 45 | ;; loops : (Listof Loop-Id) 46 | ;; A list of IDs of the Loops on the yarn, ordered from beginning to end. 47 | ;; last-loop-id : (Option Loop-Id) 48 | ;; The ID of the last Loop on the yarn, or False if there are no Loops on the yarn. 49 | ;; 50 | ;; FIXME additional attributes, including color and weight. 51 | (struct Garn 52 | ([id : Yarn-Id] 53 | [loops : (Listof Loop-Id)] 54 | [last-loop-id : (Option Loop-Id)]) 55 | #:mutable 56 | #:transparent) 57 | 58 | ;; Alternative constructor. 59 | (: make-yarn (->* (Yarn-Id) ((Option Loop)) Garn)) 60 | (define (make-yarn yarn-id [last-loop #f]) 61 | (Garn yarn-id null #f)) 62 | 63 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 64 | 65 | ;; Parameter: 66 | ;; self : Garn 67 | ;; The yarn. 68 | ;; 69 | ;; Return: 70 | ;; The number of loops on the yarn. 71 | (: yarn-length : Garn -> Natural) 72 | (define (yarn-length self) 73 | (~> self 74 | Garn-loops 75 | length)) 76 | 77 | ;; Parameter: 78 | ;; self : Garn 79 | ;; The yarn. 80 | ;; loop : (U Loop-Id Loop) 81 | ;; The ID of the Loop in question, or the Loop itself. 82 | ;; 83 | ;; Return: 84 | ;; True if the yarn contains the specified loop, otherwise False. 85 | (: yarn-has-loop? : Garn (U Loop-Id Loop) -> Boolean) 86 | (define (yarn-has-loop? self loop) 87 | (~>> self 88 | Garn-loops 89 | (memq (loop->id loop)) 90 | truthy?)) 91 | 92 | ;; Parameter: 93 | ;; self : Garn 94 | ;; The yarn. 95 | ;; loop : (U Loop-Id Loop) 96 | ;; The ID of the Loop in question, or the Loop itself. 97 | (: yarn-remove-loop! : Garn (U Loop-Id Loop) -> Void) 98 | (define (yarn-remove-loop! self loop) 99 | (set-Garn-loops! self (remove (loop->id loop) (Garn-loops self))) 100 | (set-Garn-last-loop-id! self 101 | (if (null? (Garn-loops self)) 102 | #f 103 | (last (Garn-loops self))))) 104 | 105 | ;; Parameter: 106 | ;; self : Garn 107 | ;; The yarn. 108 | ;; 109 | ;; Return: 110 | ;; New yarn with the same attributes, but different ID. 111 | (: yarn-cut : Garn -> Garn) 112 | (define (yarn-cut self) 113 | ;; FIXME copy color, weight, and other attributes 114 | (make-yarn (+ (Garn-id self) #x100))) 115 | 116 | ;; end 117 | -------------------------------------------------------------------------------- /knotty-lib/gauge.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (provide (all-defined-out)) 22 | 23 | (require "global.rkt") 24 | 25 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 26 | 27 | (define-type 28 | Measurement-Unit 29 | (U 'cm 'inch)) 30 | (define-predicate Measurement-Unit? Measurement-Unit) 31 | 32 | ;; Gauge struct. 33 | ;; related: yarn weight, needle size/machine needle spacing, aspect ratio 34 | (struct Gauge 35 | ([stitch-count : Positive-Integer] 36 | [stitch-measurement : Positive-Integer] 37 | [row-count : Positive-Integer] 38 | [row-measurement : Positive-Integer] 39 | [measurement-unit : Measurement-Unit]) 40 | #:prefab) 41 | 42 | ;; default Gauge 43 | (define default-pattern-gauge #f) 44 | 45 | (: gauge-unit : Gauge -> String) 46 | (define (gauge-unit self) 47 | (if (eq? 'cm (Gauge-measurement-unit self)) 48 | " cm" 49 | "\"")) 50 | 51 | (: gauge->aspect-ratio : (Option Gauge) -> Float) 52 | (define (gauge->aspect-ratio self) 53 | (if (false? self) 54 | 0.80 ;; default aspect ratio 55 | (/ (* (Gauge-row-measurement self) (Gauge-stitch-count self) 1.0) 56 | (* (Gauge-stitch-measurement self) (Gauge-row-count self) 1.0)))) 57 | 58 | ;; end 59 | -------------------------------------------------------------------------------- /knotty-lib/global.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (provide (all-defined-out) 22 | (for-syntax STITCH-MACRO-MAX-NUMBER)) 23 | 24 | (require syntax/parse/define ;; for `define-syntax-parse-rule` 25 | racket/runtime-path) 26 | 27 | ;; Define global constants 28 | 29 | ;; Version 30 | (define knotty-version : String "KNOTTY-VERSION") 31 | 32 | ;; File path to resources 33 | (define-runtime-path resources-path 34 | "resources") 35 | 36 | ;; File path to saxon jar file 37 | (define-runtime-path saxon-path 38 | (build-path "resources" "SaxonHE11-5J" "saxon-he-11.5.jar")) 39 | 40 | ;; Pattern option enum type definitions 41 | (define-type 42 | Technique 43 | (U 'hand 44 | 'machine)) 45 | (define-predicate Technique? Technique) 46 | 47 | (define-type 48 | Form 49 | (U 'flat 'circular)) 50 | (define-predicate Form? Form) 51 | 52 | (define-type 53 | Face 54 | (U 'rs 'ws)) 55 | (define-predicate Face? Face) 56 | 57 | (define-type 58 | Side 59 | (U 'left 'right)) 60 | (define-predicate Side? Side) 61 | 62 | ;; Short row Turn enum type 63 | (define-type 64 | Turn 65 | (U 'no-turn 'turn 'w&t)) 66 | (define-predicate Turn? Turn) 67 | 68 | ;;Ddefaults 69 | (define default-pattern-technique 'hand) 70 | (define default-pattern-form 'flat) 71 | (define default-pattern-face 'rs) 72 | (define default-pattern-side 'right) 73 | 74 | ;; Run-time parameter. 75 | ;; Set to #f makes guard functions that protect against invalid 76 | ;; pattern settings return warnings instead of error messages. 77 | (define 78 | SAFE : (Parameterof Boolean) 79 | (make-parameter #t)) 80 | 81 | ;; Compile-time parameter. 82 | ;; Controls generation of stitch macros. 83 | (define-for-syntax 84 | STITCH-MACRO-MAX-NUMBER 85 | (make-parameter 50)) 86 | 87 | ;; logger 88 | (define knotty-logger 89 | (make-logger 'knotty (current-logger))) 90 | 91 | ;; log receiver 92 | (define knotty-receiver 93 | (make-log-receiver knotty-logger 'debug)) 94 | 95 | (: wlog : String -> Void) 96 | (define (wlog msg) 97 | (log-message knotty-logger 'warning msg #f)) 98 | 99 | (: ilog : String -> Void) 100 | (define (ilog msg) 101 | (log-message knotty-logger 'info msg #f)) 102 | 103 | (: dlog : String -> Void) 104 | (define (dlog msg) 105 | (log-message knotty-logger 'debug msg #f)) 106 | 107 | ;; Sets up thread to print output from log receiver. 108 | ;; Log receiver level set in cli.rkt 109 | ;; Default level is 'warning 110 | (define (setup-log-receiver log-level) 111 | (thunk 112 | (thread 113 | (thunk 114 | (let sync-loop () 115 | (let* ([v (sync knotty-receiver)] 116 | [msg-level (vector-ref v 0)]) 117 | (when (and (not (eq? 'none log-level)) 118 | (or (eq? 'fatal msg-level) 119 | (and (not (eq? 'fatal log-level)) 120 | (or (eq? 'error msg-level) 121 | (and (not (eq? 'error log-level)) 122 | (or (eq? 'warning msg-level) 123 | (and (not (eq? 'warning log-level)) 124 | (or (eq? 'info msg-level) 125 | (eq? 'debug log-level))))))))) 126 | (eprintf "[~a] ~a\n" 127 | msg-level 128 | (vector-ref v 1)))) 129 | ;; kill thread if sent a message 130 | (when (thread-try-receive) 131 | (kill-thread (current-thread))) 132 | (sync-loop)))))) 133 | 134 | ;; Raises parameterized error message. 135 | (define-syntax (err stx) 136 | (syntax-parse stx 137 | [(err param:id msg) 138 | #`(if (param) 139 | #,(syntax/loc stx (error msg)) 140 | (log-message knotty-logger 'error msg #f))])) -------------------------------------------------------------------------------- /knotty-lib/gui.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (provide show 22 | export-html) 23 | 24 | (require racket/fixnum) 25 | (require "global.rkt" 26 | "util.rkt" 27 | "stitch.rkt" 28 | "tree.rkt" 29 | "yarn.rkt" 30 | "macros.rkt" 31 | "rows.rkt" 32 | "rowspec.rkt" 33 | "rowmap.rkt" 34 | "options.rkt" 35 | "pattern.rkt" 36 | "chart-row.rkt" 37 | "chart.rkt") 38 | (require/typed "html.rkt" 39 | [pattern-template (->* (Output-Port Pattern (HashTable Symbol Integer)) (Boolean) Void)]) 40 | (require/typed "serv.rkt" 41 | [serve-pattern (Pattern Positive-Integer Positive-Integer -> Void)]) 42 | 43 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 44 | 45 | ;; Displays Pattern as webpage. 46 | (: show : Pattern -> Void) 47 | (define (show p) 48 | (serve-pattern p 2 2)) 49 | 50 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 51 | 52 | ;; Exports static HTML page. 53 | (: export-html (->* (Pattern Path-String) (Positive-Integer Positive-Integer #:exports-with (Path-String -> Output-Port)) Void)) 54 | (define (export-html p filename [h 1] [v 1] 55 | #:exports-with [open-output-file open-output-file]) 56 | (let ([inputs 57 | (make-hasheq 58 | `((stat . 1) 59 | (hreps . ,h) 60 | (vreps . ,v) 61 | (zoom . 80) 62 | (float . 0) 63 | (notes . 0) 64 | (yarn . 0) 65 | (instr . 0) 66 | (size . 400)))] 67 | [out (open-output-file filename)]) 68 | (pattern-template out p inputs) 69 | (close-output-port out))) 70 | 71 | ;; end -------------------------------------------------------------------------------- /knotty-lib/info.rkt: -------------------------------------------------------------------------------- 1 | #lang info 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (define collection 22 | "knotty") 23 | 24 | (define version 25 | "0.1") 26 | 27 | (define pkg-desc 28 | "A domain-specific language for knitting patterns. Implementation only: no documentation") 29 | 30 | (define deps 31 | '("base" 32 | "typed/racket" 33 | "typed-racket-lib" 34 | "typed-racket-more" 35 | "sweet-exp-lib" 36 | "named-arguments" 37 | "threading-lib" 38 | "brag-lib" 39 | "br-parser-tools" 40 | "web-server-lib" 41 | "sxml" 42 | "html-template" 43 | "html-writing" 44 | "html-parsing")) 45 | 46 | (define build-deps 47 | '("lazy" 48 | "sweet-exp-lib" 49 | "threading-lib")) 50 | 51 | (define license 52 | 'LGPL-3.0-or-later) 53 | 54 | (define pkg-authors 55 | '(Tom Price)) 56 | -------------------------------------------------------------------------------- /knotty-lib/knitspeak-grammar.rkt: -------------------------------------------------------------------------------- 1 | #lang brag 2 | 3 | ;; Knotty, a domain specific language for knitting patterns. 4 | ;; 5 | ;; MIT License 6 | ;; 7 | ;; Copyright (c) 2023 Tom Price. 8 | ;; 9 | ;; Incorporating concepts from https://pypi.org/project/knit-script/ 10 | ;; Copyright (c) 2022 Megan Hofmann, Northeastern University Khoury College of 11 | ;; Computer Sciences Accessible Creative Technologies (ACT) Lab and Contributors. 12 | ;; 13 | ;; Permission is hereby granted, free of charge, to any person obtaining a copy 14 | ;; of this software and associated documentation files (the "Software"), to deal 15 | ;; in the Software without restriction, including without limitation the rights 16 | ;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | ;; copies of the Software, and to permit persons to whom the Software is 18 | ;; furnished to do so, subject to the following conditions: 19 | ;; 20 | ;; The above copyright notice and this permission notice shall be included in all 21 | ;; copies or substantial portions of the Software. 22 | ;; 23 | ;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | ;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 25 | ;; FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 26 | ;; COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 27 | ;; IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 28 | ;; CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | ;; gathers, wrapped stitches, threaded stitches, and empty repeats are not supported. 31 | 32 | pattern: statement+ 33 | 34 | statement: course-statement /PERIOD /SPACE? 35 | 36 | course-statement: course-ids /colon stitch-statement-list stitch-count? 37 | | /REPEAT /SPACE /COURSE-TYPE /SPACE course-id-or-range 38 | 39 | course-ids: COURSE-TYPE /SPACE course-id-list [/SPACE face] 40 | 41 | course-id-list: course-id-or-range (/list-sep course-id-or-range)* 42 | 43 | course-id-or-range: course-id 44 | | /FROM /SPACE course-id /SPACE /TO /SPACE course-id 45 | | course-id /SPACE? /HYPHEN /SPACE? course-id 46 | 47 | course-id: INTEGER 48 | 49 | list-sep: COMMA /SPACE? 50 | | /SPACE AND /SPACE 51 | | /COMMA /SPACE AND /SPACE 52 | | SPACE 53 | 54 | face: FACE 55 | | /LPAREN FACE /RPAREN 56 | 57 | colon: SPACE? COLON SPACE? 58 | 59 | 60 | 61 | stitch-statement-list: stitch-statement (/list-sep stitch-statement)* 62 | 63 | stitch-statement: conditional-stitch-statement 64 | | static-stitch-statement 65 | 66 | conditional-stitch-statement: conditional-stitch-group [/SPACE /TO /SPACE repeat-condition] 67 | 68 | conditional-stitch-group: /STAR /SPACE? static-stitch-statement-list /list-sep /REPEAT /SPACE /FROM /SPACE /STAR 69 | | (KNIT | PURL) [/SPACE (TBL | BELOW | WRAPPING-YARN /SPACE count)] 70 | | BO 71 | | CO 72 | 73 | repeat-condition: /LAST /SPACE INTEGER? /SPACE? STITCH 74 | | /LAST /SPACE INTEGER /SPACE? STITCHES 75 | | END 76 | 77 | static-stitch-statement-list: static-stitch-statement (/list-sep static-stitch-statement)* 78 | 79 | static-stitch-statement: static-stitch-group 80 | | stitch-run 81 | 82 | static-stitch-group: /LBRACKET static-stitch-statement-list /RBRACKET [/SPACE count] 83 | 84 | count: TWICE 85 | | INTEGER /SPACE TIMES 86 | ; | ONCE 87 | 88 | stitch-run: YO 89 | | (KNIT | PURL) INTEGER [/SPACE (TBL | BELOW)] 90 | | (KNIT INTEGER | PURL INTEGER | YO) /SPACE WRAPPING-YARN /SPACE count 91 | | (BO | CO | DROP) (INTEGER | /SPACE STITCH) 92 | | (BO | CO | DROP) /SPACE INTEGER /SPACE (/STITCH | /STITCHES) 93 | | SLIP INTEGER /SPACE [WYIB | WYIF] 94 | | DIP /SPACE /STITCH 95 | | ONE-TO INTEGER /SPACE INC 96 | | renamed-stitch 97 | ;| cluster-stitch 98 | | modifiable-stitch [/SPACE stitch-modifier] 99 | | twistable-stitch [/SPACE /TWISTED] 100 | | cable-head /SPACE cable-tail 101 | | stitch 102 | 103 | renamed-stitch: BUNNY-EARS-DEC 104 | | BUNNY-EARS-YO 105 | | BUNNY-EARS-BACK-DEC 106 | | BUNNY-EARS-BACK-YO 107 | | CTR-DBL-INC 108 | | M1 109 | | M1P 110 | | M1L 111 | | M1LP 112 | | M1R 113 | | M1RP 114 | | SKP 115 | | SL1-K2TOG-PSSO 116 | | SL2-K1-P2SSO 117 | | K1-P1-IN-NEXT-STITCH ;; not implemented in knotty 118 | | P1-K1-IN-NEXT-STITCH ;; not implemented in knotty 119 | | K1-P1-K1-IN-NEXT-STITCH ;; not implemented in knotty 120 | | P1-K1-P1-IN-NEXT-STITCH ;; not implemented in knotty 121 | | K1-YO-K1-IN-NEXT-STITCH 122 | | P1-YO-P1-IN-NEXT-STITCH 123 | 124 | ;; not implemented in knotty 125 | 126 | ;cluster-stitch: SL1-K1-YO-PSSO 127 | ; | SL1-K2-PSSO 128 | ; | SL1-P2-PSSO 129 | ; | SL1-K1-YO-K1-PSSO 130 | ; | SL1-K2-YO-PSSO 131 | ; | SL1-K3-PSSO 132 | ; | SL1-P3-PSSO 133 | ; | P2SO-YO-K1 134 | ; | P3SO-K1-YO-K1 135 | ; | P3SO-K1-YO-SSK 136 | ; | SL1-P3SO-K2TOG-YO-K1 137 | ; | YO-K2-PYO 138 | ; | YO-P2-PYO 139 | ; | YO-K3-PYO 140 | ; | YO-P3-PYO 141 | 142 | modifiable-stitch: K2TOG 143 | | K3TOG 144 | | P2TOG 145 | | P3TOG 146 | 147 | stitch-modifier: TBL 148 | | TWISTED 149 | 150 | twistable-stitch: CDD 151 | | CDDP 152 | 153 | cable-head: INTEGER /SLASH INTEGER [/SLASH INTEGER] 154 | 155 | cable-tail: LC 156 | | LCC ;; not implemented in knotty 157 | | LPC 158 | | LT 159 | | LPT 160 | | LSC ;; not implemented in knotty 161 | | LSAC ;; not implemented in knotty 162 | | RC 163 | | RCC ;; not implemented in knotty 164 | | RPC 165 | | RT 166 | | RPT 167 | | RSC ;; not implemented in knotty 168 | | RSAC ;; not implemented in knotty 169 | 170 | ;; FIXME add brioche stitches 171 | stitch: SSK ;; decreases 172 | ;| SSK2TOG 173 | | SSP 174 | ;| SSP2TOG 175 | | SSSK 176 | ;| SSSK3TOG 177 | | SSSP 178 | ;| SSSP3TOG 179 | 180 | | TURN ;; turns 181 | ;| TURNL 182 | ;| TURNR 183 | | W&T 184 | ;| W&TL 185 | ;| W&TR 186 | 187 | | MB ;; other 188 | | BRSL 189 | 190 | ;| SS ;; pattern stitches 191 | ;| RSS 192 | ;| GS 193 | 194 | 195 | 196 | ;; stitch counts are ignored by Knitspeak 197 | ;; https://stitch-maps.com/news/2015/11/stitch-counts-redux/ 198 | ;; https://www.ravelry.com/discuss/stitch-maps/3261964 199 | 200 | stitch-count: /SPACE /LPAREN (multiple-of | INTEGER /SPACE [more | fewer] (/STITCH | /STITCHES)) /RPAREN 201 | 202 | multiple-of: /MULTIPLE /SPACE /OF /SPACE INTEGER /SPACE (/STITCH | /STITCHES) plus? 203 | 204 | plus: /COMMA? /SPACE /PLUS /SPACE INTEGER 205 | 206 | more: /MORE /SPACE 207 | 208 | fewer: /FEWER /SPACE 209 | -------------------------------------------------------------------------------- /knotty-lib/loop.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | 6 | MIT License 7 | 8 | Copyright (c) 2023 Tom Price. 9 | 10 | Incorporating concepts from https://pypi.org/project/knit-script/ 11 | Copyright (c) 2022 Megan Hofmann, Northeastern University Khoury College of 12 | Computer Sciences Accessible Creative Technologies (ACT) Lab and Contributors. 13 | 14 | Permission is hereby granted, free of charge, to any person obtaining a copy 15 | of this software and associated documentation files (the "Software"), to deal 16 | in the Software without restriction, including without limitation the rights 17 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | copies of the Software, and to permit persons to whom the Software is 19 | furnished to do so, subject to the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included in all 22 | copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 26 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 27 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 28 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | |# 31 | 32 | (provide (all-defined-out)) 33 | 34 | (require threading 35 | racket/function) 36 | (require "util.rkt") 37 | 38 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 39 | 40 | (define-type Loop-Id Natural) 41 | (define-predicate Loop-Id? Loop-Id) 42 | 43 | (define-type Yarn-Id Natural) 44 | (define-predicate Yarn-Id? Yarn-Id) 45 | 46 | ;; Loop struct definition. 47 | ;; 48 | ;; Attributes: 49 | ;; id : Loop-Id 50 | ;; Unique ID number of the loop. 51 | ;; yarn-ids : (Listof Yarn-Id) 52 | ;; IDs of the Garn structs that the loop is made on. 53 | ;; layer: Integer 54 | ;; The position of this loop relative to other other loops, for instance in 55 | ;; cables and gauged sheets. Lower numbers are closer to the top. Higher 56 | ;; numbers are closer to the bottom of the piece. 57 | ;; Default is 0. 58 | ;; twisted? : Boolean 59 | ;; True if the loop is twisted. Twisted loops are not feasible on knitting 60 | ;; machines, so the default is False. 61 | ;; parents : (Listof Loop-Id) 62 | ;; The list of loops that this loop is pulled through. 63 | ;; The order of the list implies the stacking order, with the first loop at 64 | ;; the bottom the stack. 65 | (struct Loop 66 | ([id : Loop-Id] 67 | [yarn-ids : (Listof Yarn-Id)] 68 | [layer : Integer] 69 | [twisted? : Boolean] 70 | [parents : (Listof Loop-Id)]) ;; ordered from bottom to top of stack 71 | #:prefab) 72 | 73 | ;; Alternative constructor. 74 | (: make-loop (->* (Loop-Id (U Yarn-Id (Listof Yarn-Id))) (Integer Boolean) Loop)) 75 | (define (make-loop loop-id yarn-ids [layer 0] [twisted? #f]) 76 | (let ([yarn-ids~ 77 | (if (Yarn-Id? yarn-ids) 78 | (list yarn-ids) 79 | (sort yarn-ids <))]) 80 | (Loop loop-id yarn-ids~ layer twisted? null))) 81 | 82 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 83 | 84 | ;; Adds the ID of the parent Loop onto the stack of parent loop IDs. 85 | ;; 86 | ;; Parameters: 87 | ;; self : Loop 88 | ;; The loop to be altered. 89 | ;; parent : (U Loop-Id Loop) 90 | ;; The ID of a Loop to be added onto the stack, or the Loop itself. 91 | ;; stack-position : ((Option Natural)) 92 | ;; The position in the stack in which to insert the parent. 93 | ;; Default is to add to the top of the stack. 94 | ;; 95 | ;; Return: 96 | ;; The modified loop. 97 | (: loop-add-parent (->* (Loop (U Loop-Id Loop)) ((Option Natural)) Loop)) 98 | (define (loop-add-parent self parent [stack-position #f]) 99 | (let ([parent-id (loop->id parent)]) 100 | (if (false? stack-position) 101 | (struct-copy Loop self 102 | [parents (append (Loop-parents self) (list parent-id))]) 103 | (let-values ([(before after) (split-at (Loop-parents self) stack-position)]) 104 | (struct-copy Loop self 105 | [parents (append before (list parent-id) after)]))))) 106 | 107 | ;; Removes the ID of the parent Loop from the stack of parent loop IDs. 108 | ;; 109 | ;; Parameters: 110 | ;; self : Loop 111 | ;; The loop to be altered. 112 | ;; parent : (U Loop-Id Loop) 113 | ;; The ID of Loop to be removed from the stack, or the Loop itself. 114 | ;; 115 | ;; Return: 116 | ;; The modified loop. 117 | (: loop-remove-parent : Loop (U Loop-Id Loop) -> Loop) 118 | (define (loop-remove-parent self parent) 119 | (let* ([parents (Loop-parents self)] 120 | [idx (findf-index (curry eq? (loop->id parent)) 121 | parents)]) 122 | (if (false? idx) 123 | self 124 | (struct-copy Loop self 125 | [parents (append 126 | (take parents idx) 127 | (drop parents (add1 idx)))])))) 128 | 129 | ;; Parameters: 130 | ;; self : (U Loop-Id Loop) 131 | ;; The ID of a Loop, or the Loop itself. 132 | ;; 133 | ;; Return: 134 | ;; The ID of the loop. 135 | (: loop->id : (U Loop-Id Loop) -> Loop-Id) 136 | (define (loop->id self) 137 | (if (Loop-Id? self) 138 | self 139 | (Loop-id self))) 140 | 141 | ;; Parameters: 142 | ;; loop-id : Loop-Id 143 | ;; A Loop-Id. 144 | ;; self : Loop 145 | ;; A Loop. 146 | ;; 147 | ;; Return: 148 | ;; True if the Loop has the specified ID, otherwise False. 149 | (: loop-has-id? : Loop-Id Loop -> Boolean) 150 | (define (loop-has-id? loop-id self) 151 | (= loop-id (Loop-id self))) 152 | 153 | ;; end 154 | -------------------------------------------------------------------------------- /knotty-lib/main.rkt: -------------------------------------------------------------------------------- 1 | #lang sweet-exp typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | ;; To install (from within the package directory): 22 | ;; $ raco pkg install 23 | ;; To install (from pkgs.racket-lang.org): 24 | ;; $ raco pkg install knotty-lib 25 | ;; To uninstall: 26 | ;; $ raco pkg remove knotty-lib 27 | ;; To view documentation: 28 | ;; $ raco docs knotty-lib 29 | 30 | (provide (all-from-out "global.rkt") 31 | (all-from-out "stitch.rkt") 32 | (all-from-out "stitch-instructions.rkt") 33 | (all-from-out "tree.rkt") 34 | (all-from-out "yarn.rkt") 35 | (all-from-out "macros.rkt") 36 | (all-from-out "rows.rkt") 37 | (all-from-out "rowspec.rkt") 38 | (all-from-out "rowmap.rkt") 39 | (all-from-out "options.rkt") 40 | (all-from-out "gauge.rkt") 41 | (all-from-out "pattern.rkt") 42 | (all-from-out "html.rkt") 43 | (all-from-out "text.rkt") 44 | (all-from-out "serv.rkt") 45 | (all-from-out "gui.rkt") 46 | (all-from-out "knitspeak.rkt") 47 | (all-from-out "chart-row.rkt") 48 | (all-from-out "chart.rkt") 49 | (all-from-out "png.rkt") 50 | ;(all-from-out "dak.rkt") 51 | (all-from-out "xml.rkt") 52 | (all-from-out named-arguments/square-brackets)) 53 | 54 | (require "global.rkt" 55 | "util.rkt" 56 | "stitch.rkt" 57 | "stitch-instructions.rkt" 58 | "tree.rkt" 59 | "yarn.rkt" 60 | "macros.rkt" 61 | "rows.rkt" 62 | "rowspec.rkt" 63 | "rowmap.rkt" 64 | "options.rkt" 65 | "gauge.rkt" 66 | "pattern.rkt" 67 | "html.rkt" 68 | "text.rkt" 69 | "serv.rkt" 70 | "gui.rkt" 71 | "knitspeak.rkt" 72 | "chart-row.rkt" 73 | "chart.rkt" 74 | "png.rkt" 75 | ;"dak.rkt" 76 | "xml.rkt" 77 | "gui.rkt" 78 | named-arguments/square-brackets) 79 | 80 | ;; FIXME test chart, text output vs stitch-maps.com with some standard lace patterns 81 | ;; FIXME improve error messages/exception handling 82 | ;; FIXME refactor stitch, pattern etc as classes? 83 | 84 | (module* main racket 85 | ;; Main submodule. 86 | ;; This code is executed when this file is run using DrRacket or the `racket` executable. 87 | ;; The code does not run when the file is required by another module. 88 | ;; Documentation: http://docs.racket-lang.org/guide/Module_Syntax.html#%28part._main-and-test 89 | 90 | ;; create lookup table for chart symbols (knotty-stitches.xml) 91 | (require threading 92 | sxml) 93 | (require "global.rkt" 94 | "stitch.rkt" 95 | "stitch-instructions.rkt") 96 | 97 | (define stitch-sxml 98 | (append 99 | '((*PI* (xml (version "1.0") (encoding "utf-8")))) 100 | (list 101 | (append 102 | '(stitches) 103 | (for/list ([id (in-list (filter (compose not false?) (hash-keys stitch-hash)))]) 104 | (let* ([st (get-stitchtype id)] 105 | [rs-sym (~a id)] 106 | [ws-sym (~a (Stitchtype-ws-symbol st))] 107 | [h-instr (get-stitch-instructions id #t)] 108 | [m-instr (get-stitch-instructions id #f)] 109 | [rs-str (bytes->string/latin-1 (Stitchtype-rs-string st))] 110 | [ws-str (bytes->string/latin-1 (Stitchtype-ws-string st))] 111 | [width (~a (Stitchtype-width st))] 112 | [cable? (if (Stitchtype-cable? st) "1" "0")] 113 | [st-in (~a (Stitchtype-stitches-in st))] 114 | [st-out (~a (Stitchtype-stitches-out st))] 115 | [offset (~a (Stitchtype-offset st))] 116 | [rep? (if (Stitchtype-repeatable? st) "1" "0")] 117 | [var? (if (Stitchtype-variable-repeat? st) "1" "0")] 118 | [h? (if (Stitchtype-hand-compatible? st) "1" "0")] 119 | [m? (if (Stitchtype-machine-compatible? st) "1" "0")]) 120 | `(stitch (rs-symbol ,rs-sym) 121 | (ws-symbol ,ws-sym) 122 | (rs-string ,rs-str) 123 | (ws-string ,ws-str) 124 | (width ,width) 125 | (cable ,cable?) 126 | (stitches-in ,st-in) 127 | (stitches-out ,st-out) 128 | (offset ,offset) 129 | (repeatable ,rep?) 130 | (variable-repeat ,var?) 131 | (hand-compatible ,h?) 132 | (machine-compatible ,m?) 133 | (hand-instructions ,h-instr) 134 | (machine-instructions ,m-instr)))))))) 135 | 136 | (let* ([filename "knotty-stitch.xml"] 137 | [filedir (build-path resources-path "xml")] 138 | [filepath (build-path filedir filename)] 139 | [backup-name "knotty-stitch~.xml"] 140 | [backup-dir (build-path resources-path "backups")] 141 | [backup-path (build-path backup-dir backup-name)]) 142 | 143 | ;; backup old file 144 | (when (file-exists? filepath) 145 | (begin 146 | (unless (directory-exists? backup-dir) 147 | (make-directory backup-dir)) 148 | (when (file-exists? backup-path) 149 | (delete-file backup-path)) 150 | (rename-file-or-directory filepath backup-path))) 151 | 152 | ;; write new file 153 | (let* ([out (open-output-file filepath)] 154 | [output-str (srl:sxml->xml stitch-sxml)] 155 | ;; fix broken string encoding 156 | [output-str~ (regexp-replaces 157 | output-str 158 | '([#px"&(?=#)" "&"]))]) 159 | (write-bytes (string->bytes/utf-8 output-str~) out) 160 | (close-output-port out)) 161 | 162 | ;; make knotty.xsd 163 | (let ([cmd (string-append 164 | "java -jar " 165 | (path->string saxon-path) 166 | " -s:" 167 | (path->string filepath) 168 | " -xsl:" 169 | (path->string (build-path resources-path "xml" "knotty-make-xsd.xsl")) 170 | " -o:" 171 | (path->string (build-path resources-path "xml" "knotty.xsd")))]) 172 | (println cmd) 173 | (system cmd)))) 174 | 175 | ;; end 176 | -------------------------------------------------------------------------------- /knotty-lib/options.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (provide (all-defined-out)) 22 | (require "global.rkt" 23 | "util.rkt" 24 | "gauge.rkt") 25 | 26 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 27 | 28 | ;; Options struct. 29 | (struct Options 30 | ([technique : Technique] 31 | [form : Form] 32 | [face : Face] 33 | [side : Side] 34 | [gauge : (Option Gauge)]) 35 | #:guard 36 | (λ (technique form face side gauge type-name) 37 | (dlog "in `Options` struct guard function") 38 | (options-guard technique form face side gauge)) 39 | #:transparent) 40 | 41 | (: options-guard (Technique 42 | Form 43 | Face 44 | Side 45 | (Option Gauge) -> (values Technique 46 | Form 47 | Face 48 | Side 49 | (Option Gauge)))) 50 | (define (options-guard technique form face side gauge) 51 | ;; hand knits that start on the right side are knitted right-to-left 52 | (when (and (eq? technique 'hand) 53 | (eq? face 'rs) 54 | (eq? side 'left)) 55 | (err SAFE "hand knits that start on the right side must be knitted right-to-left")) 56 | ;; hand knits that start on the wrong side are knitted left-to-right 57 | (when (and (eq? technique 'hand) 58 | (eq? face 'ws) 59 | (eq? side 'right)) 60 | (err SAFE "hand knits that start on the wrong side must be knitted left-to-right")) 61 | (values technique form face side gauge)) 62 | 63 | ;; Default Options. 64 | (define default-options : Options 65 | (Options 66 | default-pattern-technique 67 | default-pattern-form 68 | default-pattern-face 69 | default-pattern-side 70 | default-pattern-gauge)) 71 | 72 | ;; Utility functions 73 | 74 | ;; Is row r knit on RS? 75 | ;; Row numbers are 1-indexed 76 | (: options-row-rs? : Options Positive-Integer -> Boolean) 77 | (define (options-row-rs? self r) 78 | (let* ([hand? : Boolean (eq? (Options-technique self) 'hand)] 79 | [flat? : Boolean (eq? (Options-form self) 'flat)] 80 | [rs? : Boolean (eq? (Options-face self) 'rs)]) 81 | (row-rs? hand? flat? rs? r))) 82 | 83 | ;; Is row r knit on RS? 84 | ;; Row numbers are 1-indexed 85 | (: row-rs? : Boolean Boolean Boolean Positive-Integer -> Boolean) 86 | (define (row-rs? hand? flat? rs? r) 87 | (or (and (not hand?) rs?) 88 | (and hand? (not flat?) rs?) 89 | (and hand? flat? (boolean-xor rs? (even? r))))) 90 | 91 | ;; Is row knit on WS? 92 | ;; Row numbers are 1-indexed 93 | (: options-row-ws? : Options Positive-Integer -> Boolean) 94 | (define (options-row-ws? self r) 95 | (not (options-row-rs? self r))) 96 | 97 | ;; Is row 1 knit from right to left? 98 | ;; Row numbers are 1-indexed 99 | (: options-row-r2l? : Options Positive-Integer -> Boolean) 100 | (define (options-row-r2l? self r) 101 | (let* ([hand? : Boolean (eq? (Options-technique self) 'hand)] 102 | [flat? : Boolean (eq? (Options-form self) 'flat)] 103 | [right? : Boolean (eq? (Options-side self) 'right)]) 104 | (row-r2l? hand? flat? right? r))) 105 | 106 | ;; Is row 1 knit from right to left? 107 | ;; Row numbers are 1-indexed 108 | (: row-r2l? : Boolean Boolean Boolean Positive-Integer -> Boolean) 109 | (define (row-r2l? hand? flat? right? r) 110 | (or (and (not hand?) right?) 111 | (and hand? (not flat?) right?) 112 | (and hand? flat? (boolean-xor right? (even? r))))) 113 | 114 | ;; Is row knit from left to right? 115 | ;; Row numbers are 1-indexed 116 | (: options-row-l2r? : Options Positive-Integer -> Boolean) 117 | (define (options-row-l2r? self r) 118 | (not (options-row-r2l? self r))) 119 | -------------------------------------------------------------------------------- /knotty-lib/pull-direction.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | 6 | MIT License 7 | 8 | Copyright (c) 2023 Tom Price. 9 | 10 | Incorporating concepts from https://pypi.org/project/knit-script/ 11 | Copyright (c) 2022 Megan Hofmann, Northeastern University Khoury College of 12 | Computer Sciences Accessible Creative Technologies (ACT) Lab and Contributors. 13 | 14 | Permission is hereby granted, free of charge, to any person obtaining a copy 15 | of this software and associated documentation files (the "Software"), to deal 16 | in the Software without restriction, including without limitation the rights 17 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | copies of the Software, and to permit persons to whom the Software is 19 | furnished to do so, subject to the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included in all 22 | copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 26 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 27 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 28 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | |# 31 | 32 | (provide (all-defined-out)) 33 | 34 | (define-type Pull-Direction (U 'BtF 'FtB)) 35 | (define-predicate Pull-Direction? Pull-Direction) 36 | 37 | (: pull-direction-opposite : Pull-Direction -> Pull-Direction) 38 | (define (pull-direction-opposite dir) 39 | (if (eq? 'BtF dir) 40 | 'FtB 41 | 'BtF)) 42 | 43 | ;; end 44 | -------------------------------------------------------------------------------- /knotty-lib/repeats.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (provide (all-defined-out)) 22 | 23 | (require "global.rkt") 24 | 25 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 26 | 27 | ;; Repeats struct definition. 28 | (struct Repeats 29 | ([caston-count : Natural] 30 | [caston-repeat : Natural] 31 | [first-repeat-row : (Option Positive-Integer)] 32 | [last-repeat-row : (Option Positive-Integer)]) 33 | #:transparent) 34 | 35 | ;; Default Repeats. 36 | (define dummy-repeats : Repeats 37 | (Repeats 0 0 #f #f)) 38 | 39 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 40 | 41 | ;; Returns original 0-indexed rownumber from 1-indexed rownumber of expanded pattern. 42 | (: original-row-index : Repeats Positive-Integer Positive-Integer Positive-Integer -> (Option Natural)) 43 | (define (original-row-index repeats nrows v-repeats n) 44 | (let* ([frr (Repeats-first-repeat-row repeats)] 45 | [lrr (Repeats-last-repeat-row repeats)] 46 | [res 47 | (if (or (false? frr) 48 | (false? lrr) 49 | (> frr lrr)) 50 | ;; no vertical repeats 51 | (if (<= n nrows) 52 | n 53 | #f) 54 | ;; vertical repeats 55 | (if (<= n frr) 56 | n 57 | (let* ([repeat-length (- lrr frr -1)] 58 | [lrr~ (+ lrr (* (sub1 v-repeats) repeat-length))]) 59 | (if (<= n lrr~) 60 | (+ (modulo (- n frr) repeat-length) frr) 61 | (if (<= (- n lrr~) (- nrows lrr)) 62 | (+ (- n lrr~) lrr) 63 | #f)))))]) 64 | (if (false? res) 65 | #f 66 | (begin 67 | (assert (positive-integer? res)) 68 | (sub1 res))))) 69 | 70 | ;; end 71 | -------------------------------------------------------------------------------- /knotty-lib/resources/SaxonHE11-5J/lib/jline-2.14.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty-lib/resources/SaxonHE11-5J/lib/jline-2.14.6.jar -------------------------------------------------------------------------------- /knotty-lib/resources/SaxonHE11-5J/lib/xmlresolver-4.6.4-data.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty-lib/resources/SaxonHE11-5J/lib/xmlresolver-4.6.4-data.jar -------------------------------------------------------------------------------- /knotty-lib/resources/SaxonHE11-5J/lib/xmlresolver-4.6.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty-lib/resources/SaxonHE11-5J/lib/xmlresolver-4.6.4.jar -------------------------------------------------------------------------------- /knotty-lib/resources/SaxonHE11-5J/notices/JAMESCLARK.txt: -------------------------------------------------------------------------------- 1 | 2 | (This notice is included in the Saxon distribution because Saxon's XPath parser 3 | was originally derived from an XPath parser written by James Clark and made available 4 | under this license. The Saxon XPath parser has since diverged very substantially, but 5 | there are traces of the original code still present.) 6 | 7 | Copyright (c) 1998, 1999 James Clark 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining 10 | a copy of this software and associated documentation files (the 11 | "Software"), to deal in the Software without restriction, including 12 | without limitation the rights to use, copy, modify, merge, publish, 13 | distribute, sublicense, and/or sell copies of the Software, and to 14 | permit persons to whom the Software is furnished to do so, subject to 15 | the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included 18 | in all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | IN NO EVENT SHALL JAMES CLARK BE LIABLE FOR ANY CLAIM, DAMAGES OR 24 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 25 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | Except as contained in this notice, the name of James Clark shall 29 | not be used in advertising or otherwise to promote the sale, use or 30 | other dealings in this Software without prior written authorization 31 | from James Clark. 32 | -------------------------------------------------------------------------------- /knotty-lib/resources/SaxonHE11-5J/notices/JLINE2.txt: -------------------------------------------------------------------------------- 1 | (This notice is included in the Saxon distribution because the JLine2 2 | library is included, unmodified, in the Saxon distribution. It is used 3 | to support interactive command line editing, autocompletion, and session 4 | history by the Gizmo utility.) 5 | 6 | Copyright (c) 2002-2016, the original author or authors. 7 | All rights reserved. 8 | 9 | http://www.opensource.org/licenses/bsd-license.php 10 | 11 | Redistribution and use in source and binary forms, with or 12 | without modification, are permitted provided that the following 13 | conditions are met: 14 | 15 | Redistributions of source code must retain the above copyright 16 | notice, this list of conditions and the following disclaimer. 17 | 18 | Redistributions in binary form must reproduce the above copyright 19 | notice, this list of conditions and the following disclaimer 20 | in the documentation and/or other materials provided with 21 | the distribution. 22 | 23 | Neither the name of JLine nor the names of its contributors 24 | may be used to endorse or promote products derived from this 25 | software without specific prior written permission. 26 | 27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 29 | BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 30 | AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 31 | EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 32 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 33 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 34 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 36 | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 38 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 39 | OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /knotty-lib/resources/SaxonHE11-5J/saxon-he-11.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty-lib/resources/SaxonHE11-5J/saxon-he-11.5.jar -------------------------------------------------------------------------------- /knotty-lib/resources/SaxonHE11-5J/saxon-he-test-11.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty-lib/resources/SaxonHE11-5J/saxon-he-test-11.5.jar -------------------------------------------------------------------------------- /knotty-lib/resources/SaxonHE11-5J/saxon-he-xqj-11.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty-lib/resources/SaxonHE11-5J/saxon-he-xqj-11.5.jar -------------------------------------------------------------------------------- /knotty-lib/resources/css/knotty-manual.css: -------------------------------------------------------------------------------- 1 | /* Symbol fonts */ 2 | .dash, 3 | .symbol { 4 | font-family: "Stitchmastery Dash"; 5 | font-size: 24px; 6 | } 7 | .purl { 8 | font-family: "Stitchmastery Dash"; 9 | font-size: 24px; 10 | text-decoration: underline solid black 1px; 11 | text-underline-offset: -2px; 12 | } 13 | .dashcable{ 14 | font-family: "Stitchmastery DashCable"; 15 | font-size: 24px; 16 | } 17 | .dashcableEH, 18 | .cable { 19 | font-family: "Stitchmastery DashCableEH"; 20 | font-size: 24px; 21 | } 22 | .dash, 23 | .dashcable, 24 | .dashcableEH, 25 | .purl { 26 | color: black; 27 | border-style: solid; 28 | border-width: 1px; 29 | padding: 2px; 30 | } 31 | 32 | /* Box styles */ 33 | .box, 34 | .shadowbox { 35 | color: black; 36 | border: solid black 1px; 37 | } 38 | .box { 39 | padding: 1em; 40 | } 41 | .shadowbox { 42 | margin-top: 1.5em; 43 | margin-bottom: 1.5em; 44 | box-shadow: 1px 1px 25px 15px #EEEEEE; 45 | padding: 0; 46 | } 47 | table.shadowbox { 48 | margin-left: auto; 49 | margin-right: auto; 50 | padding: 1em; 51 | } 52 | -------------------------------------------------------------------------------- /knotty-lib/resources/css/knotty.css: -------------------------------------------------------------------------------- 1 | /* Text fonts */ 2 | body { 3 | background-color: #F7F7F7; 4 | font-family: Tahoma, Calibri, sans-serif; 5 | } 6 | p:not(.footer), 7 | table.yarn, 8 | ul, 9 | #button { 10 | font-family: Georgia Pro, Georgia, Times, Times New Roman, serif; 11 | } 12 | .details { 13 | font-stretch: condensed; 14 | } 15 | .bold { 16 | font-weight: bold; 17 | } 18 | .italic { 19 | font-style: italic; 20 | } 21 | .footer { 22 | font-size: 0.875em; 23 | } 24 | 25 | /* Cursor */ 26 | select:hover { 27 | cursor: pointer; 28 | } 29 | select[disabled]:hover { 30 | cursor: not-allowed; 31 | } 32 | abbr, 33 | td.symbol:hover { 34 | cursor: help; 35 | } 36 | 37 | /* Links */ 38 | a, 39 | a:visited { 40 | color: #009999; 41 | text-decoration: none; 42 | } 43 | a:active, 44 | a:hover, 45 | a:focus { 46 | color: #007777; 47 | text-decoration: underline; 48 | } 49 | 50 | /* Containers */ 51 | body { 52 | box-sizing: border-box; 53 | } 54 | div, 55 | table { 56 | padding: 0; 57 | margin: 0; 58 | } 59 | table { 60 | border-collapse: separate; 61 | border-spacing: 0; 62 | } 63 | div.container { 64 | width: 95%; 65 | margin-left: 1em; 66 | padding-left: 1em; 67 | padding-right: 1em; 68 | } 69 | div.container, 70 | div.figure, 71 | table.figure { 72 | margin-left: auto; 73 | margin-right: auto; 74 | } 75 | #resizable { 76 | border: solid #DDDDDD 1px; 77 | border-radius: 3px; 78 | overflow: auto; 79 | resize: vertical; 80 | } 81 | div.main { 82 | overflow: hidden; 83 | padding: 1em; 84 | } 85 | div.main, 86 | div.details { 87 | background-color: #FFFFFF; 88 | border: solid #BBBBBB 1px; 89 | border-radius: 5px; 90 | } 91 | div.outside-details { 92 | float: right; 93 | max-width: 20%; 94 | padding-left: 40px; 95 | } 96 | div.details { 97 | padding-left: 0.5em; 98 | padding-right: 0.5em; 99 | padding-bottom: 0.5em; 100 | } 101 | div.title { 102 | /* height: 38.5px; */ 103 | padding-bottom: 10px; 104 | border: none; 105 | } 106 | div.figure { 107 | padding-bottom: 20px; 108 | } 109 | div.form { 110 | margin-top: 0.5em; 111 | } 112 | span.slider { 113 | display: inline-block; 114 | width: 30%; 115 | } 116 | span.repeats, 117 | #float-span { 118 | display: inline-block; 119 | width: 35%; 120 | } 121 | span.slider, 122 | #float-span { 123 | position: relative; 124 | top: -2em; 125 | } 126 | span.lower { 127 | top: 0.75em; 128 | } 129 | #float-span.active { 130 | top: -2px; 131 | } 132 | div.float > * { 133 | margin-top: 0.5em; 134 | } 135 | input#float:focus { 136 | outline: none; 137 | box-shadow: 0px 0px 5px grey; 138 | border: solid grey 1px; 139 | } 140 | input#float:focus:hover { 141 | outline: none; 142 | box-shadow: 0px 0px 5px grey; 143 | border: solid grey 1px; 144 | border-radius: 0; 145 | } 146 | .hidden { 147 | display: none; 148 | } 149 | 150 | /* Heading and list styles */ 151 | h1 { 152 | margin-top: 0; 153 | margin-bottom: 0; 154 | } 155 | h3 { 156 | margin-top: 1em; 157 | margin-bottom: 0.5em; 158 | } 159 | p { 160 | margin-top: 0.5em; 161 | margin-bottom: 0; 162 | } 163 | ul { 164 | list-style: none; 165 | margin-top: 0.5em; 166 | margin-bottom: 0; 167 | padding-left: 0; 168 | } 169 | li { 170 | margin-left: 0; 171 | text-indent: 0; 172 | } 173 | li.notes { 174 | margin-top: 1em; 175 | } 176 | li.rowdata { 177 | margin-top: 0.5em; 178 | } 179 | h1.chart, 180 | h2.chart, 181 | h3.chart, 182 | p.figure { 183 | text-align: center; 184 | } 185 | h3.yarn { 186 | margin-bottom: 0; 187 | } 188 | table.yarn { 189 | border: none; 190 | border-spacing: 0 0.5em; 191 | } 192 | tr.yarn { 193 | height: 1em; 194 | } 195 | td.yarn { 196 | border: none; 197 | padding-left: 0.5em; 198 | } 199 | td.colorblock { 200 | width: 1em; 201 | border: solid black 1px; 202 | } 203 | td.hide { 204 | visibility: hidden; 205 | max-width: 0; 206 | padding: 0; 207 | border: none; 208 | } 209 | p.repeats { 210 | margin-top: 0.5em; 211 | margin-bottom: 0; 212 | } 213 | label { 214 | margin-left: 0.5em; 215 | } 216 | h3.instructions { 217 | margin-top: 0.5em; 218 | } 219 | 220 | /* Chart */ 221 | table.figure { 222 | padding: 0; 223 | border-width: 0; 224 | } 225 | tr.figure { 226 | height: 24px; 227 | } 228 | td.symbol { 229 | padding: 0; 230 | border-style: solid; 231 | border-color: black; 232 | border-top-width: 1px; 233 | border-left-width: 1px; 234 | border-bottom-width: 0; 235 | border-right-width: 0; 236 | width: 24px; 237 | text-align: center; 238 | } 239 | tr.figure:last-child > td { 240 | border-style: solid; 241 | border-color: black; 242 | border-width: 1px 0 0 0; 243 | text-align: center; 244 | } 245 | td.figure:first-child { 246 | width: 4em; 247 | text-align: right; 248 | padding-right: 0.5em; 249 | } 250 | td.figure:last-child { 251 | width: 4em; 252 | text-align: left; 253 | padding-left: 0.5em; 254 | } 255 | tr.figure:last-child > td:first-child, 256 | tr.figure:last-child > td:last-child { 257 | border-width: 0; 258 | } 259 | td.nostitch { 260 | background-color: #EEEEEE; 261 | } 262 | td.nostitch > * { 263 | color: #AAAAAA; 264 | } 265 | td.empty { 266 | border-width: 0; 267 | } 268 | td.blank, 269 | td.empty { 270 | background-color: #FFFFFF; 271 | } 272 | div.strikethrough { 273 | margin-top: 13px; 274 | border: solid red 1px; 275 | background-color: red; 276 | display: block; 277 | height: 5px; 278 | } 279 | span.rownumber { 280 | font-size: 18px; 281 | font-stretch: condensed; 282 | } 283 | abbr.rownumber { 284 | display: block; 285 | text-decoration: none; 286 | position: relative; 287 | top: 4px; 288 | } 289 | span.figure { 290 | display: inline-block; 291 | height: 24px; 292 | width: 100%; 293 | position: relative; 294 | top: -4px; 295 | overflow-x: visible; 296 | overflow-y: visible; 297 | } 298 | span.nostitch { 299 | color: #AAAAAA; 300 | } 301 | span.empty { 302 | color: #FFFFFF; 303 | } 304 | td.borderTop, 305 | td.borderTopLeft, 306 | td.borderLeft { 307 | border-color: black; 308 | border-style: solid; 309 | } 310 | td.borderTop { 311 | border-width: 1px 0 0 0; 312 | } 313 | td.borderLeft { 314 | border-width: 0 0 0 1px; 315 | } 316 | td.borderTopLeft { 317 | border-width: 1px 0 0 1px; 318 | } 319 | 320 | /* Default figure settings */ 321 | #figure { 322 | scale: 1 0.8; 323 | -webkit-transition: 0.4s; 324 | transition: 0.4s; 325 | } 326 | 327 | /* Slider */ 328 | #slider { 329 | -webkit-appearance: none; /* Override default CSS styles */ 330 | appearance: none; 331 | width: 95%; 332 | height: 5px; 333 | background: #CCCCCC; /* Grey background */ 334 | outline: none; 335 | opacity: 0.7; /* Set transparency (for mouse-over effects on hover) */ 336 | -webkit-transition: 0.2s; /* 0.2 seconds transition on hover */ 337 | transition: opacity 0.2s; 338 | } 339 | #slider:hover { 340 | opacity: 1; /* Fully shown on mouse-over */ 341 | } 342 | #slider::-webkit-slider-thumb { 343 | -webkit-appearance: none; /* Override default look */ 344 | appearance: none; 345 | width: 10px; /* Set a specific slider handle width */ 346 | height: 10px; /* Slider handle height */ 347 | background: #009999; /* Blue-Green background */ 348 | cursor: pointer; /* Cursor on hover */ 349 | border-radius: 50%; /* Round boss */ 350 | } 351 | #slider::-moz-range-thumb { 352 | width: 10px; /* Set a specific slider handle width */ 353 | height: 10px; /* Slider handle height */ 354 | background: #009999; /* Blue-Green background */ 355 | cursor: pointer; /* Cursor on hover */ 356 | border-radius: 50%; /* Round boss */ 357 | } 358 | 359 | /* Button */ 360 | #button { 361 | } 362 | -------------------------------------------------------------------------------- /knotty-lib/resources/font/StitchMasteryDash.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty-lib/resources/font/StitchMasteryDash.ttf -------------------------------------------------------------------------------- /knotty-lib/resources/font/georgia.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty-lib/resources/font/georgia.ttf -------------------------------------------------------------------------------- /knotty-lib/resources/icon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty-lib/resources/icon/favicon.ico -------------------------------------------------------------------------------- /knotty-lib/resources/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty-lib/resources/icon/icon.png -------------------------------------------------------------------------------- /knotty-lib/resources/icon/knotty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty-lib/resources/icon/knotty.png -------------------------------------------------------------------------------- /knotty-lib/resources/js/knotty.js: -------------------------------------------------------------------------------- 1 | function toggleVisibility(id) { 2 | var panel = document.getElementById(id); 3 | var check = document.getElementById(id + '_checkbox'); 4 | panel.style.display = (panel.style.display == 'block') ? 'none' : 'block'; 5 | check.checked = (panel.style.display == 'block'); 6 | } 7 | 8 | function zoom() { 9 | var slider = document.getElementById('slider'); 10 | var chart = document.getElementById('figure'); 11 | var x = slider.value; 12 | chart.style.scale = x / 80 + ' ' + x / 100 * aspectRatio; 13 | chart.style.transition = '0.4s'; 14 | } 15 | 16 | function inputFloat() { 17 | var span = document.getElementById('float-span'); 18 | var float = document.getElementById('float'); 19 | var button = document.getElementById('button'); 20 | float.style.display = 'block'; 21 | button.innerHTML = 'Max float length'; 22 | button.disabled = true; 23 | span.classList.add('active'); 24 | } 25 | 26 | function submitForm() { 27 | var div = document.getElementById('resizable'); 28 | var input = document.getElementById('size'); 29 | var form = document.getElementById('form'); 30 | input.value = div.style.height.replace('px', ''); 31 | form.submit(); 32 | } 33 | 34 | onload = (event) => { 35 | zoom(); 36 | } -------------------------------------------------------------------------------- /knotty-lib/rowmap.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (provide (all-defined-out)) 22 | 23 | (require typed/racket) 24 | (require "global.rkt" 25 | "util.rkt" 26 | "stitch.rkt" 27 | "tree.rkt" 28 | "yarn.rkt" 29 | "macros.rkt" 30 | "rows.rkt") 31 | 32 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 33 | 34 | ;; Creates row number index. 35 | (: rowmap-index : (Vectorof (Vectorof Positive-Integer)) -> (Vectorof Natural)) 36 | (define (rowmap-index numbers) 37 | (let* ([n (apply max 38 | (map (λ ([v : (Vectorof Positive-Integer)]) (apply max (vector->list v))) 39 | (vector->list numbers)))] 40 | [index : (Vectorof Natural) (make-vector n)]) 41 | (for ([i : Natural (in-range (vector-length numbers))]) 42 | (let ([v (vector-ref numbers i)]) 43 | (for ([j (in-range (vector-length v))]) 44 | (vector-set! index (sub1 (vector-ref v j)) i)))) 45 | index)) 46 | 47 | ;; Rowmap guard function. 48 | (: rowmap-guard ((Vectorof (Vectorof Positive-Integer)) 49 | (Vectorof Natural) -> 50 | (values (Vectorof (Vectorof Positive-Integer)) 51 | (Vectorof Natural)))) 52 | (define (rowmap-guard numbers index) 53 | (let ([fl : (Listof Positive-Integer) (vector->list (apply vector-append (vector->list numbers)))]) 54 | (when (> (apply min fl) 1) 55 | (err SAFE "row numbers must start at 1")) 56 | (when (and 57 | (not (equal? fl '(1))) 58 | (not (equal? (uniq (diff - (sort fl <))) '(1)))) 59 | (begin 60 | (err SAFE "pattern must specify consecutive row numbers"))) 61 | (values numbers (rowmap-index numbers)))) 62 | 63 | ;; Rowmap struct definition. 64 | (struct Rowmap 65 | ([numbers : (Vectorof (Vectorof Positive-Integer))] ;; vectors of row numbers sorted by lowest number 66 | [index : (Vectorof Natural)]) ;; maps from row numbers to rowspec index 67 | #:guard 68 | (λ (numbers index type-name) 69 | (dlog "in `Rowmap` struct guard function") 70 | (rowmap-guard numbers index)) 71 | #:transparent) 72 | 73 | ;; Dummy Rowmap. 74 | (define dummy-rowmap 75 | (Rowmap 76 | '#(#(1)) 77 | '#(1))) 78 | 79 | ;; Alternative constructor. 80 | (: make-rowmap : (Vectorof (Vectorof Positive-Integer)) -> Rowmap) 81 | (define (make-rowmap numbers) 82 | (Rowmap numbers '#())) 83 | 84 | ;; Rowmap functions 85 | 86 | ;; Finds 1-indexed row number as rowmap index. 87 | (: rowmap-find : Rowmap Positive-Integer -> Natural) 88 | (define (rowmap-find self r) 89 | (vector-ref (Rowmap-index self) (sub1 r))) 90 | 91 | ;; Finds 0-indexed row number as rowmap index. 92 | (: rowmap-find0 : Rowmap Natural -> Natural) 93 | (define (rowmap-find0 self r) 94 | (vector-ref (Rowmap-index self) r)) 95 | 96 | ;; Finds indices that map to both odd and even row numbers. 97 | (: rowmap-odd&even : Rowmap -> (Listof Natural)) 98 | (define (rowmap-odd&even self) 99 | (let loop ([i : Natural (vector-length (Rowmap-numbers self))] 100 | [acc : (Listof Natural) null]) 101 | (if (zero? i) 102 | acc 103 | (let* ([j (sub1 i)] 104 | [rownums-j (vector-ref (Rowmap-numbers self) j)]) 105 | (assert (natural? j)) 106 | (if (and (for/or ([x (in-vector (vector-map odd? rownums-j))]) : Boolean x) 107 | (for/or ([x (in-vector (vector-map even? rownums-j))]) : Boolean x)) 108 | (loop j (cons j acc)) 109 | (loop j acc)))))) 110 | 111 | ;; Finds lowest row number matching index. 112 | (: rowmap-first : Rowmap Natural -> Positive-Integer) 113 | (define (rowmap-first self i) 114 | (apply min 115 | (vector->list 116 | (vector-ref 117 | (Rowmap-numbers self) i)))) 118 | 119 | ;; end 120 | -------------------------------------------------------------------------------- /knotty-lib/rows.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (provide (all-defined-out)) 22 | 23 | (require typed/racket) 24 | (require "global.rkt" 25 | "util.rkt" 26 | "stitch.rkt" 27 | "tree.rkt" 28 | "yarn.rkt" 29 | "macros.rkt" 30 | "rowspec.rkt") 31 | 32 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 33 | 34 | ;; Rows struct. 35 | (struct Rows 36 | ([rownums : (Listof Positive-Integer)] 37 | [rowspec : Rowspec]) 38 | #:guard 39 | (λ (rownums rowspec type-name) 40 | (dlog "in `Rows` struct guard function") 41 | (rows-guard-rownums rownums rowspec)) 42 | #:transparent) 43 | 44 | ;; Composable function to guard `Rows` struct. 45 | (: rows-guard-rownums ((Listof Positive-Integer) 46 | Rowspec 47 | -> (values (Listof Positive-Integer) 48 | Rowspec))) 49 | (define (rows-guard-rownums rownums rowspec) 50 | ;; check valid row numbers exist 51 | (let ([rownums~ (sort (uniq rownums) <)]) 52 | (when (zero? (length rownums~)) 53 | (err SAFE "no row numbers specified")) 54 | (values rownums~ 55 | rowspec))) 56 | 57 | ;; Rownums type. 58 | (define-type Rownums-input (Listof (U Positive-Integer Rownums-input))) 59 | 60 | ;; Alternative constructor. 61 | (: rows (->* () (#:memo String 62 | #:yarn (Option Symbol)) 63 | #:rest (U Positive-Integer Rownums-input) ;; Everything else is a row number 64 | ((U Leaf Node Treelike) (U Leaf Node Treelike) * -> Rows))) 65 | (define ((rows #:memo [memo ""] 66 | #:yarn [y-symbol 'mc] ;; MC is the default yarn 67 | . rownums) . xs) 68 | (log-message knotty-logger 'debug "in `rows` constructor" #f) 69 | ;; convert yarn symbol to number 70 | (let ([y : Byte 71 | (if (false? y-symbol) 72 | 0 73 | (if (eq? 'mc y-symbol) 74 | 0 75 | (let* ([y-str (symbol->string y-symbol)] 76 | [y~ : (Option Byte) 77 | (if (not (string=? "cc" (substring y-str 0 2))) 78 | #f 79 | (let ([y-num (string->number (substring y-str 2))]) 80 | (if (or (false? y-num) 81 | (not (real? y-num)) 82 | (not (positive? y-num))) 83 | #f 84 | (bitwise-and #xFF (exact-floor y-num)))))]) ;; :: Byte 85 | (if (false? y~) 86 | (begin 87 | (err SAFE (format "cannot parse yarn symbol ~a" y-symbol)) 88 | 0) 89 | y~))))] 90 | ;; flatten rownums, not concerned about order 91 | [rownumbers : (Listof Positive-Integer) 92 | (let flatten-rownums ([rs : Rownums-input rownums] 93 | [acc : (Listof Positive-Integer) null]) 94 | (foldl (λ ([r : (U Positive-Integer Rownums-input)] 95 | [acc : (Listof Positive-Integer)]) 96 | (if (number? r) 97 | (cons r acc) 98 | (append (flatten-rownums r null) acc))) 99 | null 100 | rs))]) 101 | (Rows 102 | rownumbers 103 | (Rowspec 104 | ((with-yarn y) xs) 105 | memo 106 | y 107 | (seteq 0) 108 | 'no-turn)))) 109 | 110 | ;; Aliases 111 | (define row rows) 112 | (define rounds rows) 113 | 114 | (: consecutive-rows : (Listof Positive-Integer) -> Boolean) 115 | (define (consecutive-rows rownums) 116 | (and 117 | (> (length rownums) 1) 118 | (= 1 (apply min (diff - rownums))))) 119 | 120 | ;; Defines sequences of row numbers. 121 | (: sequence (->* (Positive-Integer) (Positive-Integer Positive-Integer) (Listof Positive-Integer))) 122 | (define sequence 123 | (case-lambda 124 | [([x : Positive-Integer]) (pos-range 1 (add1 x) 1)] 125 | [([x : Positive-Integer] 126 | [y : Positive-Integer]) (pos-range x (add1 y) 1)] 127 | [([x : Positive-Integer] 128 | [y : Positive-Integer] 129 | [z : Positive-Integer]) (pos-range x (add1 y) z)] 130 | [else (error "Error in defining sequence")])) 131 | 132 | ;; Alias 133 | (define seq sequence) 134 | 135 | ;; end 136 | -------------------------------------------------------------------------------- /knotty-lib/serv.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | 3 | (provide serve-pattern) 4 | (require web-server/servlet 5 | web-server/servlet-env 6 | web-server/formlets) 7 | (require "global.rkt" 8 | "util.rkt" 9 | "pattern.rkt" 10 | "html.rkt") 11 | 12 | ;; Serves HTML from Pattern. 13 | (define (serve-pattern p [h-repeats 1] [v-repeats 1] [static? #f]) 14 | (let* ([nohreps? (pattern-nohreps? p)] 15 | [novreps? (pattern-novreps? p)] 16 | ;; form defaults 17 | [inputs 18 | (make-hasheq 19 | `((stat . ,(bool->int static?)) 20 | (hreps . ,(if nohreps? 0 h-repeats)) 21 | (vreps . ,(if novreps? 0 v-repeats)) 22 | (zoom . 80) 23 | (float . 0) 24 | (notes . 0) 25 | (yarn . 0) 26 | (instr . 0) 27 | (size . 0)))] 28 | ;; formlet 29 | [form (combined-formlet inputs)]) 30 | 31 | ;; define webapp 32 | (define (render request) 33 | 34 | ;; extract form values from POST request 35 | (let* ([vals (formlet-process form request)] 36 | [h (first (first vals))] 37 | [v (first (second vals))] 38 | [z (first (third vals))] 39 | [f (first (fourth vals))] 40 | [n (first (fifth vals))] 41 | [y (first (sixth vals))] 42 | [i (first (seventh vals))] 43 | [s (first (eighth vals))]) 44 | 45 | ;; update inputs 46 | (unless (or nohreps? (false? h)) 47 | (hash-set! inputs 'hreps h)) 48 | (unless (or novreps? (false? v)) 49 | (hash-set! inputs 'vreps v)) 50 | (unless (false? z) 51 | (hash-set! inputs 'zoom z)) 52 | (hash-set! inputs 'float f) 53 | (hash-set! inputs 'notes (bool->int n)) 54 | (hash-set! inputs 'yarn (bool->int y)) 55 | (hash-set! inputs 'instr (bool->int i)) 56 | (hash-set! inputs 'size s) 57 | 58 | ;; generate response 59 | (define (response-generator dummy-url) 60 | (response/output 61 | (λ (op) 62 | (pattern-template op p inputs)))) 63 | 64 | ;; dispatch 65 | (send/suspend response-generator))) 66 | 67 | ;; start webserver 68 | (serve/servlet render 69 | #:extra-files-paths (list resources-path) ;; for CSS file etc. 70 | #:servlet-path "/knotty") 71 | 72 | (void))) 73 | 74 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 75 | 76 | ;; demo 77 | ;(serve-pattern demo 2 2) 78 | ;(serve-pattern owl 1 1) 79 | ;(serve-pattern sawtooth 1 1) 80 | 81 | 82 | -------------------------------------------------------------------------------- /knotty-lib/text.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (provide (all-defined-out)) 22 | (require/typed sxml 23 | [sxml:modify ((Listof (U String Symbol (Sexp Any Sexp -> (U Sexp (Listof Sexp))) Sexp)) -> (Sexp -> Sexp))]) 24 | (require/typed html-parsing 25 | [html->xexp (String -> Sexp)]) 26 | (require/typed html-writing 27 | [xexp->html (Sexp -> String)]) 28 | (require "util.rkt" 29 | "pattern.rkt") 30 | (require/typed "html.rkt" 31 | [pattern-template (->* (Output-Port Pattern (HashTable Symbol Integer)) (Boolean) Void)]) 32 | 33 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 34 | 35 | ;; Displays pattern as written knitting instructions. 36 | (: text : Pattern -> Void) 37 | (define (text p) 38 | (display (pattern->text p))) 39 | 40 | ;; Formats pattern for text output. 41 | (: pattern->text : Pattern -> String) 42 | (define (pattern->text p) 43 | (transform-pattern-text 44 | (let ([s (open-output-string)] 45 | [i (make-hasheq 46 | '((hreps . 1) 47 | (vreps . 1) 48 | (zoom . 1) 49 | (float . 0) 50 | (notes . 0) 51 | (yarn . 0) 52 | (instr . 0) 53 | (size . 0)))]) 54 | (pattern-template s p i #t) 55 | (get-output-string s)))) 56 | 57 | ;; first convert HTML template back to SXML 58 | ;; then use XSLT to convert SXML 59 | ;; and transform back to text 60 | (: transform-pattern-text : String -> String) 61 | (define (transform-pattern-text s) 62 | (regexp-replace 63 | #px"^\n" 64 | (remove-tags 65 | (xexp->html 66 | ((sxml:modify '("//tr" insert-following "\n")) 67 | ((sxml:modify '("//td//text()[normalize-space()]" insert-following " ")) 68 | ((sxml:modify '("//tr/td[2]" insert-following "- ")) 69 | ((sxml:modify '("//div[not(normalize-space())]" delete)) 70 | ((sxml:modify '("//li" insert-following "\n")) 71 | ((sxml:modify '("//p" insert-following "\n")) 72 | ((sxml:modify '("//h3/text()[1]" insert-preceding "\n")) 73 | ((sxml:modify '("//h3/text()" insert-following ":\n")) 74 | ((sxml:modify '("//h1/text()" insert-following "\n")) 75 | ((sxml:modify '("//a" delete-undeep)) 76 | ((sxml:modify '("//div[contains(@class, 'footer')]" delete)) 77 | ((sxml:modify '("//div[contains(@class, 'form')]" delete)) 78 | ((sxml:modify '("//div[contains(@class, 'figure')]" delete)) 79 | ((sxml:modify '("/script" delete)) 80 | ((sxml:modify '("/body" delete-undeep)) 81 | ((sxml:modify '("/head" delete)) 82 | ((sxml:modify '("/html" delete-undeep)) 83 | (html->xexp s)))))))))))))))))))) 84 | "")) 85 | 86 | ;; end 87 | -------------------------------------------------------------------------------- /knotty-lib/yarn.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (provide (all-defined-out)) 22 | 23 | (require "global.rkt" 24 | "stitch.rkt" 25 | "tree.rkt") 26 | 27 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 28 | 29 | ;; Yarn struct definition. 30 | (struct Yarn 31 | ([color : Nonnegative-Fixnum] ;; RGB 32 | [name : String] 33 | [weight : (Option Byte)] ;; CYC category https://www.craftyarncouncil.com/standards/yarn-weight-system 34 | [fiber : String] 35 | [brand : String]) 36 | #:guard 37 | (λ (color name weight fiber brand type-name) 38 | (dlog "in `Yarn` struct guard function") 39 | ;; NB composed functions are applied in reverse order 40 | ((compose yarn-guard-weight 41 | yarn-guard-color) 42 | color name weight fiber brand)) 43 | #:transparent) 44 | 45 | (: yarn-guard-weight (Nonnegative-Fixnum 46 | String 47 | (Option Byte) 48 | String 49 | String -> 50 | (values Nonnegative-Fixnum 51 | String 52 | (Option Byte) 53 | String 54 | String))) 55 | (define (yarn-guard-weight color name weight fiber brand) 56 | (when (and (not (false? weight)) 57 | (> weight 7)) 58 | (err SAFE "yarn weight must be a number between 0 and 7, or #f")) 59 | (values color name weight fiber brand)) 60 | 61 | (: yarn-guard-color (Nonnegative-Fixnum 62 | String 63 | (Option Byte) 64 | String 65 | String -> 66 | (values Nonnegative-Fixnum 67 | String 68 | (Option Byte) 69 | String 70 | String))) 71 | (define (yarn-guard-color color name weight fiber brand) 72 | (when (or (negative? color) 73 | (> color #xFFFFFF)) 74 | (err SAFE "yarn color must be a number between 0 and #xFFFFFF")) 75 | (values color name weight fiber brand)) 76 | 77 | 78 | ;; Yarns type definition. 79 | (define-type Yarns 80 | (Vectorof Yarn)) 81 | 82 | 83 | ;; Alternative constructor. 84 | (: yarn (->* (Nonnegative-Fixnum) (String (Option Byte) String String) Yarn)) 85 | (define (yarn color 86 | [name ""] 87 | [weight #f] 88 | [fiber ""] 89 | [brand ""]) 90 | (Yarn color name weight fiber brand)) 91 | 92 | ;; default Yarn 93 | (define default-yarn-color #xFFFFFF) 94 | (define default-yarn-color-name "White") 95 | (define default-yarn : Yarn 96 | (yarn default-yarn-color 97 | default-yarn-color-name)) 98 | 99 | ;; Alternative constructor. 100 | (: yarns : Yarn * -> Yarns) 101 | (define (yarns . ys) 102 | ((inst list->vector Yarn) ys)) 103 | 104 | ;; default Yarns 105 | (define default-yarns : Yarns 106 | (yarns default-yarn)) 107 | 108 | 109 | ;; Yarn functions 110 | 111 | (: with-yarn : (Option Byte) -> ((U Leaf Node Treelike) (U Leaf Node Treelike) * -> Tree)) 112 | (define ((with-yarn n) . xs) 113 | (yarn-recurse n (treelike->tree xs))) 114 | 115 | (: yarn-recurse : (Option Byte) Tree -> Tree) 116 | (define (yarn-recurse n xs) 117 | (foldl (λ ([x : (U Leaf Node)] 118 | [acc : Tree]) 119 | (if (Leaf? x) 120 | ;; leaf 121 | (if (or (false? n) 122 | (false? (leaf-yarn x))) 123 | (cons (make-leaf (leaf-count x) (Stitch (leaf-symbol x) n)) 124 | acc) 125 | (cons x acc)) 126 | ;; node 127 | (cons (make-node (node-count x) (reverse (yarn-recurse n (node-tree x)))) 128 | acc))) 129 | null 130 | xs)) 131 | 132 | (: yarn-id : ((Option Byte) -> String)) 133 | (define (yarn-id y) 134 | (if (false? y) 135 | "" 136 | (if (zero? y) 137 | "MC" 138 | (format "CC~a" y)))) 139 | 140 | (: inyarn : ((Option Byte) -> String)) 141 | (define (inyarn y) 142 | (if (false? y) 143 | "" 144 | (string-append "in " (yarn-id y)))) 145 | 146 | ;; end 147 | -------------------------------------------------------------------------------- /knotty/info.rkt: -------------------------------------------------------------------------------- 1 | #lang info 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (define collection 22 | 'multi) 23 | 24 | (define version 25 | "0.1") 26 | 27 | (define pkg-desc 28 | "A domain-specific language for knitting patterns") 29 | 30 | (define deps 31 | '("base" 32 | "knotty-lib" 33 | "typed/racket" 34 | "typed-racket-lib" 35 | "typed-racket-more" 36 | "typed/rackunit" 37 | "named-arguments" 38 | "sxml" 39 | "scribble-lib" 40 | "draw-lib" 41 | "mock" 42 | "mock-rackunit")) 43 | 44 | (define build-deps 45 | '("lazy" 46 | "rackunit-typed" 47 | "sweet-exp-lib" 48 | "threading-lib" 49 | "web-server-lib")) 50 | 51 | (define implies 52 | '("knotty-lib")) 53 | 54 | (define scribblings 55 | '(("knotty/scribblings/knotty.scrbl"))) 56 | 57 | (define license 58 | 'LGPL-3.0-or-later) 59 | 60 | (define pkg-authors 61 | '(Tom Price)) 62 | -------------------------------------------------------------------------------- /knotty/scribblings/cable-lattice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/cable-lattice.png -------------------------------------------------------------------------------- /knotty/scribblings/check-float.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/check-float.png -------------------------------------------------------------------------------- /knotty/scribblings/check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/check.png -------------------------------------------------------------------------------- /knotty/scribblings/chessboard-squashed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/chessboard-squashed.png -------------------------------------------------------------------------------- /knotty/scribblings/chessboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/chessboard.png -------------------------------------------------------------------------------- /knotty/scribblings/danny-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/danny-screenshot.png -------------------------------------------------------------------------------- /knotty/scribblings/danny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/danny.png -------------------------------------------------------------------------------- /knotty/scribblings/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/demo.png -------------------------------------------------------------------------------- /knotty/scribblings/example/lattice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/example/lattice.png -------------------------------------------------------------------------------- /knotty/scribblings/fishtail-lace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/fishtail-lace.png -------------------------------------------------------------------------------- /knotty/scribblings/garter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/garter.png -------------------------------------------------------------------------------- /knotty/scribblings/houndstooth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/houndstooth.png -------------------------------------------------------------------------------- /knotty/scribblings/knotty-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/knotty-screenshot.png -------------------------------------------------------------------------------- /knotty/scribblings/knotty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/knotty.png -------------------------------------------------------------------------------- /knotty/scribblings/knotty.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @(require (for-label 4 | racket/base 5 | (except-in knotty #%app define lambda))) 6 | @(require scribble/core 7 | scribble/html-properties) 8 | 9 | @; Style comment: 10 | @; Knotty is capitalized except for file names and code fragments. 11 | 12 | @; to build locally from main directory: 13 | @; scribble +m --redirect-main http://docs.racket-lang.org/ --dest manual scribblings/knotty.scrbl 14 | 15 | @(define gnitty-style 16 | (make-style #f (list (hover-property "Hello! My name is Gnitty. I like knots!")))) 17 | 18 | 19 | @title{Knotty} 20 | @author[@author+email["Tom Price" "t0mpr1c3@gmail.com"]] 21 | @defmodule[knotty] 22 | 23 | @centered[@element[gnitty-style @image{knotty/scribblings/knotty.png}]] 24 | 25 | A domain-specific language for knitting patterns. 26 | 27 | 28 | @section[#:tag "intro"]{Introduction} 29 | 30 | Knotty is a domain-specific language for knitting patterns. 31 | 32 | It's written as a @emph{module}, or add-on, for a programming language called 33 | @hyperlink{https://docs.racket-lang.org/guide/index.html 34 | Racket}. This gives you complete flexibility in how you write and parameterize 35 | your designs. 36 | 37 | There is also a Knotty executable that converts knitting programs from one 38 | format to another. 39 | 40 | @subsection[#:tag "aim"]{Why Knotty?} 41 | 42 | Knotty aims to be a @emph{useful} open-source standard to describe knitting 43 | patterns. Knotty is easy to read, easy to write, provides a practical set 44 | of tools for designers. 45 | 46 | That said, it is still under development so please bear with me if you need a 47 | particular feature that doesn't exist yet! 48 | 49 | @subsection[#:tag "getting started"]{Getting Started} 50 | 51 | @subsubsection[#:tag "installation"]{Installation} 52 | 53 | Download and install the lastest version of Racket from the homepage. The 54 | installation will include an application called @racket[DrRacket]. DrRacket is 55 | recommended as the best way to edit and run programs in Racket. 56 | 57 | In DrRacket, open the menu option @emph{File > Install Package}. Type 58 | @emph{knotty} into the text box and press @emph{Install}. 59 | 60 | @subsubsection[#:tag "usage"]{Using Knotty} 61 | 62 | To begin with, it is recommended to use Knotty from within DrRacket. 63 | But there is also a @secref{app} that you can run from the command line. 64 | 65 | @subsection[#:tag "resources"]{Resources} 66 | 67 | @subsubsection[#:tag "manual"]{Manual} 68 | 69 | This document is intended to be read by people who are learning to use 70 | Knotty. It contains @secref{reference} materials and @secref{code} that 71 | highlight some of the features implemented in Knotty. 72 | 73 | @subsubsection[#:tag "repo"]{Repository} 74 | 75 | Try looking in the @hyperlink{https://github.com/t0mpr1c3/knotty 76 | Knotty repository} for more example files and documentation. 77 | 78 | 79 | @; included sections 80 | 81 | @include-section{demo.scrbl} 82 | 83 | @include-section{io.scrbl} 84 | 85 | @include-section{code.scrbl} 86 | 87 | @include-section{ref.scrbl} 88 | 89 | -------------------------------------------------------------------------------- /knotty/scribblings/lancellin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/lancellin.png -------------------------------------------------------------------------------- /knotty/scribblings/little-leaf-stripe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/little-leaf-stripe.png -------------------------------------------------------------------------------- /knotty/scribblings/mario-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/mario-screenshot.png -------------------------------------------------------------------------------- /knotty/scribblings/mario.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/mario.png -------------------------------------------------------------------------------- /knotty/scribblings/megaman-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/megaman-screenshot.png -------------------------------------------------------------------------------- /knotty/scribblings/megaman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/megaman.png -------------------------------------------------------------------------------- /knotty/scribblings/owl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/owl.png -------------------------------------------------------------------------------- /knotty/scribblings/pretzel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/pretzel.png -------------------------------------------------------------------------------- /knotty/scribblings/racket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/racket.png -------------------------------------------------------------------------------- /knotty/scribblings/sawtooth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/sawtooth.png -------------------------------------------------------------------------------- /knotty/scribblings/short-rows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/short-rows.png -------------------------------------------------------------------------------- /knotty/scribblings/star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/star.png -------------------------------------------------------------------------------- /knotty/scribblings/triangle-top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/triangle-top.png -------------------------------------------------------------------------------- /knotty/scribblings/tv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t0mpr1c3/knotty/788926a273a69a77760a189d0ca34ad4b5423a88/knotty/scribblings/tv.png -------------------------------------------------------------------------------- /knotty/tests/chart-row.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (module+ test 22 | (require typed/rackunit 23 | threading 24 | racket/vector) ; needed for `vector-map` 25 | (require "../../knotty-lib/stitch.rkt" 26 | "../../knotty-lib/yarn.rkt" 27 | "../../knotty-lib/chart-row.rkt") 28 | 29 | (define cr1 30 | (Chart-row 31 | '#(#s(Stitch k #f) 32 | #s(Stitch p 1) 33 | #s(Stitch yo 2)) 34 | 0 #f #f #f 0 0)) 35 | 36 | (check-equal? 37 | (chart-row-set-stitches 38 | cr1 39 | '#(#s(Stitch p 1))) 40 | (Chart-row 41 | '#(#s(Stitch p 1)) 42 | 0 #f #f #f 0 0)) 43 | 44 | (check-equal? 45 | (chart-row-width cr1) 46 | 3) 47 | 48 | (check-equal? 49 | (chart-row-colors cr1) 50 | #"\0\1\2") 51 | 52 | (check-equal? 53 | (chart-row-stitchtypes cr1) 54 | '(k p yo)) 55 | 56 | ) 57 | ;; end 58 | 59 | 60 | -------------------------------------------------------------------------------- /knotty/tests/colors.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (module+ test 22 | (require typed/rackunit 23 | racket/fixnum 24 | threading) 25 | (require "../../knotty-lib/util.rkt" 26 | "../../knotty-lib/colors.rkt") 27 | 28 | ;; tests of color functions 29 | (check-equal? 30 | (vector-length named-colors) 31 | #x1000) 32 | 33 | (check-equal? 34 | (bitcrunch #x08) 35 | #x00) 36 | 37 | (check-equal? 38 | (bitcrunch #x09) 39 | #x01) 40 | 41 | (check-equal? 42 | (bitcrunch #xF6) 43 | #x0E) 44 | 45 | (check-equal? 46 | (bitcrunch #xF7) 47 | #x0F) 48 | 49 | (check-equal? 50 | (rgb->name #xBEEFED) 51 | "Pale Turquoise") 52 | 53 | (check-equal? 54 | (rgb->name #xFEDBAD) 55 | "Navajo White") 56 | 57 | ;; number too big 58 | (check-equal? 59 | (get-color #x1000000) 60 | "") 61 | 62 | ) 63 | ;; end 64 | -------------------------------------------------------------------------------- /knotty/tests/course.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (require "../../knotty-lib/loop.rkt" 22 | "../../knotty-lib/course.rkt") 23 | 24 | (module+ test 25 | (require typed/rackunit) 26 | 27 | (define course0 28 | (course-add-loop (make-course) #s(Loop 0 (0) 0 #f ()))) 29 | (define course1 30 | (course-add-loop course0 #s(Loop 1 (0) 0 #f ()) 0)) 31 | 32 | (check-exn 33 | exn:fail? 34 | (λ () 35 | (course-add-loop course0 #s(Loop 1 (0) 0 #f (0))))) 36 | 37 | (check-equal? 38 | (Course-loop-ids course1) 39 | '(1 0)) 40 | 41 | (check-equal? 42 | (course-ref course1 0) 43 | 1) 44 | 45 | (check-equal? 46 | (course-index course1 1) 47 | 0) 48 | 49 | (check-equal? 50 | (course-has-loop? course0 1) 51 | #f) 52 | (check-equal? 53 | (course-has-loop? course1 1) 54 | #t) 55 | 56 | (check-equal? 57 | (course-length course1) 58 | 2) 59 | 60 | ;; end of submodule 61 | ) 62 | 63 | ;; end -------------------------------------------------------------------------------- /knotty/tests/diophantine.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (require "../../knotty-lib/global.rkt" 22 | "../../knotty-lib/diophantine.rkt") 23 | 24 | (module+ test 25 | (require typed/rackunit) 26 | (define-syntax check-values-equal? 27 | (syntax-rules () 28 | [(_ a b) (check-equal? (call-with-values (thunk a) list) 29 | b)])) 30 | 31 | ;; b = d 32 | (check-values-equal? 33 | (diophantine 0 0 0 0) 34 | '(0 0)) 35 | 36 | (check-values-equal? 37 | (diophantine 2 2 2 2) 38 | '(0 0)) 39 | 40 | ;; f = 0 41 | (check-values-equal? 42 | (diophantine 0 0 0 1) 43 | '(#f #f)) 44 | 45 | (check-values-equal? 46 | (diophantine 1 1 0 0) 47 | '(#f #f)) 48 | 49 | (check-values-equal? 50 | (diophantine 0 0 1 1) 51 | '(#f #f)) 52 | 53 | (check-values-equal? 54 | (diophantine 1 0 0 1) 55 | '(1 0)) 56 | 57 | (check-values-equal? 58 | (diophantine 0 1 1 0) 59 | '(0 1)) 60 | 61 | (check-values-equal? 62 | (diophantine 0 1 2 0) 63 | '(#f #f)) 64 | 65 | (check-values-equal? 66 | (diophantine 2 0 0 1) 67 | '(#f #f)) 68 | 69 | ;; e = f = 1 70 | (check-values-equal? 71 | (diophantine 1 0 1 1) 72 | '(1 0)) 73 | 74 | (check-values-equal? 75 | (diophantine 1 1 1 0) 76 | '(0 1)) 77 | 78 | ;; f = 1 79 | (check-values-equal? 80 | (diophantine 3 0 1 1) 81 | '(1 2)) 82 | 83 | (check-values-equal? 84 | (diophantine 1 1 3 0) 85 | '(2 1)) 86 | 87 | (check-values-equal? 88 | (diophantine 3 0 1 2) 89 | '(1 1)) 90 | 91 | (check-values-equal? 92 | (diophantine 1 2 3 0) 93 | '(1 1)) 94 | 95 | (check-values-equal? 96 | (diophantine 6 3 3 0) 97 | '(0 1)) 98 | 99 | (check-values-equal? 100 | (diophantine 9 0 3 3) 101 | '(1 2)) 102 | 103 | ;; general 104 | (check-values-equal? 105 | (diophantine 2 0 4 1) 106 | '(#f #f)) 107 | 108 | (check-values-equal? 109 | (diophantine 2 0 3 1) 110 | '(2 1)) 111 | 112 | ;; example from https://www.wikihow.com/Solve-a-Linear-Diophantine-Equation 113 | (check-values-equal? 114 | (diophantine 87 0 64 3) 115 | '(53 72)) 116 | ) 117 | ;; end 118 | -------------------------------------------------------------------------------- /knotty/tests/garn.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (require "../../knotty-lib/loop.rkt" 22 | "../../knotty-lib/garn.rkt" 23 | "../../knotty-lib/knitgraph.rkt") 24 | 25 | (module+ test 26 | (require typed/rackunit) 27 | 28 | (define kg (make-knitgraph)) 29 | (define y0 (make-yarn 0)) 30 | (knitgraph-add-yarn! kg y0) 31 | (define loop0 32 | (knitgraph-add-loop-to-end! kg y0)) 33 | 34 | (check-equal? 35 | (hash-keys (Knitgraph-yarns kg)) 36 | '(0)) 37 | 38 | (check-equal? 39 | (Garn-id y0) 40 | 0) 41 | 42 | (check-equal? 43 | (Garn-loops y0) 44 | '(0)) 45 | 46 | (check-equal? 47 | (Garn-last-loop-id y0) 48 | 0) 49 | 50 | (check-equal? 51 | (yarn-length y0) 52 | 1) 53 | 54 | (check-equal? 55 | (yarn-has-loop? y0 loop0) 56 | #t) 57 | (check-equal? 58 | (yarn-has-loop? y0 1) 59 | #f) 60 | 61 | (check-equal? 62 | (Garn-id 63 | (yarn-cut y0)) 64 | #x100) 65 | 66 | ;; remove loop 67 | (yarn-remove-loop! y0 loop0) 68 | (check-equal? 69 | (Garn-loops y0) 70 | null) 71 | (check-equal? 72 | (Garn-last-loop-id y0) 73 | #f) 74 | 75 | ;; end of submodule 76 | ) 77 | 78 | ;; end 79 | -------------------------------------------------------------------------------- /knotty/tests/gauge.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (module+ test 22 | (require typed/rackunit) 23 | (require "../../knotty-lib/gauge.rkt") 24 | 25 | ;; tests of gauge functions 26 | (check-equal? 27 | (gauge-unit 28 | (Gauge 5 1 6 1 'inch)) 29 | "\"") 30 | 31 | (check-equal? 32 | (gauge-unit 33 | (Gauge 12 10 15 10 'cm)) 34 | " cm") 35 | 36 | (check-equal? 37 | (gauge->aspect-ratio 38 | #f) 39 | 0.8) 40 | 41 | (check-equal? 42 | (gauge->aspect-ratio 43 | (Gauge 5 1 5 1 'inch)) 44 | 1.0) 45 | 46 | (check-equal? 47 | (gauge->aspect-ratio 48 | (Gauge 5 1 4 1 'inch)) 49 | 1.25) 50 | 51 | ) 52 | ;; end 53 | -------------------------------------------------------------------------------- /knotty/tests/knitgraph.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | (require "../../knotty-lib/pull-direction.rkt" 4 | "../../knotty-lib/loop.rkt" 5 | "../../knotty-lib/garn.rkt" 6 | "../../knotty-lib/course.rkt" 7 | "../../knotty-lib/knitgraph.rkt" 8 | "simple-knitgraphs.rkt") 9 | 10 | (module+ test 11 | (require typed/rackunit) 12 | 13 | (define kg (make-knitgraph)) 14 | (define y0 (make-yarn 0)) 15 | (define y1 (make-yarn 1)) 16 | (knitgraph-add-yarn! kg y0) 17 | (knitgraph-add-yarn! kg y1) 18 | (define loop0 19 | (knitgraph-add-loop-to-end! kg (list y0 y1))) 20 | (define loop1 21 | (knitgraph-insert-loop! kg y0 0 #f)) 22 | 23 | (check-equal? 24 | loop0 25 | #s(Loop 0 (0 1) 0 #f ())) 26 | (check-equal? 27 | loop1 28 | #s(Loop 1 (0) 0 #f ())) 29 | 30 | ;; invalid options 31 | (check-exn 32 | exn:fail? 33 | (λ () 34 | (knitgraph-insert-loop! kg (list y0 y1) 0 #t))) 35 | (check-exn 36 | exn:fail? 37 | (λ () 38 | (knitgraph-insert-loop! kg (list y0 y1) #f #t loop0))) 39 | (check-exn 40 | exn:fail? 41 | (λ () 42 | (knitgraph-insert-loop! kg (list y0 y1) #f #t #f 0))) 43 | (check-exn 44 | exn:fail? 45 | (λ () 46 | (knitgraph-insert-loop! kg y1 1 #t))) 47 | 48 | (check-equal? 49 | (knitgraph-has-yarn? kg y0) 50 | #t) 51 | (check-equal? 52 | (knitgraph-has-yarn? kg 0) 53 | #t) 54 | 55 | (define y2 (make-yarn 2)) 56 | (check-equal? 57 | (knitgraph-has-yarn? kg 2) 58 | #f) 59 | (check-exn 60 | exn:fail? 61 | (λ () 62 | (knitgraph-add-loop-to-end! kg y2))) 63 | 64 | (check-equal? 65 | (list->set 66 | (hash-keys (Knitgraph-loops kg))) 67 | (set 0 1)) 68 | (check-equal? 69 | (hash-values (Knitgraph-loops kg)) 70 | (list loop0 loop1)) 71 | 72 | ;; parent not in knitgraph 73 | (check-exn 74 | exn:fail? 75 | (λ () 76 | (knitgraph-connect-loops! kg 2 0))) 77 | 78 | ;; child not in knitgraph 79 | (check-exn 80 | exn:fail? 81 | (λ () 82 | (knitgraph-connect-loops! kg 0 2))) 83 | 84 | ;; connect loops 85 | (knitgraph-connect-loops! kg 1 0) 86 | 87 | (check-equal? 88 | (knitgraph-get-loop kg 0) 89 | #s(Loop 0 (0 1) 0 #f (1))) 90 | 91 | (check-equal? 92 | (hash-keys (Knitgraph-stitches kg)) 93 | '(#s(Edge 1 0))) 94 | (check-equal? 95 | (hash-values (Knitgraph-stitches kg)) 96 | '(#s(Edge-Attributes BtF 0 0))) 97 | 98 | (check-equal? 99 | (list->seteq (hash-keys (Knitgraph-yarns kg))) 100 | (seteq 0 1)) 101 | 102 | (check-equal? 103 | (Knitgraph-last-loop-id kg) 104 | 1) 105 | 106 | (check-equal? 107 | (knitgraph-get-prior-loop-id kg 0) 108 | #f) 109 | 110 | (check-equal? 111 | (knitgraph-get-prior-loop-id kg 1) 112 | 0) 113 | (check-equal? 114 | (knitgraph-get-prior-loop-id kg 2) 115 | #f) 116 | 117 | (check-equal? 118 | (knitgraph-get-next-loop-id kg 0) 119 | 1) 120 | 121 | (check-equal? 122 | (knitgraph-get-next-loop-id kg 1) 123 | #f) 124 | 125 | (check-equal? 126 | (knitgraph-has-loop? kg 0) 127 | #t) 128 | 129 | (check-equal? 130 | (knitgraph-get-loop kg 0) 131 | #s(Loop 0 (0 1) 0 #f (1))) 132 | (check-exn 133 | exn:fail? 134 | (λ () 135 | (knitgraph-get-loop kg 2))) 136 | 137 | (check-equal? 138 | (knitgraph-get-stitch kg 1 0) 139 | '#s(Edge-Attributes BtF 0 0)) 140 | (check-equal? 141 | (knitgraph-get-stitch kg 0 1) 142 | #f) 143 | 144 | (check-equal? 145 | (knitgraph-get-parent kg 0) 146 | 1) 147 | (check-equal? 148 | (knitgraph-get-parent kg 1) 149 | #f) 150 | 151 | (check-equal? 152 | (knitgraph-get-parents kg 0) 153 | '(1)) 154 | (check-equal? 155 | (knitgraph-get-parents kg 1) 156 | null) 157 | 158 | (check-equal? 159 | (knitgraph-get-child kg 1) 160 | 0) 161 | (check-equal? 162 | (knitgraph-get-child kg 0) 163 | #f) 164 | 165 | (check-equal? 166 | (knitgraph-get-children kg 1) 167 | '(0)) 168 | (check-equal? 169 | (knitgraph-get-children kg 0) 170 | null) 171 | 172 | ;; parent not in knitgraph 173 | (check-exn 174 | exn:fail? 175 | (λ () 176 | (knitgraph-disconnect-loops! kg 2 0))) 177 | 178 | ;; child not in knitgraph 179 | (check-exn 180 | exn:fail? 181 | (λ () 182 | (knitgraph-disconnect-loops! kg 0 2))) 183 | 184 | ;; disconnect loops 185 | (let ([kg1 (knitgraph-copy kg)]) 186 | (knitgraph-disconnect-loops! kg1 1 0) 187 | (check-equal? 188 | (knitgraph-get-loop kg1 0) 189 | #s(Loop 0 (0 1) 0 #f ())) 190 | (check-equal? 191 | (hash-keys (Knitgraph-stitches kg1)) 192 | null)) 193 | 194 | ;; remove loop 1 195 | (let ([kg2 (knitgraph-copy kg)]) 196 | (knitgraph-remove-loop! kg2 1) 197 | (check-equal? 198 | (list->set 199 | (hash-keys (Knitgraph-loops kg2))) 200 | (set 0)) 201 | (check-equal? 202 | (hash-keys (Knitgraph-stitches kg2)) 203 | null) 204 | (check-equal? 205 | (Knitgraph-last-loop-id kg2) 206 | 0) 207 | (check-equal? 208 | (hash-ref (Knitgraph-yarns kg2) 0) 209 | (Garn 0 '(0) 0))) 210 | 211 | ;; remove loop 0 212 | (let ([kg3 (knitgraph-copy kg)]) 213 | (knitgraph-remove-loop! kg3 0) 214 | (check-equal? 215 | (list->set 216 | (hash-keys (Knitgraph-loops kg3))) 217 | (set 1)) 218 | (check-equal? 219 | (Knitgraph-last-loop-id kg3) 220 | 1) 221 | (check-equal? 222 | (hash-ref (Knitgraph-yarns kg3) 0) 223 | (Garn 0 '(1) 1))) 224 | 225 | ;; insert another loop on y0 226 | (define loop2 227 | (knitgraph-insert-loop! kg y0 0 #f #s(Loop 2 (0) 0 #f ()))) 228 | (check-equal? 229 | (Garn-loops y0) 230 | '(1 2 0)) 231 | 232 | ;; insert another loop on y0 233 | (define loop3 234 | (knitgraph-insert-loop! kg y0 0 #t #f 3)) 235 | (check-equal? 236 | (Garn-loops y0) 237 | '(1 2 0 3)) 238 | 239 | (check-equal? 240 | (knitgraph-make-courses 241 | (stockinette 2 3)) 242 | '(#s(Course (0 1)) 243 | #s(Course (2 3)) 244 | #s(Course (4 5)))) 245 | 246 | ;; end of submodule 247 | ) 248 | 249 | ;; end -------------------------------------------------------------------------------- /knotty/tests/loop.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (require "../../knotty-lib/util.rkt" 22 | "../../knotty-lib/loop.rkt") 23 | 24 | (module+ test 25 | (require typed/rackunit) 26 | 27 | (define loop0 (make-loop 0 '(1 0))) 28 | (define loop1 (make-loop 1 0)) 29 | (define loop2 (make-loop 2 0)) 30 | (define loop3 (loop-add-parent loop0 loop1)) 31 | (define loop4 (loop-add-parent loop3 loop2 1)) 32 | 33 | (check-equal? 34 | loop0 35 | #s(Loop 0 (0 1) 0 #f ())) 36 | 37 | (check-equal? 38 | loop4 39 | #s(Loop 0 (0 1) 0 #f (1 2))) 40 | 41 | (check-equal? 42 | (loop->id loop0) 43 | 0) 44 | 45 | (check-equal? 46 | (loop-has-id? 0 loop0) 47 | #t) 48 | (check-equal? 49 | (loop-has-id? 0 loop1) 50 | #f) 51 | 52 | (check-equal? 53 | (loop-remove-parent loop0 loop1) 54 | loop0) 55 | (check-equal? 56 | (loop-remove-parent loop3 loop1) 57 | loop0) 58 | (check-equal? 59 | (loop-remove-parent loop4 loop2) 60 | loop3) 61 | 62 | ;; end of submodule 63 | ) 64 | 65 | ;; end 66 | -------------------------------------------------------------------------------- /knotty/tests/macros.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (module+ test 22 | (require typed/rackunit 23 | racket/vector ;; for `vector-map` 24 | racket/list ;; for `flatten` `range` 25 | syntax/parse/define) ;; for `define-syntax-parse-rule` 26 | (require "../../knotty-lib/util.rkt" 27 | "../../knotty-lib/stitch.rkt" 28 | "../../knotty-lib/tree.rkt" 29 | "../../knotty-lib/yarn.rkt" 30 | "../../knotty-lib/macros.rkt") 31 | 32 | ;; tests of macro functions 33 | (check-equal? 34 | k 35 | '(0 . #s(Stitch k #f))) 36 | 37 | (check-equal? 38 | p1 39 | '(1 . #s(Stitch p #f))) 40 | 41 | (check-equal? 42 | rs 43 | 'rs) 44 | 45 | (check-equal? 46 | (colorwork-code 0) 47 | #f) 48 | 49 | (check-equal? 50 | (colorwork-code #x30) 51 | 0) 52 | 53 | (check-equal? 54 | (colorwork-code #x39) 55 | 9) 56 | 57 | (check-equal? 58 | (colorwork-code #x3A) 59 | #f) 60 | 61 | (check-equal? 62 | (colorwork-code #x41) 63 | 10) 64 | 65 | (check-equal? 66 | (colorwork-code #x5A) 67 | 35) 68 | 69 | (check-equal? 70 | (colorwork-code #x5B) 71 | #f) 72 | 73 | (check-equal? 74 | (colorwork-code #x61) 75 | 36) 76 | 77 | (check-equal? 78 | (colorwork-code #x7A) 79 | 61) 80 | 81 | (check-equal? 82 | (colorwork-code #x7B) 83 | #f) 84 | 85 | (check-equal? 86 | (colorwork-code #xFF) 87 | #f) 88 | 89 | (check-equal? 90 | (cw "123") 91 | '((1 . #s(Stitch ss 1)) (1 . #s(Stitch ss 2)) (1 . #s(Stitch ss 3)))) 92 | 93 | ) 94 | ;; end 95 | -------------------------------------------------------------------------------- /knotty/tests/mocks.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (require mock 22 | mock/rackunit 23 | rackunit 24 | racket/function) ;; for `const` 25 | (require "../../knotty-lib/stitch.rkt" 26 | "../../knotty-lib/tree.rkt" 27 | "../../knotty-lib/rows.rkt" 28 | "../../knotty-lib/pattern.rkt") 29 | 30 | (define dummy-pattern 31 | (pattern 32 | ((row 1) (make-leaf 1 (make-stitch 'k 0))))) 33 | 34 | ;; mocks for gui.rkt 35 | (module+ test 36 | (require "../../knotty-lib/gui.rkt") 37 | 38 | ;; check that `export-html` exports file 39 | (define mock-html-exporter 40 | (mock #:behavior 41 | (thunk* (open-output-string)))) 42 | (void (export-html dummy-pattern "dummy.html" 43 | #:exports-with mock-html-exporter)) 44 | (check-mock-called-with? mock-html-exporter 45 | (arguments "dummy.html")) 46 | 47 | ;; end of module 48 | ) 49 | 50 | ;; mocks for png.rkt 51 | (module+ test 52 | (require racket/draw) ;; for `read-bitmap` 53 | (require "../../knotty-lib/png.rkt") 54 | 55 | (define small-png 56 | (bytes-append 57 | #"\211PNG\r\n\32\n\0\0\0\r" 58 | #"IHDR\0\0\0\1\0\0\0\2\b\6\0\0\0\231\201\266'\0\0\0\22" 59 | #"IDAT\b\231c\220\226\226\376\317\304\302\302\302\0\0\b\272\1_QO\262\234\0\0\0\0" 60 | #"IEND\256B`\202")) 61 | (define small-bitmap 62 | (read-bitmap (open-input-bytes small-png) 'png)) 63 | 64 | ;; check that `import-png` imports file 65 | (define mock-png-importer 66 | (mock #:behavior 67 | (const small-bitmap))) 68 | (void (import-png "dummy.png" 69 | #:imports-with mock-png-importer)) 70 | (check-mock-called-with? mock-png-importer 71 | (arguments "dummy.png" 'png)) 72 | 73 | ;; end of module 74 | ) 75 | 76 | ;; mocks for xml.rkt 77 | (module+ test 78 | (require sxml) ;; for `srl:sxml->xml` 79 | (require "../../knotty-lib/xml.rkt") 80 | 81 | (define dummy-pattern-sxml 82 | `(*TOP* 83 | ,(pattern->sxml dummy-pattern))) 84 | (define dummy-pattern-xml 85 | (srl:sxml->xml-noindent dummy-pattern-sxml)) 86 | 87 | ;; check that `import-xml` imports file 88 | (define mock-xml-importer 89 | (mock #:behavior 90 | (thunk* (open-input-string dummy-pattern-xml)))) 91 | (void (import-xml "dummy.xml" 92 | #:imports-with mock-xml-importer)) 93 | (check-mock-called-with? mock-xml-importer 94 | (arguments "dummy.xml")) 95 | 96 | ;; check that `export-xml` exports file 97 | (define mock-xml-exporter 98 | (mock #:behavior 99 | (thunk* (open-output-string)))) 100 | (void (export-xml dummy-pattern "dummy.xml" 101 | #:exports-with mock-xml-exporter)) 102 | (check-mock-called-with? mock-xml-exporter 103 | (arguments "dummy.xml")) 104 | 105 | ;; end of module 106 | ) 107 | 108 | ;; end -------------------------------------------------------------------------------- /knotty/tests/options.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (require typed/rackunit) 22 | (require "../../knotty-lib/gauge.rkt" 23 | "../../knotty-lib/options.rkt") 24 | 25 | (module+ test 26 | 27 | #| 28 | ;; machine knits cannot be circular 29 | (check-exn 30 | exn:fail? 31 | (λ () 32 | (Options 'machine-texture 33 | 'circular 34 | 'rs 35 | 'right 36 | #f))) 37 | |# 38 | 39 | ;; hand knits start on RS, RHS 40 | (check-exn 41 | exn:fail? 42 | (λ () 43 | (Options 'hand 44 | 'circular 45 | 'rs 46 | 'left 47 | #f))) 48 | 49 | ;; hand knits start on WS, LHS 50 | (check-exn 51 | exn:fail? 52 | (λ () 53 | (Options 'hand 54 | 'circular 55 | 'ws 56 | 'right 57 | #f))) 58 | 59 | (check-equal? 60 | (options-row-rs? 61 | (Options 'hand 62 | 'flat 63 | 'rs 64 | 'right 65 | #f) 66 | 1) 67 | #t) 68 | 69 | (check-equal? 70 | (options-row-rs? 71 | (Options 'hand 72 | 'flat 73 | 'rs 74 | 'right 75 | #f) 76 | 2) 77 | #f) 78 | 79 | (check-equal? 80 | (options-row-rs? 81 | (Options 'hand 82 | 'flat 83 | 'ws 84 | 'left 85 | #f) 86 | 1) 87 | #f) 88 | 89 | (check-equal? 90 | (options-row-rs? 91 | (Options 'hand 92 | 'flat 93 | 'ws 94 | 'left 95 | #f) 96 | 2) 97 | #t) 98 | 99 | (check-equal? 100 | (options-row-rs? 101 | (Options 'machine 102 | 'flat 103 | 'rs 104 | 'right 105 | #f) 106 | 1) 107 | #t) 108 | 109 | (check-equal? 110 | (options-row-rs? 111 | (Options 'hand 112 | 'circular 113 | 'rs 114 | 'right 115 | #f) 116 | 1) 117 | #t) 118 | 119 | (check-equal? 120 | (options-row-ws? 121 | (Options 'hand 122 | 'circular 123 | 'rs 124 | 'right 125 | #f) 126 | 1) 127 | #f) 128 | 129 | (check-equal? 130 | (options-row-r2l? 131 | (Options 'hand 132 | 'flat 133 | 'rs 134 | 'right 135 | #f) 136 | 1) 137 | #t) 138 | 139 | (check-equal? 140 | (options-row-r2l? 141 | (Options 'hand 142 | 'flat 143 | 'rs 144 | 'right 145 | #f) 146 | 2) 147 | #f) 148 | 149 | (check-equal? 150 | (options-row-r2l? 151 | (Options 'hand 152 | 'flat 153 | 'ws 154 | 'left 155 | #f) 156 | 1) 157 | #f) 158 | 159 | (check-equal? 160 | (options-row-r2l? 161 | (Options 'hand 162 | 'flat 163 | 'ws 164 | 'left 165 | #f) 166 | 2) 167 | #t) 168 | 169 | (check-equal? 170 | (options-row-r2l? 171 | (Options 'machine 172 | 'flat 173 | 'rs 174 | 'right 175 | #f) 176 | 1) 177 | #t) 178 | 179 | (check-equal? 180 | (options-row-r2l? 181 | (Options 'hand 182 | 'circular 183 | 'rs 184 | 'right 185 | #f) 186 | 1) 187 | #t) 188 | 189 | (check-equal? 190 | (options-row-l2r? 191 | (Options 'hand 192 | 'circular 193 | 'rs 194 | 'right 195 | #f) 196 | 1) 197 | #f) 198 | 199 | ) 200 | ;; end 201 | -------------------------------------------------------------------------------- /knotty/tests/png.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (module+ test 22 | (require typed/rackunit 23 | typed/racket/draw 24 | racket/fixnum) 25 | (require "../../knotty-lib/colors.rkt" 26 | "../../knotty-lib/stitch.rkt" 27 | "../../knotty-lib/yarn.rkt" 28 | "../../knotty-lib/tree.rkt" 29 | "../../knotty-lib/macros.rkt" 30 | "../../knotty-lib/rows.rkt" 31 | "../../knotty-lib/rowspec.rkt" 32 | "../../knotty-lib/rowmap.rkt" 33 | "../../knotty-lib/gauge.rkt" 34 | "../../knotty-lib/pattern.rkt" 35 | "../../knotty-lib/png.rkt") 36 | 37 | (check-equal? 38 | (let* ([small 39 | (bytes-append 40 | #"\211PNG\r\n\32\n\0\0\0\r" 41 | #"IHDR\0\0\0\1\0\0\0\2\b\6\0\0\0\231\201\266'\0\0\0\22" 42 | #"IDAT\b\231c\220\226\226\376\317\304\302\302\302\0\0\b\272\1_QO\262\234\0\0\0\0" 43 | #"IEND\256B`\202")] 44 | [input (open-input-bytes small)] 45 | [pic (read-bitmap input 'png)]) 46 | (bitmap->pattern pic)) 47 | (pattern 48 | (yarn #x1B1B1B "Nero") 49 | (yarn #x1F1F1F "Nero (2)") 50 | ((row 1) (cc1 k1)) 51 | ((row 2) p1))) 52 | 53 | (check-equal? 54 | (let* ([megaman 55 | (bytes-append 56 | #"\211PNG\r\n\32\n\0\0\0\r" 57 | #"IHDR\0\0\0\e\0\0\0\34\b\6\0\0\0\220\321\304\355\0\0\0\6bKGD\0\0\0\377\0\377j\331`\37\0\0\1S" 58 | #"IDATH\307\335\226\341\255\204 \20\204g\f}\234\235\234\245\330\211kg\330\tW\t\357\a\242\200(\350\221\373\361HL\324\b\237\273;\263@\21\261\370" 59 | #"\321\350\360\303\241\236L\22\221\354}SX\264\260u\331\27\262\32\250n\201D\357/H\a\264\266\32\330=\2\1\356\231tWe:\277\27\310\32\35D\27\201]UT" 60 | #"\366\304\35It\315\325hF\215\327k\332K\a\227^;\275Ai\230\306\20D\22$aF\r\310\320\306\324\"R\235\2466\260`|>\363\252\v\v\273\326\322Z\273\275\177" 61 | #"T\263\r\342\305A\242\207\206\0315\230Dj\f\320\367\262\315;S\245\272\364\325\364\216%N\2\243\300\230x\261\276\17\24;/\20\31\262\300k5\316\313\1" 62 | #"\330\347\352\27\200n\325,\333-B\2007qx\245?pb\360k\201\310P\257D\262h\201\2L\337\334{t\243\16R\250\307\243v\345\244;$\317\345\216\236\233w\310" 63 | #"t\351\f\0225\3424\272P\251\25{\332%,Rf\262\360a'\230\27\340\304_E\201\34&\371\250|\4^\245\363\22E|\5S\247\220\234\262\202T\211\b\204\214\277[" 64 | #"\357}\355R\260*\32\372\321\361k\207\206@\2255\362\255\205\353\277\347\277=\21\377\1\245\31\265\270\300A\314#\0\0\0\0" 65 | #"IEND\256B`\202")] 66 | [input (open-input-bytes megaman)] 67 | [pic (read-bitmap input 'png)]) 68 | (bitmap->pattern pic #:form 'circular)) 69 | (pattern 70 | #:form 'circular 71 | (yarn #x808080 "Grey") 72 | (yarn #x000000 "Black") 73 | (yarn #x0080C0 "Bondi Blue") 74 | (yarn #x00FFFF "Aqua") 75 | (yarn #xE0E080 "Primrose") 76 | (yarn #xFFFFFF "White") 77 | ((row 1) (cw "000000000000000000000000000")) 78 | ((row 2) (cw "000000000000000000000000000")) 79 | ((row 3) (cw "000111111111000111111111000")) 80 | ((row 4) (cw "000122222221000122222221000")) 81 | ((row 5) (cw "000011222221000122222110000")) 82 | ((row 6) (cw "000000112223101322211000000")) 83 | ((row 7) (cw "000000012233313333210000000")) 84 | ((row 8) (cw "000000001332222333100000000")) 85 | ((row 9) (cw "000001110122222221011100000")) 86 | ((row 10) (cw "000012221122222221122210000")) 87 | ((row 11) (cw "000012221133333331122210000")) 88 | ((row 12) (cw "000012211133333331112210000")) 89 | ((row 13) (cw "000012223133333331322210000")) 90 | ((row 14) (cw "000001223333111113322100000")) 91 | ((row 15) (cw "000001233331444441332100000")) 92 | ((row 16) (cw "000000113312411114111000000")) 93 | ((row 17) (cw "000000001124455545410000000")) 94 | ((row 18) (cw "000000000124551141510000000")) 95 | ((row 19) (cw "000000001324551141510000000")) 96 | ((row 20) (cw "000000001322455522510000000")) 97 | ((row 21) (cw "000000001322222211210000000")) 98 | ((row 22) (cw "000000000122222133210000000")) 99 | ((row 23) (cw "000000000122222111100000000")) 100 | ((row 24) (cw "000000000012221331000000000")) 101 | ((row 25) (cw "000000000001113310000000000")) 102 | ((row 26) (cw "000000000000011100000000000")) 103 | ((row 27) (cw "000000000000000000000000000")) 104 | ((row 28) (cw "000000000000000000000000000")))) 105 | 106 | ) 107 | ;; end 108 | -------------------------------------------------------------------------------- /knotty/tests/pull-direction.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (require "../../knotty-lib/pull-direction.rkt") 22 | 23 | (module+ test 24 | (require typed/rackunit) 25 | 26 | (check-equal? 27 | (pull-direction-opposite 'BtF) 28 | 'FtB) 29 | (check-equal? 30 | (pull-direction-opposite 'FtB) 31 | 'BtF) 32 | 33 | ;; end of submodule 34 | ) 35 | 36 | ;; end -------------------------------------------------------------------------------- /knotty/tests/repeats.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (require typed/rackunit) 22 | (require "../../knotty-lib/repeats.rkt") 23 | 24 | ;; FIXME more tests required 25 | (module+ test 26 | 27 | ;; test `original-row-index` 28 | 29 | (check-equal? 30 | (original-row-index 31 | (Repeats 0 0 #f #f) 1 2 2) 32 | #f) 33 | 34 | (check-equal? 35 | (original-row-index 36 | (Repeats 0 0 #f 1) 1 2 1) 37 | 0) 38 | 39 | (check-equal? 40 | (original-row-index 41 | (Repeats 0 0 1 #f) 1 2 1) 42 | 0) 43 | 44 | (check-equal? 45 | (original-row-index 46 | (Repeats 0 0 2 1) 2 2 1) 47 | 0) 48 | 49 | (check-equal? 50 | (original-row-index 51 | (Repeats 0 0 2 1) 2 2 3) 52 | #f) 53 | 54 | (check-equal? 55 | (original-row-index 56 | (Repeats 0 0 1 2) 2 2 3) 57 | 0) 58 | 59 | (check-equal? 60 | (original-row-index 61 | (Repeats 0 0 3 3) 3 2 4) 62 | 2) 63 | 64 | (check-equal? 65 | (original-row-index 66 | (Repeats 0 0 2 3) 4 2 1) 67 | 0) 68 | 69 | (check-equal? 70 | (original-row-index 71 | (Repeats 0 0 2 3) 4 2 6) 72 | 3) 73 | 74 | (check-equal? 75 | (original-row-index 76 | (Repeats 0 0 2 3) 4 2 7) 77 | #f) 78 | 79 | ) 80 | ;; end 81 | -------------------------------------------------------------------------------- /knotty/tests/rowcount.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (module+ test 22 | (require typed/rackunit 23 | typed/racket) 24 | (require "../../knotty-lib/util.rkt" 25 | "../../knotty-lib/stitch.rkt" 26 | "../../knotty-lib/tree.rkt" 27 | "../../knotty-lib/yarn.rkt" 28 | "../../knotty-lib/macros.rkt" 29 | "../../knotty-lib/rows.rkt" 30 | "../../knotty-lib/rowspec.rkt" 31 | "../../knotty-lib/rowcount.rkt") 32 | 33 | (check-equal? 34 | (rowcount-full-row dummy-rowcount) 35 | (Rowcount 0 0 0 0 0 #f #f #f #f #f #f #f #f 0)) 36 | 37 | (check-equal? 38 | (let ([rowcounts (vector (Rowcount 0 #f #f #f #f #f #f #f #f #f #f #f #f 0))]) 39 | (rowcounts-set-consumed! rowcounts 0 0) 40 | rowcounts) 41 | (vector (Rowcount 0 #f #f #f #f 0 #f #f #f #f #f #f #f 0))) 42 | 43 | (check-equal? 44 | (let ([rowcounts (vector (Rowcount 0 #f #f #f #f #f #f #f #f #f #f #f #f 0))]) 45 | (rowcounts-set-consumed! rowcounts 0 #f) 46 | rowcounts) 47 | (vector (Rowcount 0 #f #f #f #f #f #f #f #f #f #f #f #f 0))) 48 | 49 | (check-equal? 50 | (let ([rowcounts (vector (Rowcount 0 #f #f #f #f #f #f #f #f #f #f #f #f 0))]) 51 | (rowcounts-set-produced! rowcounts 0 0) 52 | rowcounts) 53 | (vector (Rowcount 0 #f #f #f #f #f 0 #f #f #f #f #f #f 0))) 54 | 55 | (check-equal? 56 | (let ([rowcounts (vector (Rowcount 0 #f #f #f #f #f #f #f #f #f #f #f #f 0))]) 57 | (rowcounts-set-produced! rowcounts 0 #f) 58 | rowcounts) 59 | (vector (Rowcount 0 #f #f #f #f #f #f #f #f #f #f #f #f 0))) 60 | 61 | (check-equal? 62 | (let ([rowcounts (vector (Rowcount 0 #f #f #f #f #f #f #f #f #f #f #f #f 0))]) 63 | (rowcounts-set-before! rowcounts 0 0 0) 64 | rowcounts) 65 | (vector (Rowcount 0 0 0 #f #f #f #f #f #f #f #f #f #f 0))) 66 | 67 | (check-equal? 68 | (let ([rowcounts (vector (Rowcount 0 #f #f #f #f #f #f #f #f #f #f #f #f 0))]) 69 | (rowcounts-set-before! rowcounts 0 0 #f) 70 | rowcounts) 71 | (vector (Rowcount 0 0 #f #f #f #f #f #f #f #f #f #f #f 0))) 72 | 73 | (check-equal? 74 | (let ([rowcounts (vector (Rowcount 0 #f #f #f #f #f #f #f #f #f #f #f #f 0))]) 75 | (rowcounts-set-after! rowcounts 0 0 0) 76 | rowcounts) 77 | (vector (Rowcount 0 #f #f 0 0 #f #f #f #f #f #f #f #f 0))) 78 | 79 | (check-equal? 80 | (let ([rowcounts (vector (Rowcount 0 #f #f #f #f #f #f #f #f #f #f #f #f 0))]) 81 | (rowcounts-set-after! rowcounts 0 0 #f) 82 | rowcounts) 83 | (vector (Rowcount 0 #f #f 0 #f #f #f #f #f #f #f #f #f 0))) 84 | 85 | (check-equal? 86 | (let ([rowcounts (vector (Rowcount 0 #f #f #f #f #f #f #f #f #f #f #f #f 0))]) 87 | (rowcounts-no-turns! rowcounts) 88 | rowcounts) 89 | (vector (Rowcount 0 0 0 0 0 #f #f #f #f #f #f #f #f 0))) 90 | ) 91 | ;; end 92 | -------------------------------------------------------------------------------- /knotty/tests/rowmap.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (module+ test 22 | (require typed/rackunit 23 | typed/racket) 24 | (require "../../knotty-lib/util.rkt" 25 | "../../knotty-lib/stitch.rkt" 26 | "../../knotty-lib/tree.rkt" 27 | "../../knotty-lib/yarn.rkt" 28 | "../../knotty-lib/macros.rkt" 29 | "../../knotty-lib/rows.rkt" 30 | "../../knotty-lib/rowmap.rkt") 31 | 32 | ;; row numbers must start at 1 33 | (check-exn 34 | exn:fail? 35 | (λ () 36 | (make-rowmap '#(#(2))))) 37 | 38 | ;; row numbers must be consecutive 39 | (check-exn 40 | exn:fail? 41 | (λ () 42 | (make-rowmap '#(#(1 3))))) 43 | 44 | (define test1 45 | (make-rowmap '#(#(1 2 3) #(4) #(5)))) 46 | 47 | (check-equal? 48 | (rowmap-find test1 1) 49 | 0) 50 | 51 | (check-exn 52 | exn:fail? 53 | (λ () 54 | (rowmap-find dummy-rowmap 2))) 55 | 56 | (check-equal? 57 | (rowmap-odd&even test1) 58 | '(0)) 59 | 60 | (check-equal? 61 | (rowmap-odd&even dummy-rowmap) 62 | null) 63 | 64 | (check-equal? 65 | (rowmap-first test1 0) 66 | 1) 67 | 68 | ) 69 | ;; end 70 | -------------------------------------------------------------------------------- /knotty/tests/rows.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (require typed/rackunit 22 | typed/racket) 23 | (require "../../knotty-lib/util.rkt" 24 | "../../knotty-lib/stitch.rkt" 25 | "../../knotty-lib/tree.rkt" 26 | "../../knotty-lib/yarn.rkt" 27 | "../../knotty-lib/macros.rkt" 28 | "../../knotty-lib/rowspec.rkt" 29 | "../../knotty-lib/rows.rkt") 30 | 31 | (module+ test 32 | ;; tests of `rows` constructor 33 | 34 | ;; multiple (non-nested) repeats 35 | (check-exn 36 | exn:fail? 37 | (λ () 38 | ((rows 1) (repeat k1) p))) 39 | 40 | ;; no variable repeats, combine adjacent leaves 41 | (check-equal? 42 | ((rows 1 #:memo "test of `rows` constructor") k1 k1) 43 | (Rows 44 | '(1) 45 | (Rowspec '((2 . #s(Stitch k 0))) "test of `rows` constructor" 0 (set 0) 'no-turn))) 46 | 47 | ;; no variable repeats, combine leaf in singleton node 48 | (check-equal? 49 | ((rows 1 #:memo "test of `rows` constructor") (x2 k1)) 50 | (Rows 51 | '(1) 52 | (Rowspec '((2 . #s(Stitch k 0))) "test of `rows` constructor" 0 (set 0) 'no-turn))) 53 | 54 | ;; no variable repeats, multiple simplifications 55 | (check-equal? 56 | ((rows 1 #:memo "test of `rows` constructor") (x2 (x3 (x4 k1 k1)))) 57 | (Rows 58 | '(1) 59 | (Rowspec '((48 . #s(Stitch k 0))) "test of `rows` constructor" 0 (set 0) 'no-turn))) 60 | 61 | ;; nonconsecutive rows 62 | (check-equal? 63 | ((rows 1 3 #:memo "test of `rows` constructor") p2) 64 | (Rows 65 | '(1 3) 66 | (Rowspec '((2 . #s(Stitch p 0))) "test of `rows` constructor" 0 (set 0) 'no-turn))) 67 | 68 | ;; consecutive and conformable 69 | (check-equal? 70 | ((rows 1 2 #:memo "test of `rows` constructor") k2 p2) 71 | (Rows 72 | '(1 2) 73 | (Rowspec '((2 . #s(Stitch k 0)) (2 . #s(Stitch p 0))) "test of `rows` constructor" 0 (set 0) 'no-turn))) 74 | 75 | ;; consecutive and conformable, memo, repeated and list-format row numbers 76 | (check-equal? 77 | ((rows (seq 1 2) '(1) #:memo "test of `rows` constructor") p2 (repeat yo (x3 bo2) (twice yo)) (x3 cdd)) 78 | (Rows 79 | '(1 2) 80 | (Rowspec 81 | '((2 . #s(Stitch p 0)) 82 | (0 83 | (1 . #s(Stitch yo 0)) 84 | (3 (2 . #s(Stitch bo 0))) 85 | (2 (1 . #s(Stitch yo 0)))) 86 | (3 (1 . #s(Stitch cdd 0)))) "test of `rows` constructor" 0 (set 0) 'no-turn))) 87 | #| 88 | ;; consecutive but not conformable 89 | (check-exn 90 | exn:fail? 91 | (λ () 92 | ((rows 1 2) k1 m))) 93 | 94 | ;; consecutive but not conformable 95 | (check-exn 96 | exn:fail? 97 | (λ () 98 | ((rows 1 2) k1 ssk))) 99 | |# 100 | ;; no row numbers 101 | (check-exn 102 | exn:fail? 103 | (λ () 104 | ((rows null) k1))) 105 | 106 | ;; MC is default yarn 107 | (check-equal? 108 | ((rows 1 #:memo "test of yarn function") (cc1 k1)) 109 | (Rows 110 | '(1) 111 | (Rowspec '((1 . #s(Stitch k 1))) "test of yarn function" 0 (set 0) 'no-turn))) 112 | 113 | ;; yarn MC 114 | (check-equal? 115 | ((rows 1 #:yarn mc #:memo "test of yarn function") (cc2 k1)) 116 | (Rows 117 | '(1) 118 | (Rowspec '((1 . #s(Stitch k 2))) "test of yarn function" 0 (set 0) 'no-turn))) 119 | 120 | ;; invalid yarn 121 | (check-exn 122 | exn:fail? 123 | (λ () 124 | ((rows 1 #:yarn 'cc0 #:memo "test of yarn function") (cc1 k1)))) 125 | 126 | ;; innermost yarn specification has priority 127 | (check-equal? 128 | ((rows 1 #:memo "test of yarn function") (mc (cc3 k1))) 129 | (Rows 130 | '(1) 131 | (Rowspec '((1 . #s(Stitch k 3))) "test of yarn function" 0 (set 0) 'no-turn))) 132 | 133 | ;; row #:yarn specification cedes priority 134 | (check-equal? 135 | ((rows 1 #:yarn cc1 #:memo "test of yarn function") k1 (cc4 p1)) 136 | (Rows 137 | '(1) 138 | (Rowspec 139 | '((1 . #s(Stitch k 1)) 140 | (1 . #s(Stitch p 4))) "test of yarn function" 1 (seteq 1 4) 'no-turn))) 141 | 142 | ;; row #:yarn specification cedes priority 143 | (check-equal? 144 | ((rows 1 #:yarn cc5 #:memo "test of yarn function") (mc k1) p1) 145 | (Rows 146 | '(1) 147 | (Rowspec 148 | '((1 . #s(Stitch k 0)) 149 | (1 . #s(Stitch p 5))) "test of yarn function" 5 (seteq 0 5) 'no-turn))) 150 | 151 | ;; unparseable row #:yarn specification 152 | (check-exn 153 | exn:fail? 154 | (λ () 155 | ((rows 1 #:yarn 'green #:memo "test of yarn function") k1))) 156 | 157 | ;; 'mc is default yarn 158 | (check-equal? 159 | ((rows 1 #:yarn #f #:memo "test of yarn function") k1) 160 | (Rows '(1) 161 | (Rowspec '((1 . #s(Stitch k 0))) "test of yarn function" 0 (set 0) 'no-turn))) 162 | 163 | #| should give warning 164 | ;; 'mc is default yarn 165 | (check-equal? 166 | (parameterize ([SAFE #f]) 167 | ((rows 1 #:yarn 'green #:memo "test of yarn function") k1)) 168 | (Rows '(1) '((1 . #s(Stitch k 0))) "test of yarn function" 0 1 #'no-turn)) 169 | |# 170 | 171 | ;; turn in middle of row 172 | (check-exn 173 | exn:fail? 174 | (λ () 175 | ((rows 1) turn k1))) 176 | 177 | ;; turn in middle of row 178 | (check-exn 179 | exn:fail? 180 | (λ () 181 | ((rows 1) w&t w&t w&t))) 182 | 183 | ;; turn in repeat 184 | (check-exn 185 | exn:fail? 186 | (λ () 187 | ((rows 1) k1 (x1 w&t)))) 188 | 189 | ;; short row with variable number repeat 190 | (check-exn 191 | exn:fail? 192 | (λ () 193 | ((rows 1) k w&t))) 194 | 195 | ;; turn not last stitch in row 196 | (check-exn 197 | exn:fail? 198 | (λ () 199 | ((rows 1) k1 w&t k1))) 200 | 201 | ;; short row 202 | (check-equal? 203 | ((rows 1 #:memo "test of short row") k1 turn) 204 | (Rows 205 | '(1) 206 | (Rowspec '((1 . #s(Stitch k 0)) (1 . #s(Stitch turn 0))) "test of short row" 0 (set 1) 'turn))) ;; FIXME eventually need to fix turn to width 0 207 | 208 | (check-equal? 209 | (consecutive-rows '(1 2)) 210 | #t) 211 | 212 | (check-equal? 213 | (consecutive-rows '(1)) 214 | #f) 215 | 216 | (check-equal? 217 | (consecutive-rows '(1 3)) 218 | #f) 219 | 220 | (check-equal? 221 | (seq 3) 222 | '(1 2 3)) 223 | 224 | (check-equal? 225 | (seq 1 9 2) 226 | '(1 3 5 7 9)) 227 | 228 | ;; FIXME test yarns used 229 | 230 | ) 231 | ;; end 232 | -------------------------------------------------------------------------------- /knotty/tests/rowspec.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | ;; FIXME need more tests 22 | 23 | (module+ test 24 | (require typed/rackunit 25 | threading) 26 | (require "../../knotty-lib/util.rkt" 27 | "../../knotty-lib/stitch.rkt" 28 | "../../knotty-lib/tree.rkt" 29 | "../../knotty-lib/yarn.rkt" 30 | "../../knotty-lib/macros.rkt" 31 | "../../knotty-lib/rows.rkt" 32 | "../../knotty-lib/rowspec.rkt") 33 | 34 | (check-equal? 35 | (Rowspec null "" 0 (set 0) 'no-turn) 36 | dummy-rowspec) 37 | 38 | (check-equal? 39 | (rowspec-stitches-compatible? dummy-rowspec 'hand) 40 | #t) 41 | 42 | (check-equal? 43 | (rowspec-stitches-compatible? 44 | (Rowspec 45 | (list (make-leaf 1 #s(Stitch tuck 0))) 46 | "" 0 (set 1) 'no-turn) 47 | 'hand) 48 | #f) 49 | 50 | (check-equal? 51 | (rowspec-stitches-compatible? 52 | (Rowspec 53 | (list (make-leaf 1 #s(Stitch dyo 0))) 54 | "" 0 (set 1) 'no-turn) 55 | 'machine) 56 | #f) 57 | 58 | (check-equal? 59 | (rowspec-set-stitches dummy-rowspec '((1 . #s(Stitch k 0)))) 60 | (Rowspec '((1 . #s(Stitch k 0))) "" 0 (set 0) 'no-turn)) 61 | 62 | (check-equal? 63 | (rowspec-swap-stitch 64 | (Rowspec '((1 . #s(Stitch k 0))) "" 0 (set 0) 'no-turn) 65 | 'k 'p) 66 | (Rowspec '((1 . #s(Stitch p 0))) "" 0 (set 0) 'no-turn)) 67 | 68 | (check-exn 69 | exn:fail? 70 | (λ () 71 | (Rowspec '((1 . #s(Stitch turnr 0)) (1 . #s(Stitch k 0))) "" 0 (set 0) 'turn))) 72 | 73 | ) 74 | ;; end 75 | 76 | -------------------------------------------------------------------------------- /knotty/tests/simple-knitgraphs.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | 6 | MIT License 7 | 8 | Copyright (c) 2023 Tom Price. 9 | 10 | Incorporating concepts from https://pypi.org/project/knit-script/ 11 | Copyright (c) 2022 Megan Hofmann, Northeastern University Khoury College of 12 | Computer Sciences Accessible Creative Technologies (ACT) Lab and Contributors. 13 | 14 | Permission is hereby granted, free of charge, to any person obtaining a copy 15 | of this software and associated documentation files (the "Software"), to deal 16 | in the Software without restriction, including without limitation the rights 17 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | copies of the Software, and to permit persons to whom the Software is 19 | furnished to do so, subject to the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included in all 22 | copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 26 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 27 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 28 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | |# 31 | 32 | (provide (all-defined-out)) 33 | (require "../../knotty-lib/pull-direction.rkt" 34 | "../../knotty-lib/loop.rkt" 35 | "../../knotty-lib/garn.rkt" 36 | "../../knotty-lib/course.rkt" 37 | "../../knotty-lib/knitgraph.rkt") 38 | 39 | ;; Adapted from https://github.com/mhofmann-uw/599-Knitting-Complete/blob/main/debugging_tools/simple_knitgraphs.py 40 | 41 | (: stockinette : Positive-Integer Positive-Integer -> Knitgraph) 42 | (define (stockinette width height) 43 | (let* ([kg (make-knitgraph)] 44 | [y0 (make-yarn 0)]) 45 | (knitgraph-add-yarn! kg y0) 46 | (let* ([first-row 47 | (reverse 48 | (for/list ([i (in-range width)]) : (Listof Natural) 49 | (let ([loop (knitgraph-add-loop-to-end! kg y0)]) 50 | (Loop-id loop))))]) 51 | (let row-iter ([prev first-row] 52 | [row 1]) 53 | (if (= row height) 54 | kg 55 | (row-iter 56 | (reverse 57 | (for/list ([i (in-range width)]) : (Listof Natural) 58 | (let* ([child (knitgraph-add-loop-to-end! kg y0)] 59 | [child-id (Loop-id child)] 60 | [parent-id (list-ref prev i)]) 61 | (knitgraph-connect-loops! kg parent-id child-id) 62 | child-id))) 63 | (add1 row))))))) 64 | 65 | (: rib : Positive-Integer Positive-Integer Positive-Integer -> Knitgraph) 66 | (define (rib width height rib-width) 67 | (let* ([kg (make-knitgraph)] 68 | [y0 (make-yarn 0)]) 69 | (knitgraph-add-yarn! kg y0) 70 | (let ([first-row 71 | (reverse 72 | (for/list ([i (in-range width)]) : (Listof Natural) 73 | (let ([loop (knitgraph-add-loop-to-end! kg y0)]) 74 | (Loop-id loop))))]) 75 | (if (= 1 height) 76 | kg 77 | (let ([second-row 78 | (reverse 79 | (for/list ([i (in-range width)]) : (Listof Natural) 80 | (let* ([loop (knitgraph-add-loop-to-end! kg y0)] 81 | [rib-id (quotient i rib-width)] 82 | [pull-direction 83 | (if (even? rib-id) ;; rib starts with Knit stitches on RS 84 | 'BtF 85 | 'FtB)] 86 | [parent-id (list-ref first-row i)] 87 | [child-id (Loop-id loop)]) 88 | (knitgraph-connect-loops! kg parent-id child-id #f pull-direction) 89 | child-id)))]) 90 | (let row-iter ([prev second-row] 91 | [row 2]) 92 | (if (= row height) 93 | kg 94 | (row-iter 95 | (reverse 96 | (for/list ([i (in-range width)]) : (Listof Natural) 97 | (let* ([loop (knitgraph-add-loop-to-end! kg y0)] 98 | [parent-id (list-ref prev i)] 99 | [child-id (Loop-id loop)] 100 | [stitches (Knitgraph-stitches kg)] 101 | [edges (hash-keys stitches)] 102 | [parent-stitch 103 | (findf (λ ([x : Edge]) (= parent-id (Edge-child x))) 104 | edges)] 105 | [grandparent-id 106 | (if (false? parent-stitch) 107 | (error 'knotty "parent stitch not found") 108 | (Edge-parent parent-stitch))] 109 | [pull-direction 110 | (Edge-Attributes-pull-direction (hash-ref stitches parent-stitch))]) 111 | (knitgraph-connect-loops! kg parent-id child-id #f pull-direction) 112 | child-id))) 113 | (add1 row))))))))) 114 | 115 | #| 116 | def seed(width: int = 4, height=4) -> Knit_Graph: 117 | """ 118 | :param width: a number greater than 0 to set the number of stitches in the swatch 119 | :param height: A number greater than 0 to set teh number of courses in the swatch 120 | :return: A knit graph with a checkered pattern of knit and purl stitches of width and height size. 121 | The first stitch should be a knit 122 | """ 123 | assert width > 0 124 | assert height > 1 125 | 126 | knitGraph = Knit_Graph() 127 | yarn = Yarn("yarn", knitGraph) 128 | knitGraph.add_yarn(yarn) 129 | first_row = [] 130 | for _ in range(0, width): 131 | loop_id, loop = yarn.add_loop_to_end() 132 | first_row.append(loop_id) 133 | knitGraph.add_loop(loop) 134 | 135 | prior_row = first_row 136 | next_row = [] 137 | for column, parent_id in enumerate(reversed(prior_row)): 138 | child_id, child = yarn.add_loop_to_end() 139 | next_row.append(child_id) 140 | knitGraph.add_loop(child) 141 | if column % 2 == 0: # even seed: 142 | pull_direction = Pull_Direction.BtF 143 | else: 144 | pull_direction = Pull_Direction.FtB 145 | knitGraph.connect_loops(parent_id, child_id, pull_direction=pull_direction) 146 | 147 | for _ in range(2, height): 148 | prior_row = next_row 149 | next_row = [] 150 | for parent_id in reversed(prior_row): 151 | child_id, child = yarn.add_loop_to_end() 152 | next_row.append(child_id) 153 | knitGraph.add_loop(child) 154 | grand_parent = [*knitGraph.graph.predecessors(parent_id)][0] 155 | parent_pull_direction = knitGraph.graph[grand_parent][parent_id]["pull_direction"] 156 | knitGraph.connect_loops(parent_id, child_id, pull_direction=parent_pull_direction.opposite()) 157 | 158 | return knitGraph 159 | |# 160 | 161 | #| 162 | (: viz : Knitgraph -> Void) 163 | (define (viz kg) 164 | (graphviz (Knitgraph-graph kg))) 165 | |# 166 | 167 | (define kg0 (stockinette 4 4)) 168 | (define kg1 (rib 6 6 2)) 169 | ;(define out (open-output-file "test.dot" #:exists 'replace)) 170 | ;(write-bytes (string->bytes/utf-8 (graphviz (Knitgraph-graph kg))) out) 171 | ;(close-output-port out) 172 | 173 | ;; end -------------------------------------------------------------------------------- /knotty/tests/stitch-instructions.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (module+ test 22 | (require typed/rackunit) 23 | (require "../../knotty-lib/util.rkt" 24 | "../../knotty-lib/stitch.rkt" 25 | "../../knotty-lib/stitch-instructions.rkt") 26 | 27 | ;; tests of stitch instruction functions 28 | 29 | (check-equal? 30 | (get-stitch-instructions 'k #t) 31 | "Knit") 32 | 33 | (check-equal? 34 | (get-stitch-instructions 'kbtl #f) 35 | #f) 36 | 37 | (check-equal? 38 | (get-stitch-instructions 'tuck #t) 39 | #f) 40 | 41 | ;; check that all hand stitches have an instruction 42 | ;; check that all machine stitches have an instruction 43 | 44 | ) 45 | ;; end 46 | -------------------------------------------------------------------------------- /knotty/tests/stitch.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (module+ test 22 | (require typed/rackunit) 23 | (require "../../knotty-lib/util.rkt" 24 | "../../knotty-lib/stitch.rkt") 25 | 26 | ;; tests of stitch functions 27 | 28 | (check-equal? 29 | (get-stitchtype 'k) 30 | '#s(Stitchtype k p p k 1 #f #"k" #"p" 32 46 1 1 0 #t #t #t #t "knit")) 31 | 32 | (check-equal? 33 | (get-stitchtype 'na) 34 | '#s(Stitchtype na na na na 1 #f #"" #"" #f #f 1 1 0 #t #t #t #t "blank")) 35 | 36 | (check-exn 37 | exn:fail? 38 | (λ () 39 | (get-stitchtype 'octopus))) 40 | 41 | (check-equal? 42 | (make-stitch 'k 0) 43 | '#s(Stitch k 0)) 44 | 45 | #| gives warning 46 | (check-equal? 47 | (parameterize ([SAFE #f]) (get-stitchtype 'octopus)) 48 | '#s(Stitchtype ns ns ns ns 1 #f #"w" #"w" 44 44 0 0 0 #f #f #t #t "no stitch")) 49 | |# 50 | 51 | (check-equal? 52 | (turn? 'k) 53 | #f) 54 | 55 | (check-equal? 56 | (w&t? 'w&t) 57 | #t) 58 | 59 | ) 60 | ;; end 61 | -------------------------------------------------------------------------------- /knotty/tests/text.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (require typed/rackunit) 22 | (require/typed sxml 23 | [srl:sxml->xml-noindent (Sexp -> String)] 24 | [sxml:modify ((Listof (U String Symbol (Sexp Any Sexp -> (U Sexp (Listof Sexp))) Sexp)) -> (Sexp -> Sexp))]) 25 | (require "../../knotty-lib/util.rkt" 26 | "../../knotty-lib/stitch.rkt" 27 | "../../knotty-lib/stitch-instructions.rkt" 28 | "../../knotty-lib/gauge.rkt" 29 | "../../knotty-lib/yarn.rkt" 30 | "../../knotty-lib/macros.rkt" 31 | "../../knotty-lib/tree.rkt" 32 | "../../knotty-lib/rows.rkt" 33 | "../../knotty-lib/rowspec.rkt" 34 | "../../knotty-lib/rowmap.rkt" 35 | "../../knotty-lib/pattern.rkt") 36 | (require/typed "../../knotty-lib/text.rkt" 37 | [pattern->text (Pattern -> String)]) 38 | 39 | (module+ test 40 | 41 | (define 42 | test-pattern 43 | (pattern 44 | #:name "Demo" 45 | #:url "url" 46 | #:attribution '(#s(Author "Me" "")) 47 | #:technique 'hand 48 | (yarn 0 "black" 5) 49 | (yarn #xffffff "white" 6) 50 | ((rows 1 3 #:memo "memo") k1 (twice (mc p1) (cc1 k1 p1)) k1) 51 | ((rows 2 4 #:yarn cc1) k1 (mc (x3 p1 k1)) k1) 52 | ((row 5 #:memo "last row!") bo))) 53 | 54 | ;; test `pattern->text` 55 | (check-equal? 56 | (pattern->text test-pattern) 57 | (string-append 58 | "Demo\n\n" 59 | "Author:\nMe\n\n" 60 | "Notes:\n" 61 | "This hand knitting pattern is designed to be knit flat.\n" 62 | "Odd-numbered rows are knit on the RS of the piece, even-numbered rows on the WS.\n" 63 | "The first row starts on the right hand side of the pattern.\n\n" 64 | "Yarn:\nMC - #000000 black bulky \nCC1 - #FFFFFF white super bulky \n\n" 65 | ;"Stitches:\nbo : Bind off\nk : Knit\np : Purl\n\n" 66 | "Instructions:\n" 67 | "Cast on 8 stitches.\n" 68 | "Rows 1 and 3 (RS): in MC k1; [ in MC p1; in CC1 k1, p1 ] twice; in MC k1 (memo).\n" 69 | "Rows 2 and 4: in CC1 k1; [ in MC p1, k1 ] 3 times; in CC1 k1.\n" 70 | "Row 5: in MC bo to end of row (last row!; 0 stitches).\n")) 71 | 72 | ;; test `pattern->text` 73 | (check-equal? 74 | (pattern->text 75 | (pattern 76 | #:technique 'hand 77 | #:form 'circular 78 | #:side 'left 79 | #:face 'ws 80 | #:repeat-rows 1 81 | (yarn #xfeedee "pink" 7) 82 | ((row 1) k10))) 83 | (string-append 84 | "Notes:\n" 85 | "This hand knitting pattern is designed to be knit in the round.\n" 86 | "Every round is knit on the WS of the piece.\n" 87 | "Each round starts on the left hand side of the pattern.\n\n" 88 | "Yarn:\nMC - #FEEDEE pink jumbo \n\n" 89 | ;"Stitches:\nk : Knit\n\n" 90 | "Instructions:\n" 91 | "Cast on 10 stitches and join in the round.\n" 92 | "Round 1 (WS): in MC k10.\n" 93 | "Repeat round 1.\n")) 94 | 95 | ;; test `pattern->text` 96 | (check-equal? 97 | (pattern->text 98 | (pattern 99 | #:technique 'machine 100 | #:form 'flat 101 | #:side 'left 102 | #:face 'rs 103 | #:keywords '("knitting" "cool stuff") 104 | #:attribution '(#s(Author "Tom" "") #s(Author "Dick" "") #s(Author "Harry" "")) 105 | #:gauge (Gauge 10 4 12 4 'inch) 106 | #:repeat-rows 1 107 | (yarn #xfeedee "pink" 0) 108 | ((row 1) (repeat k1 p1)))) 109 | (string-append 110 | "Authors:\nTom, Dick and Harry\n\n" 111 | "Tags:\nknitting, cool stuff.\n\n" 112 | "Gauge:\n10 stitches in 4\", 12 rows in 4\".\n\n" 113 | "Notes:\n" 114 | "This machine knitting pattern is designed to be knit flat.\n" 115 | "Every row is knit on the RS of the piece.\n" 116 | "The first row starts on the left hand side of the pattern.\n\n" 117 | "Yarn:\nMC - #FEEDEE pink lace \n\n" 118 | ;"Stitches:\nk2tog : Right-slanting decrease\n\n" 119 | "Instructions:\n" 120 | "Cast on a multiple of 2 stitches.\n" 121 | "Row 1 (RS): * in MC k1, p1; repeat from * to end of row.\n" 122 | "Repeat row 1.\n")) 123 | 124 | ;; test `pattern->text` 125 | (check-equal? 126 | (pattern->text 127 | (pattern 128 | #:technique 'machine 129 | #:form 'circular 130 | #:side 'right 131 | #:face 'ws 132 | (yarn #xfeedee "pink" 1) 133 | ((row 1) (repeat k1 p1) k1))) 134 | (string-append 135 | "Notes:\n" 136 | "This machine knitting pattern is designed to be knit in the round.\n" 137 | "Every round is knit on the WS of the piece.\n" 138 | "Each round starts on the right hand side of the pattern.\n\n" 139 | "Yarn:\nMC - #FEEDEE pink super fine \n\n" 140 | ;"Stitches:\nk2tog : Right-slanting decrease\n\n" 141 | "Instructions:\n" 142 | "Cast on a multiple of 2 stitches plus 1 and join in the round.\n" 143 | "Round 1 (WS): * in MC k1, p1; repeat from * to last stitch; k1.\n")) 144 | 145 | ;; FIXME need more varied tests 146 | 147 | ) 148 | ;; end 149 | -------------------------------------------------------------------------------- /knotty/tests/util.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (module+ test 22 | (require typed/rackunit 23 | racket/fixnum) 24 | (require "../../knotty-lib/util.rkt") 25 | 26 | (check-equal? 27 | (uniq 28 | '(1 2 2 3 3 3)) 29 | '(1 2 3)) 30 | 31 | (check-equal? 32 | (diff * 33 | '(1 2 3)) 34 | '(2 6)) 35 | 36 | (check-equal? 37 | (sum 38 | '(1 2 3)) 39 | 6) 40 | 41 | (check-equal? 42 | (vector-which 43 | '#()) 44 | #f) 45 | 46 | (check-equal? 47 | (vector-which 48 | '#(#f 'xyzzy)) 49 | 1) 50 | 51 | (check-equal? (vector-sum '#(1 2 3)) 6) 52 | (check-equal? (vector-min '#(1 2 3)) 1) 53 | (check-equal? (vector-max '#(1 2 3)) 3) 54 | 55 | (check-equal? 56 | (vector-reverse 57 | '#(1 2 3)) 58 | '#(3 2 1)) 59 | 60 | (check-equal? 61 | (cum-sum 62 | '(1 2 3)) 63 | '(1 3 6)) 64 | 65 | (check-equal? 66 | (rownums->text '(1)) 67 | " 1") 68 | 69 | (check-equal? 70 | (rownums->text '(1 2)) 71 | "s 1 and 2") 72 | 73 | (check-equal? 74 | (rownums->text '(1 2 3)) 75 | "s 1, 2 and 3") 76 | 77 | (check-equal? 78 | (bytes-max '(#x41 #x42 #x43)) 79 | #x43) 80 | 81 | (check-equal? 82 | (bytes-reverse #"ABC") 83 | #"CBA") 84 | 85 | (check-equal? 86 | (unique-bytes #"AABBCCC") 87 | '(#x41 #x42 #x43)) 88 | 89 | (check-equal? 90 | (byte-sum #xFF #xFF) 91 | #xFE) 92 | 93 | (check-equal? 94 | (hex-color 255) 95 | "0000FF") 96 | 97 | (check-equal? 98 | (bytes-index '(2 4 1 5)) 99 | #"\377\2\0\377\1\3") 100 | 101 | (check-equal? 102 | (hash->list (list-index '(2 #f))) 103 | '((#f . 1) (2 . 0))) 104 | 105 | (check-equal? 106 | (string-chop-last "Flava") 107 | "Flav") 108 | 109 | (check-equal? 110 | (contrast-color-hex "") 111 | "black") 112 | 113 | (check-equal? 114 | (contrast-color-hex "00000G") 115 | "black") 116 | 117 | (check-equal? 118 | (hex->byte "100") 119 | #f) 120 | 121 | (check-equal? 122 | (contrast-color-rgb 0 0 0) 123 | "white") 124 | 125 | (check-equal? 126 | (contrast-color-rgb 255 255 0) 127 | "black") 128 | 129 | (check-equal? 130 | (remove-hyphen 'hyphenated-word) 131 | "hyphenated word") 132 | 133 | (check-equal? 134 | (remove-underscore 'words_with_underscores) 135 | "words with underscores") 136 | 137 | (check-equal? 138 | (safe-substring "something" 0 4) 139 | "some") 140 | 141 | (check-equal? 142 | (safe-substring "something" 4 99) 143 | "thing") 144 | 145 | (check-equal? (be-false) #f) 146 | 147 | (check-equal? (int->bool 0) #f) 148 | (check-equal? (int->bool 1) #t) 149 | 150 | (check-equal? (bool->int #f) 0) 151 | (check-equal? (bool->int #t) 1) 152 | 153 | (check-equal? (truthy? #f ) #f) 154 | (check-equal? (truthy? null) #t) 155 | 156 | (check-equal? (halve 0) 0) 157 | (check-equal? (halve 1) 1) 158 | (check-equal? (halve 2) 1) 159 | (check-equal? (halve 3) 2) 160 | (check-equal? (halve -3) -2) 161 | 162 | (check-equal? ((mult 5) 2) 10) 163 | 164 | (check-equal? 165 | (repeat->text 1 #t) 166 | " once") 167 | 168 | (check-equal? 169 | (multiple->text 2 1) 170 | "multiple of 2 stitches plus 1") 171 | 172 | (check-equal? 173 | (more-or-less 2) 174 | "2 more stitches") 175 | 176 | (check-equal? 177 | (more-or-less 1) 178 | "1 more stitch") 179 | 180 | (check-equal? 181 | (more-or-less -1) 182 | "1 less stitch") 183 | 184 | (check-equal? 185 | (more-or-less -2) 186 | "2 fewer stitches") 187 | 188 | (check-equal? 189 | (remove-tags "ok") 190 | "ok") 191 | 192 | (check-equal? (string->natural "") #f) 193 | (check-equal? (string->natural "x") #f) 194 | (check-equal? (string->natural "+nan.f") #f) 195 | (check-equal? (string->natural "-inf.0") #f) 196 | (check-equal? (string->natural "+inf.f") #f) 197 | (check-equal? (string->natural "-1+i") #f) 198 | (check-equal? (string->natural "-1.2") #f) 199 | (check-equal? (string->natural "0") 0) 200 | (check-equal? (string->natural "1") 1) 201 | 202 | (check-equal? (string->positive-integer "") #f) 203 | (check-equal? (string->positive-integer "0") #f) 204 | (check-equal? (string->positive-integer "1") 1) 205 | 206 | (check-equal? (string->byte "") #f) 207 | (check-equal? (string->byte "0") 0) 208 | (check-equal? (string->byte "256") #f) 209 | 210 | (check-equal? (string->boolean "") #f) 211 | (check-equal? (string->boolean "0") #f) 212 | (check-equal? (string->boolean "1") #t) 213 | 214 | (check-equal? 215 | (findf-index (λ (_) #t) null) 216 | #f) 217 | (check-equal? 218 | (findf-index odd? '(0 1 2 3)) 219 | 1) 220 | 221 | ;; end of submodule 222 | ) 223 | 224 | ;; end 225 | -------------------------------------------------------------------------------- /knotty/tests/yarn.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | #| 4 | Knotty, a domain specific language for knitting patterns. 5 | Copyright (C) 2021-3 Tom Price 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | |# 20 | 21 | (module+ test 22 | (require typed/rackunit) 23 | (require "../../knotty-lib/stitch.rkt" 24 | "../../knotty-lib/tree.rkt" 25 | "../../knotty-lib/yarn.rkt") 26 | 27 | ;; tests of yarn functions 28 | 29 | ;; invalid yarn color 30 | (check-exn 31 | exn:fail? 32 | (λ () 33 | (yarn #x1000000))) 34 | 35 | ;; invalid yarn weight 36 | (check-exn 37 | exn:fail? 38 | (λ () 39 | (yarn 0 "" 8))) 40 | 41 | (check-equal? 42 | (yarn-id #f) 43 | "") 44 | 45 | (check-equal? 46 | (yarn-id 0) 47 | "MC") 48 | 49 | (check-equal? 50 | (yarn-id 1) 51 | "CC1") 52 | 53 | (check-equal? 54 | (inyarn #f) 55 | "") 56 | 57 | (check-equal? 58 | (inyarn 0) 59 | "in MC") 60 | 61 | (check-equal? 62 | (inyarn 1) 63 | "in CC1") 64 | 65 | ) 66 | ;; end 67 | --------------------------------------------------------------------------------