diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..34ec1c2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*~ +\#* +.\#* +.DS_Store +compiled/ +/doc/ +.dmg diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..f055199 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,49 @@ +language: c + +# Based on: https://github.com/greghendershott/travis-racket + +env: + global: + # Supply a global RACKET_DIR environment variable. This is where + # Racket will be installed. A good idea is to use ~/racket because + # that doesn't require sudo to install. + - RACKET_DIR=~/racket + matrix: + # Supply at least one RACKET_VERSION environment variable. This is + # used by the install-racket.sh script (run at before_install, + # below) to select the version of Racket to download and install. + # + # Supply more than one RACKET_VERSION (as in the example below) to + # create a Travis-CI build matrix to test against multiple Racket + # versions. + - RACKET_VERSION=6.12 + - RACKET_VERSION=7.0 + - RACKET_VERSION=7.1 + - RACKET_VERSION=7.2 + - RACKET_VERSION=HEAD + +matrix: + allow_failures: +# - env: RACKET_VERSION=HEAD + fast_finish: true + +before_install: +- git clone https://github.com/greghendershott/travis-racket.git ~/travis-racket +- cat ~/travis-racket/install-racket.sh | bash # pipe to bash not sh! +- export PATH="${RACKET_DIR}/bin:${PATH}" #install-racket.sh can't set for us + +install: + - raco pkg install --auto --name guiapp + +before_script: + +# Here supply steps such as raco make, raco test, etc. You can run +# `raco pkg install --deps search-auto` to install any required +# packages without it getting stuck on a confirmation prompt. +script: + - raco test -x -p guiapp + +after_success: + - raco setup --check-pkg-deps --pkgs guiapp + - raco pkg install --auto cover cover-coveralls + - raco cover -b -f coveralls -d $TRAVIS_BUILD_DIR/coverage . diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..e0f01fa --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,13 @@ +Copyright 2020 spdegabrielle + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..beb5bf7 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,23 @@ +guiapp + +MIT License + +Copyright (c) 2020 spdegabrielle + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a4bac61 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +guiapp +====== +README text here. diff --git a/info.rkt b/info.rkt new file mode 100644 index 0000000..155287d --- /dev/null +++ b/info.rkt @@ -0,0 +1,8 @@ +#lang info +(define collection "guiapp") +(define deps '("base")) +(define build-deps '("scribble-lib" "racket-doc" "rackunit-lib")) +(define scribblings '(("scribblings/guiapp.scrbl" ()))) +(define pkg-desc "Description Here") +(define version "0.0") +(define pkg-authors '(spdegabrielle)) diff --git a/main.rkt b/main.rkt new file mode 100644 index 0000000..2729b6e --- /dev/null +++ b/main.rkt @@ -0,0 +1,136 @@ +#lang racket/gui +;; --------------------------------------------------------------------------------------------------- +(module+ test + (require rackunit)) + +;; Notice +;; To create an executable +;; $ raco exe -o hello hello.rkt +;; +;; see https://docs.racket-lang.org/raco/exe.html +;; +;; To share stand-alone executables: +;; $ raco distribute executable ... +;; +;; e.g +;; $ raco distribute greetings hello.exe +;; +;; creates a directory "greetings" (if the directory doesn’t exist already), +;; and it copies the executables "hello.exe" and "goodbye.exe" into "greetings". +;; +;; see https://docs.racket-lang.org/raco/exe-dist.html + + +;; This code is a modernised version of the code for the paper +;; Programming Languages as Operating Systems (1999) +;; https://www2.ccs.neu.edu/racket/pubs/icfp99-ffkf.pdf + +;; The repl editor class +(define esq-text% + (class text% + ;; lexical access to inherited methods: + (inherit insert last-position get-text erase) + ;; private fields: + (define prompt-pos 0) + (define locked? #t) + ;; override can-insert? to block pre-prompt inserts: + (define/augment can-insert? + (lambda (start len) + (and (>= start prompt-pos) (not locked?)))) + ;; override can-delete? to block pre-prompt deletes: + (define/augment can-delete? + (lambda (start end) + (and (>= start prompt-pos) (not locked?)))) + ;; override on-char to detect Enter/Return: + (define/override on-char + (lambda (c) + (super on-char c) + (when (and (eq? (send c get-key-code) + #\return) (not locked?)) + (set! locked? #t) + (evaluate + (get-text prompt-pos (last-position)))))) + ;; method to insert a new prompt + (define/public new-prompt + (lambda () + (queue-output (lambda () + (set! locked? #f) + (insert "> ") + (set! prompt-pos (last-position)))))) + ;; method to display output + (define/public output + (lambda (str) (queue-output (lambda () + (let ((was-locked? locked?)) + (set! locked? #f) + (insert str) + (set! locked? was-locked?)))))) + ;; method to reset the repl: + (define/public reset + (lambda () + (set! locked? #f) (set! prompt-pos 0) (erase) (new-prompt))) + ;; initialize superclass-defined state: + (super-new) + ;; create the initial prompt: + (new-prompt))) + +(define esq-eventspace (current-eventspace)) +(define (queue-output proc) + (parameterize ((current-eventspace esq-eventspace)) + (queue-callback proc #f))) ;; GUI creation +(define frame + (make-object frame% "SchemeEsq" #f 400 200)) +(define reset-button + (make-object button% "Reset" frame + (lambda (b e) (reset-program)))) +(define repl-editor (make-object esq-text%)) +(define repl-display-canvas + (make-object editor-canvas% frame)) +(send repl-display-canvas set-editor repl-editor) (send frame show #t) +;; User space initialization +(define user-custodian (make-custodian)) +(define user-output-port (make-output-port + 'eqs + always-evt + ;; string printer: + (lambda (bstr start end buffer? enable-break?) + (send repl-editor output (bytes->string/utf-8 bstr #\? start end)) + (- end start)) + ;; closer: + (lambda () 'nothing-to-close))) +(define user-eventspace + (parameterize ([current-custodian user-custodian] + [current-namespace (make-gui-namespace)]) + (make-eventspace))) +;; Evaluation and resetting +(define (evaluate expr-str) + (parameterize ((current-eventspace user-eventspace)) + (queue-callback (lambda () + (current-output-port user-output-port) + (with-handlers ((exn? + (lambda (exn) (display + (exn-message exn))))) + (println (eval (read (open-input-string expr-str))))) + (send repl-editor new-prompt))))) +(define (reset-program) + (custodian-shutdown-all user-custodian) + (set! user-custodian (make-custodian)) + (parameterize ([current-custodian user-custodian] + [current-namespace (make-gui-namespace)]) + (set! user-eventspace (make-eventspace))) + (send repl-editor reset)) + +;; + +(module+ test + ;; Any code in this `test` submodule runs when this file is run using DrRacket + ;; or with `raco test`. The code here does not run when this file is + ;; required by another module. + + (check-equal? (+ 2 2) 4)) + +(module+ main + ;; (Optional) main submodule. Put code here if you need it to be executed when + ;; this file is run using DrRacket or the `racket` executable. The code here + ;; does not run when this file is required by another module. Documentation: + ;; http://docs.racket-lang.org/guide/Module_Syntax.html#%28part._main-and-test%29 + (void)) diff --git a/scribblings/guiapp.scrbl b/scribblings/guiapp.scrbl new file mode 100644 index 0000000..872238a --- /dev/null +++ b/scribblings/guiapp.scrbl @@ -0,0 +1,10 @@ +#lang scribble/manual +@require[@for-label[guiapp + racket/base]] + +@title{guiapp} +@author{spdegabrielle} + +@defmodule[guiapp] + +Package Description Here