mirror of
https://gitlab.com/vindarel/ciel.git
synced 2025-12-05 18:20:34 -08:00
init file: add --no-userinit
and add --noinform that was missing in Clingon options. Move the useful load-without-shebang in utils.lisp, now available for all systems. "make" alone calls make build
This commit is contained in:
parent
f7a4f06335
commit
b23214917c
8 changed files with 98 additions and 33 deletions
2
Makefile
2
Makefile
|
|
@ -1,5 +1,7 @@
|
|||
LISP ?= sbcl
|
||||
|
||||
all: build
|
||||
|
||||
# Install some Quicklisp dependencies.
|
||||
ql-deps:
|
||||
# 2023-03: we want str:ensure-suffix, not yet in Quicklisp.
|
||||
|
|
|
|||
|
|
@ -210,6 +210,8 @@ This REPL is more user friendly than the default SBCL one:
|
|||
%q => Ends the session.
|
||||
```
|
||||
|
||||
The CIEL terminal REPL loads the `~/.cielrc` init file at start-up if present. Don't load with `--no-userinit`.
|
||||
|
||||
See more in [*the documentation*](https://ciel-lang.github.io/CIEL/#/).
|
||||
|
||||
# Usage
|
||||
|
|
|
|||
|
|
@ -13,4 +13,9 @@
|
|||
|
||||
(in-package :ciel-user)
|
||||
|
||||
;; XXX: we would like to read our ~/.cielrc init file when resuming the core
|
||||
;; in Slime.
|
||||
;; Currently we load it only when starting the terminal REPL.
|
||||
;; See the :toplevel option.
|
||||
|
||||
(sb-ext:save-lisp-and-die "ciel-core")
|
||||
|
|
|
|||
2
ciel.asd
2
ciel.asd
|
|
@ -136,6 +136,7 @@
|
|||
((:file "packages")
|
||||
(:file "json-pointer-minus")
|
||||
(:file "ciel")))
|
||||
(:file "utils")
|
||||
(:module "src/more-docstrings"
|
||||
:components
|
||||
((:file "docstrings"))))
|
||||
|
|
@ -152,6 +153,7 @@
|
|||
:lisp-critic ;; it would be nice to integrate it with Slime.
|
||||
:magic-ed)
|
||||
:components ((:file "repl")
|
||||
(:file "utils")
|
||||
(:file "scripting")
|
||||
(:file "shell-utils")
|
||||
(:file "repl-utils")
|
||||
|
|
|
|||
|
|
@ -539,3 +539,27 @@ This allows you to have a dumb "live reload" workflow with a simple editor and a
|
|||
(simple-auto-reload)
|
||||
(sleep most-positive-fixnum))
|
||||
~~~
|
||||
|
||||
## Misc
|
||||
|
||||
### Load your scripts in the REPL
|
||||
|
||||
Calling your scripts from the shell is pretty cool, what if you could
|
||||
*also* have them available at your fingertips in a Lisp REPL?
|
||||
|
||||
TLDR;
|
||||
|
||||
```lisp
|
||||
;; in ~/.cielrc
|
||||
(ciel::load-without-shebang "~/path/to/yourscript.lisp")
|
||||
```
|
||||
|
||||
As the name suggests, this `load` function works even if your file starts with a shebang line (which is not valid Lisp code, so the default `LOAD` function would fail).
|
||||
|
||||
Y'know, sometimes you live longer in a Lisp REPL than in a shell
|
||||
without noticing. Or simply, manipulating real objects in a text
|
||||
buffer can be more practical than copy-pasting text in a rigid
|
||||
terminal (even though Emacs'
|
||||
[vterm](https://github.com/akermu/emacs-libvterm) is an excellent improvement too).
|
||||
|
||||
> INFO: the `~/.cielrc` file is loaded at start-up of the terminal REPL (called with `ciel`), not yet when you start the core image in your IDE.
|
||||
|
|
|
|||
22
repl.lisp
22
repl.lisp
|
|
@ -8,7 +8,7 @@
|
|||
(:use :common-lisp :trivial-package-local-nicknames)
|
||||
(:import-from :magic-ed
|
||||
:magic-ed)
|
||||
(:export sbcli help what *repl-version* *repl-name* *prompt* *prompt2* *result-indicator* *config-file*
|
||||
(:export sbcli help what *repl-version* *repl-name* *prompt* *prompt2* *result-indicator* *init-file*
|
||||
*hist-file* *special*
|
||||
*syntax-highlighting* *pygmentize* *pygmentize-options*))
|
||||
|
||||
|
|
@ -48,7 +48,7 @@
|
|||
(defvar *prompt* (format nil "~a" (cl-ansi-text:green "ciel-user> ")))
|
||||
(defvar *prompt2* "....> ")
|
||||
(defvar *result-indicator* "=> ")
|
||||
(defvar *config-file* "~/.cielrc")
|
||||
(defvar *init-file* "~/.cielrc")
|
||||
(defvar *hist-file* "~/.ciel_history")
|
||||
(defvar *hist* (list))
|
||||
(defvar *syntax-highlighting* nil)
|
||||
|
|
@ -87,6 +87,11 @@
|
|||
:if-does-not-exist :create)
|
||||
(write-line str out)))
|
||||
|
||||
(defun load-init-file (&optional (init-file *init-file*))
|
||||
"Load the ~/.cielrc init file.
|
||||
Defaults to `*init-file*'."
|
||||
(load init-file))
|
||||
|
||||
(defun end ()
|
||||
"Ends the session."
|
||||
(format t "~%Bye!~&")
|
||||
|
|
@ -524,12 +529,13 @@ strings to match candidates against (for example in the form \"package:sym\")."
|
|||
(rl:redisplay)
|
||||
))
|
||||
|
||||
(defun repl (&key noinform)
|
||||
(defun repl (&key noinform no-usernit)
|
||||
"Toplevel REPL.
|
||||
|
||||
CLI options:
|
||||
- -h, --help
|
||||
- --noinform: don't print the welcome banner.
|
||||
- --no-userinit: don't load the user's cielrc init file.
|
||||
"
|
||||
|
||||
(let ((argv (uiop:command-line-arguments)))
|
||||
|
|
@ -556,10 +562,8 @@ strings to match candidates against (for example in the form \"package:sym\")."
|
|||
(rl:bind-keyseq "\\C-x\\C-e" #'edit-current-input)
|
||||
(rl:set-paren-blink-timeout 500)
|
||||
|
||||
(if (probe-file *config-file*)
|
||||
(load *config-file*))
|
||||
|
||||
;; Print a banner and system info.
|
||||
;; Checking a CLI arg this way is an old, done before our use of Clingon.
|
||||
(unless (or noinform
|
||||
(member "--noinform" (uiop:command-line-arguments) :test #'string-equal))
|
||||
(princ *banner*)
|
||||
|
|
@ -570,6 +574,12 @@ strings to match candidates against (for example in the form \"package:sym\")."
|
|||
(write-char #\linefeed)
|
||||
(finish-output nil))
|
||||
|
||||
;; Load CIEL's user init file.
|
||||
(unless (or no-usernit
|
||||
(member "--no-userinit" (uiop:command-line-arguments) :test #'string-equal))
|
||||
(when (uiop:file-exists-p *init-file*)
|
||||
(load-init-file)))
|
||||
|
||||
(when *hist-file* (read-hist-file))
|
||||
|
||||
(in-package :ciel-user)
|
||||
|
|
|
|||
|
|
@ -8,33 +8,6 @@
|
|||
Hash-table: file name (sans extension) -> file content (string).
|
||||
The name is case-insensitive (it's easier for typing things in the terminal).")
|
||||
|
||||
(defun maybe-ignore-shebang (in)
|
||||
"If this file starts with #!, delete the shebang line,
|
||||
so we can LOAD the file.
|
||||
Return: a stream (it is LOADable)."
|
||||
;; thanks Roswell for the trick.
|
||||
(let ((first-line (read-line in)))
|
||||
(make-concatenated-stream
|
||||
;; remove shebang:
|
||||
(make-string-input-stream
|
||||
(format nil "~a"
|
||||
(if (str:starts-with-p "#!" first-line)
|
||||
""
|
||||
first-line)))
|
||||
;; rest of the file:
|
||||
in)))
|
||||
|
||||
(defun load-without-shebang (file)
|
||||
"LOAD this file, but exclude the first line if it is a shebang line."
|
||||
(with-open-file (file-stream file)
|
||||
(load
|
||||
(maybe-ignore-shebang file-stream))))
|
||||
|
||||
(defun has-shebang (file)
|
||||
"Return T if the first line of this file is a shell shebang line (starts with #!)."
|
||||
(with-open-file (s file)
|
||||
(str:starts-with-p "#!" (read-line s))))
|
||||
|
||||
;; eval
|
||||
(defun wrap-user-code (s)
|
||||
"Wrap this user code to handle common conditions, such as a C-c C-c to quit gracefully."
|
||||
|
|
@ -124,6 +97,16 @@
|
|||
:long-name "scripts"
|
||||
:short-name #\z
|
||||
:key :scripts)
|
||||
(clingon:make-option
|
||||
:flag
|
||||
:description "Don't load the ~/.cielrc init file at start-up (for the CIEL terminal REPL)."
|
||||
:long-name "no-userinit"
|
||||
:key :no-userinit)
|
||||
(clingon:make-option
|
||||
:flag
|
||||
:description "Don't print the welcome banner."
|
||||
:long-name "noinform"
|
||||
:key :noinform)
|
||||
))
|
||||
|
||||
#+(or)
|
||||
|
|
@ -259,6 +242,8 @@
|
|||
|
||||
;; default: run CIEL's REPL.
|
||||
(t
|
||||
;; XXX: maybe pass all CLI options here, don't re-read them in the repl function.
|
||||
;; (which was the old way).
|
||||
(sbcli::repl)))
|
||||
|
||||
(error (c)
|
||||
|
|
|
|||
35
utils.lisp
Normal file
35
utils.lisp
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
(in-package :ciel)
|
||||
|
||||
|
||||
;;; Utilities that are useful enough to be available everywhere.
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; These are used for the scripting capabilities.
|
||||
;;; We can load a file with or without a shebang line.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
(defun maybe-ignore-shebang (in)
|
||||
"If this file starts with #!, delete the shebang line,
|
||||
so we can LOAD the file.
|
||||
Return: a stream (it is LOADable)."
|
||||
;; thanks Roswell for the trick.
|
||||
(let ((first-line (read-line in)))
|
||||
(make-concatenated-stream
|
||||
;; remove shebang:
|
||||
(make-string-input-stream
|
||||
(format nil "~a"
|
||||
(if (str:starts-with-p "#!" first-line)
|
||||
""
|
||||
first-line)))
|
||||
;; rest of the file:
|
||||
in)))
|
||||
|
||||
(defun load-without-shebang (file)
|
||||
"LOAD this file, but exclude the first line if it is a shebang line."
|
||||
(with-open-file (file-stream file)
|
||||
(load
|
||||
(maybe-ignore-shebang file-stream))))
|
||||
|
||||
(defun has-shebang (file)
|
||||
"Return T if the first line of this file is a shell shebang line (starts with #!)."
|
||||
(with-open-file (s file)
|
||||
(str:starts-with-p "#!" (read-line s))))
|
||||
Loading…
Add table
Add a link
Reference in a new issue