4 Racket API
4.1 Enigma API: Metadata
| (require enigma/metadata) | package: enigma-app |
Current value: enigma
Current value: 1.0.3
Current value: MPL-2.0
The source code of this module:
#lang racket/base (require racket/contract/base) (provide (contract-out [name string?] [version string?] [license string?])) (define name "enigma") (define version "1.0.3") (define license "MPL-2.0")
4.2 Enigma API: CLI Application
| (require enigma/app/cli) | package: enigma-app |
The source code of this module:
#lang racket/base (require json) (require racket/cmdline) (require racket/file) (require racket/match) (require threading) (require "../metadata.rkt") (require "../emacs/package/archives.rkt") (require "../emacs/system/run-emacs.rkt") (require "../subcommands/compile.rkt") (require "../subcommands/dependencies.rkt") (require "../subcommands/install.rkt") (require "../subcommands/launch.rkt") (require "../subcommands/test.rkt") (require "../log/simplelog.rkt") (require "../system/output/color.rkt") (require "../system/utils/path.rkt") (provide app-cli) (define (program-parameter/execution-directory/guard path) (define actual-path (~> path expand-user-path path->complete-path simplify-path)) (match actual-path [(? directory-exists? d) d] [(? file-exists? f) (path->directory f)] [_ (raise (exn:fail (format "Given path does not exist, given: ~v" actual-path) (current-continuation-marks)))])) (define (program-parameter/user-emacs-directory/guard path) (cond [path (~> path expand-user-path path->complete-path simplify-path path->string)] [else #false])) (define program-pseudo-parameter/extra-emacs-flags (make-parameter '())) (define program-parameter/execution-directory (make-parameter (current-directory) program-parameter/execution-directory/guard)) (define program-parameter/user-emacs-directory (make-parameter #false program-parameter/user-emacs-directory/guard)) (define (display-jsexpr jsexpr) (~>> jsexpr (jsexpr->string #:indent 2) displayln)) (define (call-for-exit procedure/arity2) (begin (define-values (result-code result-hash) (procedure/arity2 (program-parameter/execution-directory) (program-pseudo-parameter/extra-emacs-flags))) (display-jsexpr result-hash) (match result-hash [(list) (simplelog-error "No matching Emacs lisp files were found")] [_ (void)]) (exit result-code))) (define (run-action action emacs-flags) (parameterize ([current-directory (program-parameter/execution-directory)] [program-pseudo-parameter/extra-emacs-flags emacs-flags]) (simplelog-debug "Called with: action: ~v and emacs-flags: ~v" action emacs-flags) (simplelog-debug "Working in directory: ~a" (current-directory)) (define maybe-user-emacs-directory (program-parameter/user-emacs-directory)) (cond [maybe-user-emacs-directory (define emacs-directory-setup-expr `(progn (setq user-emacs-directory ,maybe-user-emacs-directory) (setq package-user-dir (expand-file-name "elpa" user-emacs-directory)))) (simplelog-debug "User's Emacs directory: ~a" maybe-user-emacs-directory) (make-directory* maybe-user-emacs-directory) (program-pseudo-parameter/extra-emacs-flags `("--eval" ,(format "~s" emacs-directory-setup-expr) ,@(program-pseudo-parameter/extra-emacs-flags)))] [else (void)]) (match action ['compile (call-for-exit compile-found-emacs-lisp-files)] ['dependencies (call-for-exit install-emacs-lisp-files-dependencies)] ['install (call-for-exit install-found-emacs-lisp-files)] ['launch (call-for-exit launch-with-found-emacs-lisp-files)] ['test (call-for-exit test-found-emacs-lisp-files)] [_ (raise (exn:fail (format "Unknown action, given: ~v" action) (current-continuation-marks)))]))) (define (subcommand/dependencies argv) (command-line #:program "enigma dependencies" #:argv argv #:multi [("--clear-package-archives") "Clear the Emacs package-archives of any records" (parameter/emacs-package-archives '())] [("--add-package-archive") package-archive-url "Register a package-archive record" (parameter/emacs-package-archives (cons package-archive-url (parameter/emacs-package-archives)))] #:args emacs-flags (run-action 'dependencies emacs-flags))) (define (subcommand/compile argv) (command-line #:program "enigma compile" #:argv argv #:args emacs-flags (run-action 'compile emacs-flags))) (define (subcommand/test argv) (command-line #:program "enigma test" #:argv argv #:once-each [("--buttercup-exe") buttercup-exe "Set a custom Buttercup executable path" (parameter/buttercup-executable buttercup-exe)] [("--ert-runner-exe") ert-runner-exe "Set a custom ERT-Runner executable path" (parameter/ert-runner-executable ert-runner-exe)] #:args emacs-flags (run-action 'test emacs-flags))) (define (subcommand/launch argv) (command-line #:program "enigma launch" #:argv argv #:args emacs-flags (run-action 'launch emacs-flags))) (define (subcommand/install argv) (command-line #:program "enigma install" #:argv argv #:multi [("--clear-package-archives") "Clear the Emacs package-archives of any records" (parameter/emacs-package-archives '())] [("--add-package-archive") package-archive-url "Register a package-archive record" (parameter/emacs-package-archives (cons package-archive-url (parameter/emacs-package-archives)))] #:args emacs-flags (run-action 'install emacs-flags))) (define (app-cli argv) (command-line #:program name #:argv argv #:usage-help "requires a subcommand, one of: compile, dependencies, install, launch or test" #:ps " Available subcommands: - compile - compile found Emacs Lisp files, - dependencies - install Emacs Lisp files' dependencies (\"Package-Requires\"), - install - install (suitable) Emacs Lisp files as packages (their parent dir), - launch - launch GNU Emacs in a prepared environment, - test - run found Emacs Lisp tests (supports: ert, ert-runner or buttercup). Original author: Maciej xgqt Barć. Licensed under the permissive copyleft MPL-2.0 license (http://mozilla.org/MPL/2.0/). No warranty. " #:once-each [("-V" "--version") "Show the program's currently used version" (begin (displayln version) (exit 0))] [("--license") "Show the program's license" (begin (displayln license) (exit 0))] [("-C" "--directory") directory "Change to directory directory before doing anything else" (program-parameter/execution-directory directory)] [("--no-color") "Suppress displaying colors by the program" (parameter/colored-output? #false)] [("--user-emacs-directory") directory "Overwrite the user's Emacs directory" (program-parameter/user-emacs-directory directory)] [("--emacs-exe") emacs-exe "Set a custom GNU Emacs executable path" (parameter/emacs-executable emacs-exe)] #:args (subcommand . subcommand-arguments) (match subcommand [(or "subcommands") (displayln "Available subcommands:") (for ([s '("compile" "dependencies" "install" "launch" "test")]) (printf " - ~a\n" s))] [(or "compile" "com" "c") (subcommand/compile subcommand-arguments)] [(or "dependencies" "deps" "d") (subcommand/dependencies subcommand-arguments)] [(or "install" "inst" "i") (subcommand/install subcommand-arguments)] [(or "launch" "l") (subcommand/launch subcommand-arguments)] [(or "test" "t") (subcommand/test subcommand-arguments)] [_ (raise (exn:fail (format "Unknown subcommand, given: ~v" subcommand) (current-continuation-marks)))])))
4.3 Enigma API: Compile Subcommand
| (require enigma/subcommands/compile) | package: enigma-app |
procedure
(compile-found-emacs-lisp-files start-path extra-emacs-flags)
→
exact-integer? (listof hash?) start-path : path-string? extra-emacs-flags : (listof string?)
Returns the values that indicate: exact-integer? total compilation success and a list of objects that describe properties of compiled files.
The source code of this module:
#lang racket/base (require racket/contract/base) (require racket/match) (require "../emacs/file/emacs-context.rkt") (require "../emacs/path/load-path.rkt") (require "../emacs/system/run-emacs.rkt") (require "../system/utils/path.rkt") (require "../system/utils/time.rkt") (require "../log/simplelog.rkt") (require "../compiler/stamp/stamp.rkt") (provide (contract-out [compile-found-emacs-lisp-files (-> path-string? (listof string?) (values exact-integer? (listof hash?)))])) (define (compile-emacs-lisp-file/inner file-path load-path extra-emacs-flags) (define cmdline-args (append (make-emacs-cmdline-args load-path extra-emacs-flags) `("-batch" "-f" "batch-byte-compile" ,(path->string file-path)))) (define exit-code (run-emacs cmdline-args)) (match exit-code [0 (create-stamp file-path "compiled")] [_ (void)]) exit-code) (define (compile-emacs-lisp-file file-path load-path extra-emacs-flags) (cond [(stamp-actual? file-path "compiled") (simplelog-debug "Skipping up-to-date file: ~a" (path->name file-path)) 0] [else (define name (path->name file-path)) (with-time-report #:announce (lambda () (simplelog-info "Compiling ~a" name)) #:report (lambda (elapsed) (simplelog-debug "Compilation of ~a took ~ams" name elapsed)) #:thunk (lambda () (compile-emacs-lisp-file/inner file-path load-path extra-emacs-flags)))])) (define (compile-found-emacs-lisp-files start-path extra-emacs-flags) (define result-code (make-parameter 0)) (define-values (emacs-lisp-files load-path) (find-emacs-lisp-context start-path)) (define sources-count (length emacs-lisp-files)) (define result-hash (for/list ([emacs-lisp-file emacs-lisp-files] [i (in-naturals 1)]) (simplelog-status i sources-count "compile-emacs-lisp-file ~a" emacs-lisp-file) (define exit-code (compile-emacs-lisp-file emacs-lisp-file load-path extra-emacs-flags)) (define successful? (= 0 exit-code)) (define compiled-file (match successful? [#true (match (path-replace-extension emacs-lisp-file #".elc") [(? file-exists? f) (path->string f)] [_ #false])] [_ #false])) (define h (hash 'compiled-file compiled-file 'exit-code exit-code 'file-path (path->string emacs-lisp-file) 'successful? successful?)) (when (not successful?) (result-code exit-code)) h)) (values (result-code) result-hash))
4.4 Enigma API: Dependencies Subcommand
| (require enigma/subcommands/dependencies) | |
| package: enigma-app | |
procedure
(install-emacs-lisp-files-dependencies start-path extra-emacs-flags)
→
exact-integer? (listof hash?) start-path : path-string? extra-emacs-flags : (listof string?)
Returns the values that indicate: exact-integer? total installation success and a list of objects that describe properties of installed dependencies.
The source code of this module:
#lang racket/base (require racket/contract/base) (require "../emacs/file/content-guess.rkt") (require "../emacs/file/emacs-context.rkt") (require "../emacs/package/archives.rkt") (require "../emacs/path/load-path.rkt") (require "../emacs/system/run-emacs.rkt") (require "../log/simplelog.rkt") (require "../system/utils/time.rkt") (provide (contract-out [install-emacs-lisp-files-dependencies (-> path-string? (listof string?) (values exact-integer? (listof hash?)))])) (define (install-remote-emacs-package package-name extra-emacs-flags) (define package-bootstrap-expr `(progn (setq package-archives (quote ,(get-emacs-package-archives))) (package-initialize) (package-install (quote ,package-name)))) (define cmdline-args (append (make-emacs-cmdline-args '() extra-emacs-flags) `("-batch" "--eval" ,(format "~s" package-bootstrap-expr)))) (define exit-code (with-time-report #:announce (lambda () (simplelog-success "Installing dependency ~a" package-name)) #:report (lambda (elapsed) (simplelog-debug "Installing dependency ~a took ~ams" package-name elapsed)) #:thunk (lambda () (run-emacs cmdline-args)))) (when (= 0 exit-code) (simplelog-success "Install of remote package ~v succeeded" package-name)) exit-code) (define (install-emacs-lisp-files-dependencies start-path extra-emacs-flags) (define result-code (make-parameter 0)) (define-values (emacs-lisp-files _load-path) (find-emacs-lisp-context start-path)) (define refresh-result (refresh-emacs-package-archives extra-emacs-flags)) (when (> refresh-result 0) (result-code refresh-result)) (define sources (for/fold ([results '()]) ([emacs-lisp-file emacs-lisp-files]) (define version (guess-file-version emacs-lisp-file)) (define dependencies (guess-file-dependencies emacs-lisp-file)) (cond [(and version (not (null? dependencies))) (cons (cons emacs-lisp-file dependencies) results)] [else results]))) (define sources-count (length sources)) (define result-hash (for/list ([emacs-lisp-pair (reverse sources)] [i (in-naturals 1)]) (define emacs-lisp-file (car emacs-lisp-pair)) (define dependencies (cdr emacs-lisp-pair)) (simplelog-status i sources-count "install-remote-emacs-package ~a" emacs-lisp-file) (simplelog-debug "Found dependencies: ~v in file ~a" dependencies emacs-lisp-file) (define exit-codes (for/list ([package-name dependencies]) (install-remote-emacs-package package-name extra-emacs-flags))) (define first-failure-exit-code (for/first ([exit-code exit-codes] #:when (> exit-code 0)) exit-code)) (define successful? (not first-failure-exit-code)) (when (not successful?) (result-code first-failure-exit-code)) (hash 'dependencies (format "~s" dependencies) 'file-path (path->string emacs-lisp-file) 'successful? successful?))) (values (result-code) result-hash))
4.5 Enigma API: Install Subcommand
| (require enigma/subcommands/install) | package: enigma-app |
procedure
(install-found-emacs-lisp-files start-path extra-emacs-flags)
→
exact-integer? (listof hash?) start-path : path-string? extra-emacs-flags : (listof string?)
Returns the values that indicate: exact-integer? total installation success and a list of objects that describe properties of installed files.
The source code of this module:
#lang racket/base (require racket/contract/base) (require racket/match) (require "../emacs/file/emacs-context.rkt") (require "../emacs/path/load-path.rkt") (require "../emacs/system/run-emacs.rkt") (require "../system/utils/path.rkt") (require "../system/utils/time.rkt") (require "../log/simplelog.rkt") (require "../compiler/stamp/stamp.rkt") (provide (contract-out [compile-found-emacs-lisp-files (-> path-string? (listof string?) (values exact-integer? (listof hash?)))])) (define (compile-emacs-lisp-file/inner file-path load-path extra-emacs-flags) (define cmdline-args (append (make-emacs-cmdline-args load-path extra-emacs-flags) `("-batch" "-f" "batch-byte-compile" ,(path->string file-path)))) (define exit-code (run-emacs cmdline-args)) (match exit-code [0 (create-stamp file-path "compiled")] [_ (void)]) exit-code) (define (compile-emacs-lisp-file file-path load-path extra-emacs-flags) (cond [(stamp-actual? file-path "compiled") (simplelog-debug "Skipping up-to-date file: ~a" (path->name file-path)) 0] [else (define name (path->name file-path)) (with-time-report #:announce (lambda () (simplelog-info "Compiling ~a" name)) #:report (lambda (elapsed) (simplelog-debug "Compilation of ~a took ~ams" name elapsed)) #:thunk (lambda () (compile-emacs-lisp-file/inner file-path load-path extra-emacs-flags)))])) (define (compile-found-emacs-lisp-files start-path extra-emacs-flags) (define result-code (make-parameter 0)) (define-values (emacs-lisp-files load-path) (find-emacs-lisp-context start-path)) (define sources-count (length emacs-lisp-files)) (define result-hash (for/list ([emacs-lisp-file emacs-lisp-files] [i (in-naturals 1)]) (simplelog-status i sources-count "compile-emacs-lisp-file ~a" emacs-lisp-file) (define exit-code (compile-emacs-lisp-file emacs-lisp-file load-path extra-emacs-flags)) (define successful? (= 0 exit-code)) (define compiled-file (match successful? [#true (match (path-replace-extension emacs-lisp-file #".elc") [(? file-exists? f) (path->string f)] [_ #false])] [_ #false])) (define h (hash 'compiled-file compiled-file 'exit-code exit-code 'file-path (path->string emacs-lisp-file) 'successful? successful?)) (when (not successful?) (result-code exit-code)) h)) (values (result-code) result-hash))
4.6 Enigma API: Launch Subcommand
| (require enigma/subcommands/launch) | package: enigma-app |
procedure
(launch-with-found-emacs-lisp-files start-path extra-emacs-flags)
→
exact-integer? (listof hash?) start-path : path-string? extra-emacs-flags : (listof string?)
Returns the values that indicate: exact-integer? total launch success and a list of objects that describe properties of used files.
The source code of this module:
#lang racket/base (require racket/contract/base) (require "../emacs/file/emacs-context.rkt") (require "../emacs/path/load-path.rkt") (require "../emacs/system/run-emacs.rkt") (require "../log/simplelog.rkt") (provide (contract-out [launch-with-found-emacs-lisp-files (-> path-string? (listof string?) (values exact-integer? (listof hash?)))])) (define (launch-with-found-emacs-lisp-files start-path extra-emacs-flags) (define-values (emacs-lisp-files load-path) (find-emacs-lisp-context start-path)) (define cmdline-args (make-emacs-cmdline-args load-path extra-emacs-flags)) (simplelog-debug "Launching from: ~a" start-path) (define exit-code (run-emacs cmdline-args)) (define result-hash (for/list ([emacs-lisp-file emacs-lisp-files]) (hash 'file-path (path->string emacs-lisp-file)))) (values exit-code result-hash))
4.7 Enigma API: Test Subcommand
| (require enigma/subcommands/test) | package: enigma-app |
procedure
(test-found-emacs-lisp-files start-path extra-emacs-flags)
→
exact-integer? (listof hash?) start-path : path-string? extra-emacs-flags : (listof string?)
Returns the values that indicate: exact-integer? total test success and a list of objects that describe properties of tested files.
The source code of this module:
#lang racket/base (require racket/contract/base) (require racket/match) (require threading) (require "../emacs/file/content-guess.rkt") (require "../emacs/file/emacs-context.rkt") (require "../emacs/path/load-path.rkt") (require "../emacs/system/run-emacs.rkt") (require "../system/utils/path.rkt") (require "../system/utils/time.rkt") (require "../log/simplelog.rkt") (require "../compiler/stamp/stamp.rkt") (provide (contract-out [test-found-emacs-lisp-files (-> path-string? (listof string?) (values exact-integer? (listof hash?)))])) (define (test-emacs-lisp-file/inner file-path load-path extra-emacs-flags) (define test-runner (guess-file-test-runner file-path)) (define exit-code (match test-runner ['ert (define cmdline-args (append (make-emacs-cmdline-args load-path extra-emacs-flags) `("-batch" ,(~> file-path path->directory path->string) "-l" ,(path->string file-path) "-f" "ert-run-tests-batch-and-exit"))) (run-emacs cmdline-args)] ['ert-runner (define cmdline-args (append (make-emacs-cmdline-args load-path extra-emacs-flags) (~> file-path path->string list))) (run-ert-runner cmdline-args)] ['buttercup (define cmdline-args (append (make-emacs-cmdline-args load-path extra-emacs-flags) (~> file-path path->directory path->string list))) (run-buttercup cmdline-args)] [_ (raise (exn:fail (format "Unknown test runner, given: ~v" test-runner) (current-continuation-marks)))])) (match exit-code [0 (create-stamp file-path "tested")] [_ (void)]) exit-code) (define (test-emacs-lisp-file file-path load-path extra-emacs-flags) (cond [(stamp-actual? file-path "tested") (simplelog-debug "Skipping up-to-date file: ~a" (path->name file-path)) 0] [else (define name (path->name file-path)) (with-time-report #:announce (lambda () (simplelog-info "Testing ~a" name)) #:report (lambda (elapsed) (simplelog-debug "Test of ~a took ~ams" name elapsed)) #:thunk (lambda () (test-emacs-lisp-file/inner file-path load-path extra-emacs-flags)))])) (define (emacs-lisp-test-file? file-path) (define name (path->name file-path)) (and (not (regexp-match #rx"^test(s|)-helper\\.el$" name)) (or (regexp-match #rx"^test(s|)-.*\\.el$" name) (regexp-match #rx".*-test(s|)\\.el$" name)))) (define (test-found-emacs-lisp-files start-path extra-emacs-flags) (define result-code (make-parameter 0)) (define-values (emacs-lisp-files load-path) (find-emacs-lisp-context start-path)) (define sources (filter emacs-lisp-test-file? emacs-lisp-files)) (define sources-count (length sources)) (define result-hash (for/list ([emacs-lisp-file sources] [i (in-naturals 1)]) (simplelog-status i sources-count "test-emacs-lisp-file ~a" emacs-lisp-file) (define exit-code (test-emacs-lisp-file emacs-lisp-file load-path extra-emacs-flags)) (define successful? (= 0 exit-code)) (define h (hash 'exit-code exit-code 'file-path (path->string emacs-lisp-file) 'successful? successful?)) (when (not successful?) (result-code exit-code)) h)) (values (result-code) result-hash))
4.8 Enigma API: Stamp
| (require enigma/compiler/stamp/stamp) | package: enigma-app |
procedure
(create-stamp file-path stamp-type) → hash?
file-path : path-string? stamp-type : string?
Returns a hash with stamp data.
procedure
(stamp-actual? file-path stamp-type) → boolean?
file-path : path-string? stamp-type : string?
Returns #true when the stamp exists and its recorded file size and modification time match the file values.
The source code of this module:
#lang racket/base (require racket/contract/base) (require racket/file) (require json) (require threading) (require "../../log/simplelog.rkt") (require "../../system/utils/path.rkt") (provide (contract-out [create-stamp (-> path-string? string? hash?)] [stamp-actual? (-> path-string? string? boolean?)])) (define (get-stamp-path file-path stamp-type) (define stamp-file-name (~> file-path path->name (path-replace-extension _ (format ".~a.stamp" stamp-type)))) (define stamp-file-directory (~> file-path path->directory (build-path _ ".cache"))) (define stamp-file-path (~> stamp-file-directory (build-path _ stamp-file-name))) (values stamp-file-path stamp-file-directory stamp-file-name)) (define (create-stamp file-path stamp-type) (define-values (stamp-path dir name) (get-stamp-path file-path stamp-type)) (define source-size (file-size file-path)) (define source-time (file-or-directory-modify-seconds file-path)) (define creation-time (current-seconds)) (define stamp-data (hash 'creation-time creation-time 'source-size source-size 'source-time source-time)) (simplelog-debug "Creating stamp: ~a" name) (make-directory* dir) (call-with-output-file stamp-path #:exists 'replace #:mode 'text (lambda (out) (displayln (jsexpr->string stamp-data) out))) stamp-data) (define read-stamp (lambda~> file->string string->jsexpr)) (define (stamp-actual? file-path stamp-type) (define-values (stamp-path _dir _name) (get-stamp-path file-path stamp-type)) (cond [(file-exists? stamp-path) (define stamp-data (read-stamp stamp-path)) (and stamp-data (= (hash-ref stamp-data 'source-size) (file-size file-path)) (= (hash-ref stamp-data 'source-time) (file-or-directory-modify-seconds file-path)))] [else #false]))
4.9 Enigma API: Content Guess
| (require enigma/emacs/file/content-guess) | |
| package: enigma-app | |
procedure
(guess-file-test-runner file-path) → symbol?
file-path : path-string?
Returns 'ert, 'ert-runner, 'buttercup or 'none.
procedure
(guess-file-dependencies file-path) → (listof symbol?)
file-path : path-string?
Returns a list of symbols representing package dependencies.
procedure
(guess-file-version file-path) → (or/c string? #false)
file-path : path-string?
Returns a version string or #false.
The source code of this module:
#lang racket/base (require racket/contract/base) (require racket/file) (require racket/match) (require racket/string) (require threading) (require "../../system/utils/path.rkt") (provide (contract-out [guess-file-test-runner (-> path-string? symbol?)] [guess-file-dependencies (-> path-string? (listof symbol?))] [guess-file-version (-> path-string? (or/c string? #false))])) (define (guess-file-test-runner file-path) (cond [(~> file-path path->directory (build-path "test-helper.el") file-exists?) 'ert-runner] [else (define content (file->string file-path)) (match content [(regexp #rx"\\(require 'ert") 'ert] [(regexp #rx"\\(ert-deftest ") 'ert] [(regexp #rx"\\(require 'buttercup") 'buttercup] [(regexp #rx"\\(describe ") 'buttercup] [_ 'none])])) (define (guess-file-dependencies file-path) (define maybe-deps (for/or ([line (file->lines file-path)]) (match line [(regexp #rx"^;; Package-Requires: \\(.+\\)" (list matched)) ;; FIXME: A little fragile, maybe reimplement. (~> matched (regexp-replace ";; Package-Requires:" _ "") string-trim open-input-string ; "((emacs \"26.3\") (s \"0.2\"))" read ; ((emacs "26.3") (s "0.2")) (map car _) ; (emacs s) (filter (lambda (pkg-name) (match pkg-name [(or 'emacs 'seq) #false] [_ #true])) _))] [_ #false]))) (cond [maybe-deps] [else '()])) (define (guess-file-version file-path) (for/or ([line (file->lines file-path)]) (match line [(regexp #rx"^;; Version: .*" (list matched)) (~> matched (regexp-replace ";; Version:" _ "") string-trim)] [(regexp #rx"^;; Package-Version: .*" (list matched)) (~> matched (regexp-replace ";; Package-Version:" _ "") string-trim)] [_ #false])))
4.10 Enigma API: File Context
| (require enigma/emacs/file/emacs-context) | |
| package: enigma-app | |
procedure
(similar-emacs-lisp-name? emacs-lisp-path supposed-path) → boolean? emacs-lisp-path : path-string? supposed-path : path-string?
procedure
(find-likely-emacs-lisp-segments file-path) → (listof path?)
file-path : path-string?
procedure
(guess-load-path emacs-lisp-files) → (listof path?)
emacs-lisp-files : (listof path?)
procedure
(find-emacs-lisp-context start-path)
→
(listof path?) (listof path?) start-path : path-string?
The source code of this module:
#lang racket/base (require racket/contract/base) (require racket/list) (require racket/set) (require threading) (require "../../system/utils/find.rkt") (require "../../system/utils/path.rkt") (provide (contract-out [similar-emacs-lisp-name? (-> path-string? path-string? boolean?)] [find-likely-emacs-lisp-segments (-> path-string? (listof path?))] [guess-load-path (-> (listof path?) (listof path?))] [find-emacs-lisp-context (-> path-string? (values (listof path?) (listof path?)))])) (define (similar-emacs-lisp-name? emacs-lisp-path supposed-path) (define lisp-name (path->name emacs-lisp-path)) (define lispy-name (regexp-replace #rx"\\.el$" lisp-name "")) (define path-name (path->name supposed-path)) (cond [(~> (string-append "^" lispy-name "(_|-).*") regexp (regexp-match path-name) (and #true))] [(~> (string-append ".*(_|-)" lispy-name "$") regexp (regexp-match path-name) (and #true))] [(~> (string-append ".*(_|-)" lisp-name "$") regexp (regexp-match path-name) (and #true))] [(equal? lispy-name path-name)] [(equal? lisp-name path-name)] [else #false])) (define (find-likely-emacs-lisp-segments file-path) (for/list ([path (make-paths-tree file-path)] #:when (similar-emacs-lisp-name? file-path path)) path)) (define (guess-load-path emacs-lisp-files) (~> emacs-lisp-files (map find-likely-emacs-lisp-segments _) flatten list->set set->list (filter directory-exists? _))) (define (file-hidden-directory? file-path start-path) (define full-path-segments (path-segments file-path)) (define start-path-segments (path-segments start-path)) (define only-relative-segments (~> start-path-segments length (list-tail full-path-segments _))) (define relative-directory-segments (drop-right only-relative-segments 1)) (ormap (lambda~> path->string (regexp-match-exact? #rx"^\\..*" _)) relative-directory-segments)) (define (find-emacs-lisp-context start-path) (define emacs-lisp-files (find-emacs-lisp-files start-path)) (define load-path (guess-load-path emacs-lisp-files)) (define non-hidden-files (filter (lambda~> (file-hidden-directory? _ start-path) not) emacs-lisp-files)) (values non-hidden-files load-path))
4.11 Enigma API: Emacs Package Archives
| (require enigma/emacs/package/archives) | |
| package: enigma-app | |
parameter
→ (or/c #false (listof string?)) (parameter/emacs-package-archives archive-list) → void? archive-list : (or/c #false (listof string?))
When set to #false, the default archives list is used.
procedure
Uses the value of parameter/emacs-package-archives if set, otherwise uses the default archives.
procedure
(refresh-emacs-package-archives extra-emacs-flags)
→ exact-integer? extra-emacs-flags : (listof string?)
Returns an exit code, 0 on success.
The source code of this module:
#lang racket/base (require racket/contract/base) (require racket/match) (require threading) (require "../../log/simplelog.rkt") (require "../path/load-path.rkt") (require "../system/run-emacs.rkt") (provide (contract-out [parameter/emacs-package-archives (parameter/c (or/c #false (listof string?)))] [get-emacs-package-archives (-> list?)] [refresh-emacs-package-archives (-> (listof string?) exact-integer?)])) (define parameter/emacs-package-archives (make-parameter #false)) (define default-emacs-package-archives-list '("https://tromey.com/elpa/" "https://elpa.gnu.org/packages/" "https://melpa.org/packages/")) (define make-archive-name (lambda~> (regexp-replace #rx"^http(s)://" _ "") (regexp-replace #rx"/.*$" _ "") (regexp-replace* #rx"\\." _ "-"))) (define (make-emacs-package-archives archives-list) (for/list ([archive-url archives-list]) (define archive-name (make-archive-name archive-url)) (cons archive-name archive-url))) (define (get-emacs-package-archives) (match (parameter/emacs-package-archives) [#false (make-emacs-package-archives default-emacs-package-archives-list)] [emacs-package-archives (make-emacs-package-archives emacs-package-archives)])) (define (refresh-emacs-package-archives-expr) `(progn (require 'package) (setq package-archives (quote ,(get-emacs-package-archives))) (message " Package user dir: %s" package-user-dir) (message " Initializing package database...") (package-initialize) (message " Refreshing package archives...") (package-refresh-contents))) (define (refresh-emacs-package-archives extra-emacs-flags) (define cmdline-args (append (make-emacs-cmdline-args '() extra-emacs-flags) `("-batch" "--eval" ,(format "~s" (refresh-emacs-package-archives-expr))))) (simplelog-debug "Refreshing Emacs packages") (define exit-code (run-emacs cmdline-args)) (when (= 0 exit-code) (simplelog-success "Refresh of Emacs packages succeeded")) exit-code)
4.12 Enigma API: Load Path
| (require enigma/emacs/path/load-path) | package: enigma-app |
procedure
(make-emacs-cmdline-args load-path-dirs extra-emacs-flags) → (listof string?) load-path-dirs : (listof path-string?) extra-emacs-flags : (listof string?)
The source code of this module:
#lang racket/base (require racket/contract/base) (require racket/match) (provide (contract-out [make-emacs-cmdline-args (-> (listof path-string?) (listof string?) (listof string?))])) (define (make-emacs-cmdline-args load-path-dirs extra-emacs-flags) (define load-flags (for/fold ([args '()]) ([load-path-dir load-path-dirs]) `(,@args "-L" ,(match load-path-dir [(? string? s) s] [p (path->string p)])))) (append load-flags extra-emacs-flags))
4.13 Enigma API: Run Emacs
| (require enigma/emacs/system/run-emacs) | |
| package: enigma-app | |
parameter
(parameter/emacs-executable executable-name-or-path) → void? executable-name-or-path : string?
Defaults to "emacs".
parameter
(parameter/buttercup-executable executable-name-or-path) → void? executable-name-or-path : string?
Defaults to "buttercup".
parameter
(parameter/ert-runner-executable executable-name-or-path) → void? executable-name-or-path : string?
Defaults to "ert-runner".
procedure
(run-emacs args) → exact-integer?
args : (listof string?)
Returns the exit code.
procedure
(run-buttercup args) → exact-integer?
args : (listof string?)
Returns the exit code.
procedure
(run-ert-runner args) → exact-integer?
args : (listof string?)
Returns the exit code.
The source code of this module:
#lang racket/base (require racket/contract/base) (require racket/string) (require racket/system) (require "../../log/simplelog.rkt") (provide (contract-out [parameter/emacs-executable (parameter/c string?)] [parameter/buttercup-executable (parameter/c string?)] [parameter/ert-runner-executable (parameter/c string?)] [run-emacs (-> (listof string?) exact-integer?)] [run-buttercup (-> (listof string?) exact-integer?)] [run-ert-runner (-> (listof string?) exact-integer?)])) (define parameter/emacs-executable (make-parameter "emacs")) (define parameter/buttercup-executable (make-parameter "buttercup")) (define parameter/ert-runner-executable (make-parameter "ert-runner")) (define (run-emacs args) (define emacs-exe-path (find-executable-path (parameter/emacs-executable))) (when (not emacs-exe-path) (raise (exn:fail "Could not find any GNU Emacs executable" (current-continuation-marks)))) (define cmd-args (append (list "-q" "--no-site-file") args)) (simplelog-debug "Executing: ~a ~a" emacs-exe-path (string-join cmd-args " ")) (apply system*/exit-code emacs-exe-path cmd-args)) (define (run-buttercup args) (define buttercup-exe-path (find-executable-path (parameter/buttercup-executable))) (when (not buttercup-exe-path) (raise (exn:fail "Could not find buttercup executable" (current-continuation-marks)))) (define cmd-args (append '("--traceback" "full") args)) (simplelog-debug "Executing: ~a ~a" buttercup-exe-path (string-join cmd-args " ")) (apply system*/exit-code buttercup-exe-path cmd-args)) (define (run-ert-runner args) (define ert-runner-exe-path (find-executable-path (parameter/ert-runner-executable))) (when (not ert-runner-exe-path) (raise (exn:fail "Could not find ert-runner executable" (current-continuation-marks)))) (define cmd-args (append '("--reporter" "ert+duration" "--script") args)) (simplelog-debug "Executing: ~a ~a" ert-runner-exe-path (string-join cmd-args " ")) (apply system*/exit-code ert-runner-exe-path cmd-args))
4.14 Enigma API: Find System Utils
| (require enigma/system/utils/find) | package: enigma-app |
procedure
(emacs-lisp-file? file-path) → boolean?
file-path : path-string?
procedure
(find-emacs-lisp-files start-path) → (listof path?)
start-path : path-string?
The source code of this module:
#lang racket/base (require racket/contract/base) (require racket/file) (require threading) (require "../../system/utils/path.rkt") (provide (contract-out [emacs-lisp-file? (-> path-string? boolean?)] [find-emacs-lisp-files (-> path-string? (listof path?))])) (define emacs-lisp-file? (lambda~> expand-user-path path->complete-path simplify-path path->string ((lambda (p) (and ;; Matches "*.el". (~> p (regexp-match #rx"\\.el$" _) (and #true)) ;; Is not a dir. (not (directory-exists? p)) ;; Is not hidden. (~> p path->name (regexp-match #rx"^\\." _) not))) _))) (define find-emacs-lisp-files (lambda~> expand-user-path path->complete-path (simplify-path #true) (find-files emacs-lisp-file? #:follow-links? #true _)))
4.15 Enigma API: Path System Utilities
| (require enigma/system/utils/path) | package: enigma-app |
procedure
(path-segments file-path) → (listof path?)
file-path : path-string?
procedure
(make-paths-tree file-path) → (listof path?)
file-path : path-string?
procedure
(path->directory file-path) → path?
file-path : path-string?
procedure
(path->name file-path) → string?
file-path : path-string?
The source code of this module:
#lang racket/base (require racket/contract/base) (require racket/list) (require threading) (provide (contract-out [path-segments (-> path-string? (listof path?))] [make-paths-tree (-> path-string? (listof path?))] [path->directory (-> path-string? path?)] [path->name (-> path-string? string?)])) (define path-segments (lambda~> expand-user-path path->complete-path simplify-path explode-path)) (define (make-paths-tree file-path) (for/fold ([paths '()]) ([path-segment (path-segments file-path)]) (cond [(null? paths) (list path-segment)] [else (define last-used-path (car paths)) (cons (build-path last-used-path path-segment) paths)]))) (define path->directory (lambda~> path-segments reverse cdr reverse (apply build-path _))) (define path->name (lambda~> path-segments last path->string))
4.16 Enigma API: Time Util
| (require enigma/system/utils/time) | package: enigma-app |
procedure
(with-time-report #:announce pre-report-function #:report report-function #:thunk thunk-function) → any? pre-report-function : (-> any) report-function : (-> exact-integer? any) thunk-function : (-> any)
Before calling the thunk, pre-report-function is invoked as an announcement.
After the thunk completes, the elapsed time in milliseconds is reported to report-function.
The return value is the result of thunk-function.
The source code of this module:
#lang racket/base (require racket/contract/base) (require threading) (provide (contract-out [with-time-report (-> #:announce (-> any) #:report (-> exact-integer? any) #:thunk (-> any) any)])) (define (with-time-report #:announce [pre-report-function void] #:report [report-function void] #:thunk [thunk-function void]) (define start-time-milliseconds (current-milliseconds)) (dynamic-wind (lambda () (pre-report-function)) (lambda () (thunk-function)) (lambda () (define stop-time-milliseconds (current-milliseconds)) (~> (- stop-time-milliseconds start-time-milliseconds) report-function))))