Emacs Eask
GitHubDiscordToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage
Edit page

Development API

This document provides a reference to the public Eask API, which you may use in your projects and extensions to Eask.

🚩 Entry Point

πŸ” Snippet: _prepare.el

Load lisp/_prepare.el to start using other Eask API.

(let ((dir (file-name-directory (nth 1 (member "-scriptload" command-line-args)))))
  (load (expand-file-name "_prepare.el"
                          (locate-dominating-file dir "_prepare.el"))
        nil t))

Each Elisp scripts should have this snippet at the very top of the file.

πŸ” Macro: eask-start (&rest body)

Command entry point. Each command file should contain this macro somewhere in the file.

  ;; TODO: design your command here!

🚩 Environment

πŸ” Variable: eask-has-colors

Return non-nil if the terminal supports colors.

(when eask-has-colors ...

πŸ” Variable: eask-homedir

Eask’s home directory path.

(message "%s" eask-homedir)

πŸ” Variable: eask-invocation

Eask’s invocation program path.

(message "%s" eask-invocation)

It could be the node executable or the eask executable itself.

πŸ” Variable: eask-is-pkg

Return non-nil if Eask is packaged.

(when eask-is-pkg ...

πŸ” Variable: eask-rest

Eask’s arguments after command separator `–’; return a list.

$ eask <command> -- args0 args1


(message "%s" eask-rest)  ; '(args0 args1)

πŸ” Function: eask-rest ()

Eask’s arguments after command separator `–’; return a string.

$ eask <command> -- args0 args1


(message "%s" (eask-rest))  ; "args0 args1"

🚩 Core

πŸ” Variable: eask-lisp-root

Points to lisp directory from the project root.

(message "%s" eask-lisp-root)  ; path/to/eask/cli/lisp/

πŸ” Function: eask-working-directory ()

Return the working directory of the program going to be executed.

(message "%s" (eask-working-directory))  ; path/to/current/work/space/

πŸ” Function: eask-command ()

Return the current command in string. Suppose the command is:

$ eask init


(message "%s" (eask-command))  ; init

πŸ” Function: eask-command-p (commands)

Return t if COMMANDS is the current command.

πŸ” Function: eask-special-p ()

Return t if the command that can be run without Eask-file existence.

This allows some commands can still be executed without defining the user directory. This can be handy when you want to do normal operations without touching the user directory.

πŸ” Function: eask-execution-p ()

Return t if the command is the execution command.

This is added because we don’t want to pollute error and warn functions.

πŸ” Function: eask-checker-p ()

Return t if running Eask as the checker.

Without this flag, the process will be terminated once the error is occurred. This flag allows you to run through operations without reporting errors.

πŸ” Function: eask-script (script)

Return full script filename.

(eask-script "extern/pacakge")  ; {project-root}/lisp/extern/package.el

πŸ” Function: eask-load (script)

Load another eask script.

(eask-load "extern/ansi")  ; load {project-root}/lisp/extern/ansi.el file

πŸ” Function: eask-call (script)

Call another eask script.

(eask-call "clean/elc")  ; call command `eask clean-elc`
πŸ’‘ We don’t often call this since we don’t wish to execute another command directly!

πŸ” Function: eask-import (url)

Load and evaluate the script from the url.

(eask-import "https://raw.githubusercontent.com/emacsmirror/emacswiki.org/master/yes-no.el")

;; The script will be available after the call!

πŸ” Macro: eask-defvc< (version &rest body)

Define the scope if the Emacs version is below a specific version.

VERSION is an integer and will be compared with emacs-major-version.

(eask-defvc< 28
  ;; This is missing before Emacs 28; define it
  (defvar package-native-compile nil))
πŸ’‘ This is used for Emacs compatibility!

πŸ” Macro: eask–silent (&rest body)

Mute all messages from standard output inside the scope.

(eask--unsilent (message "You can't hear me! :("))

πŸ” Macro: eask–unsilent (&rest body)

Unmute all messages from standard output inside the scope.

(eask--unsilent (message "You can hear me! :)"))

πŸ” Function: eask-dependencies ()

Return a list of dependencies.

Elements should either be (NAME . VERSION) or (NAME . RECIPE-FORMAT).

πŸ” Function: eask-pkg-init (&optional force)

Initialize packages for use.

  ;; Now you can use packages installed in `package-user-dir'
πŸ’‘ This is usually called after eask-start!

πŸ” Macro: eask-with-archives (archives &rest body)

Scope that temporary makes archives available.

ARCHIVES can either be a string or a list of strings.

(eask-with-archives "melpa"
  (eask-package-install 'dash))  ; install packages that are only defined in MELPA
πŸ’‘ This is handy when you need certain packages from certain archives.

πŸ” Function: eask-package-desc (name &optional current)

Build package descriptor for a package.

CURRENT means installed packages; otherwise it will return any available packages from selected package archives.

πŸ” Function: eask-argv (index)

Return a command-line argument by index.

πŸ” Function: eask-args ()

Return a list that is extracted from command-line arguments.

$ eask info --verbose 4 foo bar

It will ignore --verbose and 4, and only returns foo, and bar.

πŸ” Variable: eask-file

Path to currently loaded Eask-file.

πŸ” Variable: eask-file-root

Directory to currently loaded Eask-file.

πŸ” Function: eask–match-file (name)

Check to see if NAME is our target Eask-file, then return it.

The following output is with Emacs 28.1:

(eask--match-file "Eask")         ; t
(eask--match-file "Eask.28")      ; t
(eask--match-file "Eask.28.1")    ; t
(eask--match-file "Eask.29")      ; nil

(eask--match-file "Easkfile")     ; t
(eask--match-file "Easkfile.28")  ; t
(eask--match-file "Easkfile.29")  ; nil

πŸ” Function: eask–all-files (&optional dir)

Return a list of Eask files from DIR.

Consider the following directory tree:

. root
β”œβ”€β”€ Eask
β”œβ”€β”€ Eask.28
└── Eask.29

The following output is with Emacs 28.1:

(eask--all-files "/root/")  ; '(Eask Eask.28)

πŸ” Function: eask–find-files (start-path)

Find the Eask-file from START-PATH.

Consider the following directory tree:

β”œβ”€ src
β”‚ └── config.el
β”œβ”€β”€ Eask
β”œβ”€β”€ Eask.28
└── Eask.29

The following output is with Emacs 28.1:

(eask--find-files "/project/src/config.el")  ; '(/project/Eask /project/Eask.28)

πŸ” Function: eask-file-try-load (start-path)

Try load the Eask-file in START-PATH.

(eask--find-files "/project/src/")  ; t

πŸ” Function: eask-network-insecure-p ()

Return t if the current Emacs session allows insecure network connections.

🚩 Flags

πŸ” Function: eask-global-p ()

Return t if the global option is enabled.

(when (eask-global-p)
  user-emacs-directory)   ; ~/.eask/

πŸ” Function: eask-config-p ()

Return t if the config option is enabled.

(when (eask-config-p)
  user-emacs-directory)   ; ~/.emacs.d
πŸ’‘ If both options --config and --global are on, the global space is chosen over the config space.

πŸ” Function: eask-local-p ()

This uses the current workspace, and this is the default.

(when (eask-local-p)
  user-emacs-directory)   ; ./.eask/{emacs-version}/
πŸ’‘ This function returns t only when (eask-global-p) and (eask-config-p) are false!

πŸ” Function: eask-all-p ()

Return t if the all option is enabled.

(when (eask-all-p)
  ;; Run all tests

πŸ” Function: eask-quick-p ()

Return t if the quick option is enabled.

(unless (eask-quick-p)
  (load user-init-file)

πŸ” Function: eask-force-p ()

Return t if the force option is enabled.

(package-delete .. (eask-force-p))

πŸ” Function: eask-dev-p ()

Return t if the development option is enabled.

(when (eask-dev-p)
  (package-install 'ert-runner))  ; install development dependency

πŸ” Function: eask-debug-p ()

Return t if the debug option is enabled.

(when (eask-debug-p)
  (error "Executing in debug mode..."))

πŸ” Function: eask-strict-p ()

Return t if the strict option is enabled.

(setq byte-compile-error-on-warn (eask-strict-p))

πŸ” Function: eask-timestamps-p ()

Return t/nil if the timestamps option is enabled/disabled.

These flags can’t co-exist in the same command.

(when (eask-timestamps-p)
  (message "Print log with timestamps!"))

πŸ” Function: eask-log-level-p ()

Return t/nil if the log-level option is enabled/disabled.

These flags can’t co-exist in the same command.

(when (eask-log-level-p)
  (message "Print log with level prefix!"))

πŸ” Function: eask-log-file-p ()

Return t/nil if the log-file option is enabled/disabled.

These flags can’t co-exist in the same command.

(when (eask-log-file-p)
  (message "Let's create a log file!"))

πŸ” Function: eask-no-color-p ()

Return t if the color option is enabled.

(unless (eask-no-color-p)
  (message "This string has no ansi code!"))

πŸ” Function: eask-allow-error-p ()

Return t if the allow-error option is enabled.

(unless (eask-allow-error-p)
  (error "Stop here."))

πŸ” Function: eask-insecure-p ()

Return t if the insecure option is enabled.

(when (eask-insecure-p)
  ;; Do some dangerous tasks?

πŸ” Function: eask-proxy ()

πŸ” Function: eask-http-proxy ()

πŸ” Function: eask-https-proxy ()

πŸ” Function: eask-no-proxy ()

Return a string represents hostname + port number.

$ eask [command] --proxy "localhost:1000"
$ eask [command] --http-proxy "localhost:2000"
$ eask [command] --https-proxy "localhost:3000"
$ eask [command] --no-proxy "localhost:4000"

πŸ” Function: eask-destination ()

Return a string represents the destination (output path).

(write-file (or (eask-destination) "./dist"))  ; write file to destination

πŸ” Function: eask-depth ()

Return an integer represents the depth of the current print level.

(setq print-level (eask-depth))

πŸ” Function: eask-verbose ()

Return an integer represents the verbosity level.

(when (= (eask-verbose) 4)
  (setq byte-compile-verbose t))

🚩 Eask-file

These functions are the actual implementation of Eask-file DSL; and have the word eask- as the function prefix.

See DSL section for more information.

πŸ” Variable: eask-package

It holds package’s NAME, VERSION, and DESCRIPTION in a plist.

(plist-get eask-package :name)  ; return package name

Three functions that are extended from this variable:

  • (eask-package-name)
  • (eask-package-version)
  • (eask-package-description)

πŸ” Variable: eask-package-file

Points to package main file.

πŸ” Variable: eask-package-desc

Package descriptor from the package main file.

(package-desc-p eask-package-desc)  ; return t
⚠ This can be nil if the package-descriptor cannot be constructed correctly!

πŸ” Variable: eask-files

Holds a list of files pattern in wildcard specification.

πŸ” Variable: eask-scripts

Holds a list of available scripts that can be executed by user using the eask run-script command.

πŸ” Variable: eask-depends-on-emacs

Holds information about Emacs minimum version.

(depends-on "emacs" "26.1")

Function will return Emacs version in string.

  • (eask-depends-emacs-version) - return "26.1"

πŸ” Variable: eask-depends-on

Holds a list of dependencies.

πŸ” Variable: eask-depends-on-dev

Holds a list of dependencies that are development used.

πŸ” Function: eask-f-package (name version description)

Alias of package.

πŸ” Function: eask-f-website-url (url)

Alias of website-url.

πŸ” Function: eask-f-keywords (&rest keywords)

Alias of keywords.

πŸ” Function: eask-f-author (name &optional email)

Alias of author.

πŸ” Function: eask-f-license (name)

Alias of license.

πŸ” Function: eask-f-package-file (file)

Alias of package-file.

πŸ” Function: eask-f-files (pkg &rest args)

Alias of files.

πŸ” Function: eask-f-script (name command &rest args)

Alias of script.

πŸ” Function: eask-f-source (name &optional location)

Alias of source.

πŸ” Function: eask-f-source-priority (name &optional priority)

Alias of source-priority.

πŸ” Function: eask-f-depends-on (pkg &rest args)

Alias of depends-on.

πŸ” Function: eask-f-development (&rest dependencies)

Alias of development.

πŸ” Function: eask-f-exec-paths (&rest dirs)

Alias of exec-paths.

πŸ” Function: eask-f-load-paths (&rest dirs)

Alias of load-paths.

🚩 Logging

Logger utility with timestamps and log level.

The log level value is defined in function eask--verb2lvl.

debugDesignates fine-grained informational events that are most useful to debug an application.4
logDesignates normal messages.3
infoDesignates informational messages that highlight the progress of the application at coarse-grained level.2
warnDesignates potentially harmful situations.1
errorDesignates error events that might still allow the application to continue running.0

The default level is log.

πŸ” Variable: eask-verbosity

The verbosity level is represented as an integer.

(setq eask-verbosity 4)  ; you could set from 0 to 4

πŸ” Variable: eask-timestamps

Log messages with timestamps.

(setq eask-timestamps t)


2022-04-14 13:44:46 This is a message with timestamps

πŸ” Variable: eask-log-level

Log messages with level. (default: nil)

(setq eask-log-level t)


[DEBUG] This is a DEBUG message with log level

πŸ” Variable: eask-log-file

Weather to generate log files. (default: nil)

(setq eask-log-level t)

Use command cat to see the log,

$ cat /.log/messages.log

πŸ” Variable: eask-level-color

Define each log level color.

(setq eask-level-color
      '((debug . ansi-blue)
        (log   . ansi-white)
        (info  . ansi-cyan)
        (warn  . ansi-yellow)
        (error . ansi-red)))

πŸ” Function: eask-reach-verbosity-p (symbol)

Make execution when it reaches the verbosity level.

(when (eask-reach-verbosity-p 'debug)
  ;; TODO: execution here..

πŸ” Macro: eask-with-verbosity (symbol &rest body)

Define verbosity scope.

(eask-with-verbosity 'debug
  ;; TODO: execution here..

Everything in the scope of this macro will be muted unless the verbosity reaches. It will only be printed when you have specified --verbose 4 global option.

πŸ” Macro: eask-with-verbosity-override (symbol &rest body)

Define override verbosity scope.

(eask-with-verbosity 'debug
  (eask-with-verbosity-override 'log
    ;; TODO: execution here..
  (eask-with-verbosity-override 'info
    ;; TODO: execution here..

Like macro eask-with-verbosity; but force display messages if it wasn’t able to display.

πŸ” Function: eask-debug (msg &rest args)

(eask-debug "This is DEBUG message")
2022-04-14 17:31:54 [DEBUG] This is DEBUG message

πŸ” Function: eask-log (msg &rest args)

(eask-log "This is LOG message")
2022-04-14 17:31:54 [LOG] This is LOG message

πŸ” Function: eask-info (msg &rest args)

(eask-info "This is INFO message")
2022-04-14 17:31:54 [INFO] This is INFO message

πŸ” Function: eask-warn (msg &rest args)

(eask-warn "This is WARNING message")
2022-04-14 17:31:54 [WARNING] This is WARNING message

πŸ” Function: eask-error (msg &rest args)

(eask-error "This is ERROR message")
2022-04-14 17:31:54 [ERROR] This is ERROR message

πŸ” Function: eask-print (msg &rest args)

Standard output printing without newline.

(eask-println "Print to stdout!")

πŸ” Function: eask-println (msg &rest args)

Like the function eask-print but contains the newline at the end.

(eask-println "Print to stdout! (with newline)")

πŸ” Function: eask-msg (msg &rest args)

Like the message function but will replace unicode with color.

(eask-msg "Print this message with newline!")

πŸ” Function: eask-write (msg &rest args)

Like the eask-msg function but without the newline at the end.

(eask-write "Print this message without newline...")

πŸ” Function: eask-report (&rest args)

Report error/warning depends on strict flag.

(eask-report "This can be warning or error")

See option –strict.

🚩 Error Handling

πŸ” Variable: eask–ignore-error-p

Non-nil to prevent Emacs from being killed.

(let ((eask--ignore-error-p t))
  (error "Emacs can't die! :P"))

πŸ” Variable: eask-inhibit-error-message

Non-nil to stop error/warning message.

(let ((eask-inhibit-error-message t))
  (error "This won't display at all!"))

πŸ” Macro: eask-ignore-errors (&rest body)

Prevent Emacs from being killed.

  (error "Emacs can't die! :P"))

πŸ” Macro: eask–silent-error (&rest body)

Inhibit display error/warning messages.

  (error "This won't display at all!"))

πŸ” Macro: eask-ignore-errors-silent (&rest body)

Prevent Emacs from being killed and inhibit display error/warning messages.

  (error "Nothing happens!"))

πŸ” Function: eask–exit ()

Send exit code.

This will kill Emacs process.

🚩 File

πŸ” Function: eask-package-files ()

Return a list of package files.

πŸ” Function: eask-package-el-files ()

Return a list of package files with .el extension.

πŸ” Function: eask-package-elc-files ()

Return a list of package files with .elc extension.

πŸ” Function: eask-package-multi-p ()

Return nil if single file package.

πŸ” Function: eask-package-single-p ()

Return t if single file package.

πŸ” Function: eask-unpacked-size ()

Return size of the current package.

⚠️ This returns a string not bytes.

🚩 Progress

πŸ” Macro: eask-with-progress (msg-start body msg-end)

Create execution with the responsive message output.

  "Downloading files... "
  (eask-with-verbosity 'debug  ; Often used with `eask-with-verbosity'
    ;; Execute some operations..
  "done βœ“")

Expect output:

Downloading files... done βœ“

πŸ” Function: eask-print-log-buffer (&optional buffer-or-name)

Print buffer and highlight the errors and warnings.

(eask-print-log-buffer "*Package-Lint*")
πŸ’‘ This is handy for linters that create a buffer to display errors and warnings.

🚩 Help

πŸ” Function: eask-help (command)

Print help manual located under lisp/help/ directory.

(eask-help "core/search")
πŸ’‘ This is used when a command fails, and would like to give users some tips!

🚩 Utilities

πŸ” Function: eask-guess-package-name ()

Return the possible package name.

πŸ” Function: eask-guess-entry-point ()

Return the possible package’s entry point.