~shunter/mstrings

f1c41d4ac681cff57f34bfbd473eff12983f8dc3 — Samuel Hunter 1 year, 7 months ago d1797ef v0.1.0
Replace cl-syntax with named-readtables; bump version number

I haven't found a strong reason why cl-syntax is better than
its dependency named-readtables, so I moved over.
4 files changed, 67 insertions(+), 41 deletions(-)

M README.md
M mstrings.asd
M mstrings.lisp
M test.lisp
M README.md => README.md +52 -31
@@ 1,10 1,13 @@
# M-strings for Common Lisp
# Mstrings - Pretty Multliline Strings for Common Lisp
[![builds.sr.ht status](https://builds.sr.ht/~shunter/mstrings/commits/master/test.yml.svg)](https://builds.sr.ht/~shunter/mstrings/commits/master/test.yml)

Reader macro for friendlier multiline strings.
**Mstrings** defines a reader macro for strings with a small handful of
features to provide visually appealing multiline blocks. An M-string:

M-strings defines a reader macro for multiline strings with various
quality-of-life features, including whitespace elimination and folding.
- Trims leading whitespace from lines
- Respects escaped whitespace characters and keeps them untrimmed
- Concatenates lines together when joined by an escaped Newline
- Alternative mode to fold multiple non-empty lines into one joined by spaces

When writing strings that take multiple lines, for example an extensive
docstring, it feels natural to align them up. However, the Lisp reader will


@@ 63,12 66,9 @@ qux=3"
Any comments, questions, issues, or patches are greatly appreciated!
I do my main development on [Sourcehut](https://sr.ht/~shunter/mstrings/), with a [mailing list](https://lists.sr.ht/~shunter/public-inbox) and [issue tracker](https://todo.sr.ht/~shunter/mstrings).

## Usage
## Install and Enable It

M-strings uses [cl-syntax](https://github.com/fukamachi/cl-syntax) to expose the
reader macro. Install it through Quicklisp, or manually alongside its
dependents [trivial-types](https://github.com/m2ym/trivial-types) and
[named-readtables](https://github.com/kmizumar/named-readtables/).
M-strings' sole dependency is [named-readtables](https://named-readtables.common-lisp.dev/), available on Quicklisp.

Install M-strings locally, until it is added to Quicklisp:



@@ 77,39 77,30 @@ $ cd ~/common-lisp/ # Or wherever you store your systems
$ git clone https://git.sr.ht/~shunter/mstrings
```

To use M-string macros, call `(syntax:use-syntax '#:mstrings)` at the beginning
of every file:
This library uses named readtables to expose the reader:

```lisp
* (require :mstrings)
* (syntax:use-syntax '#:mstrings)
* (use-package :named-readtables)
* (in-readtable mstrings:mstring-syntax)

* #M"Hello, world!"
* "Hello, world!"
```

## Features

M-strings remove leading whitespace:
```lisp
* (princ #M"Hello
            World!")
Hello
World!
```

M-strings read empty lines as a single newline:
## Features

M-strings trim leading whitespace from lines:

```lisp
* (princ #M"Hello

            World!")
Hello

World!
```

M-strings respect escaped characters and, outside for newlines, treats them line non-whitespace characters:
M-strings respect escaped characters and keeps them untrimmed:

```lisp
* (princ #M"keys:


@@ 120,7 111,7 @@ keys:
  bar: "banana"
```

M-strings concatenate together two lines if they're separated by an escaped newline - useful for very long single-line values:
M-strings concatenates lines together when they're joined by an escaped Newline - useful for very long single-line values:

```lisp
* (princ #M"NB2HI4DTHIXS653XO4XHS33VOR2WEZJOMNXW\


@@ 130,8 121,8 @@ NB2HI4DTHIXS653XO4XHS33VOR2WEZJOMNXW2L3XMF2GG2B7OY6WIULXGR3TSV3HLBRVC===

By default, M-strings are read in "literal-block mode", where newlines are read
as literal newlines. Prefixing a string with a `>` sets the reader to
"folding-block mode", where multiple lines in the string are folded into one
line:
"folding-block mode", where multiple non-empty lines are folded into one,
joined by spaces:

```lisp
* (princ #M>"The quick brown fox


@@ 142,6 133,13 @@ line:
             judge my vow!")
The quick brown fox jumps over the lazy dog.
Sphinx of black quartz, judge my vow!

* (princ #M>"Escaped newlines
             \
             still prevent
             \
             line breaks")
Escaped Newlines still prevent line breaks
```

## Shorthand notation: `#"..." and #>"..."`


@@ 151,9 149,9 @@ The reader macro function understands `#"..."` and `#>"..."` as shorthands for
macro collisions from other systems:

```lisp
* (syntax:use-syntax 'mstrings:shorthand-mstrings)
  ;; Or, for both:
* (syntax:use-syntax '(#:mstrings mstrings:shorthand-mstrings))
* (in-readtable mstrings:shorthand-mstring-syntax)
* ;; Or, for both shorthand and long-hand:
* (in-readtable mstrings:full-mstring-syntax)

*    #"Literal-block
       Mode"


@@ 182,3 180,26 @@ Reader macro accepts multiline strings. It ignores and warns on any provided
- If *subchar* is anything else, it follows the default behavior: it assumes
  literal-block mode unless there is a greater-than-sign preceding the string,
  in which case it switches to folding-block mode.

### [Readtable] **mstring-syntax**

The standard readtable with the longhand mstring syntax:

- `#M"..."` - Literal-block mstring
- `#M>"..."` - Folding-block mstring

### [Readtable] **shorthand-mstring-syntax**

The standard readtable with both `#"` and `#>` dispatch character pairs bound
to **mstring-reader**:

- `#"..."` - Literal-block mstring
- `#>"..."` - Folding-block mstring

### [Readtable] **full-mstring-syntax**

The standard readtable with additions from both **mstring-syntax** and
**shorthand-mstring-syntax**:

- `#M"..."`, `#"..."` - Literal-block mstring
- `#M>"..."`, `#>"..."` - Folding-block mstring

M mstrings.asd => mstrings.asd +6 -5
@@ 4,9 4,9 @@
;;; BSD 3-Clause License. See LICENSE for details.

(defsystem #:mstrings
  :description "Reader macro for friendlier multiline strings"
  :long-description "Mstrings defines a reader macro for multiline strings with various quality-of-life features, including whitespace elimination and line folding."
  :version "0.0.0"
  :description "Pretty multiline strings Reader Macro"
  :long-description "Mstrings defines a reader macro for strings with a small handful of features to provide visually appealing multiline blocks."
  :version "0.1.0"
  :license "BSD 3-Clause"
  :author "Samuel Hunter"



@@ 15,17 15,18 @@
  :bug-tracker "https://todo.sr.ht/~shunter/mstrings/"
  :mailto "\~\s\h\u\n\t\e\r\/\p\u\b\l\i\c\-\i\n\b\o\x\@\l\i\s\t\s\.\s\r\.\h\t"

  :depends-on (#:cl-syntax)
  :depends-on (#:named-readtables)
  :components ((:file "mstrings"))
  :in-order-to ((test-op (test-op :mstrings/test))))

(defsystem #:mstrings/test
  :description "Mstrings library test suite"
  :version "0.0.0"
  :version "0.1.0"
  :license "BSD 3-Clause"
  :author "Samuel Hunter"

  :depends-on (#:mstrings
               #:cl-syntax
               #:parachute)
  :components ((:file "test"))
  :perform (test-op (op c)

M mstrings.lisp => mstrings.lisp +8 -3
@@ 7,7 7,9 @@
  (:nicknames #:mstrings)
  (:use #:cl)
  (:export #:mstring-reader
           #:shorthand-mstrings)
           #:mstring-syntax
           #:shorthand-mstring-syntax
           #:full-mstring-syntax)
  (:documentation "Reader macro for friendlier multiline strings"))

(in-package #:xyz.shunter.mstrings)


@@ 144,14 146,17 @@ It ignores and warns on any provided ARG, and provides a few quality-of-life fea
    ;; Room for more block modes here if need be
    (t (error "Unknown string style '~C'" (peek-char! nil stream)))))

(syntax:define-package-syntax #:xyz.shunter.mstrings
(named-readtables:defreadtable mstring-syntax
  (:merge :standard)
  (:dispatch-macro-char #\# #\M #'mstring-reader))

(syntax:defsyntax shorthand-mstrings
(named-readtables:defreadtable shorthand-mstring-syntax
  (:merge :standard)
  ;; #\" is also claimed by the string-escape library
  (:dispatch-macro-char #\# #\" #'mstring-reader)
  ;; #> is claimed by Clozure CL 1.2 and later :(
  #-CCL-1.2
  (:dispatch-macro-char #\# #\> #'mstring-reader))

(named-readtables:defreadtable full-mstring-syntax
  (:merge mstring-syntax shorthand-mstring-syntax))

M test.lisp => test.lisp +1 -2
@@ 9,8 9,7 @@
  (:documentation "Mstrings library test suite"))

(in-package #:xyz.shunter.mstrings.test)

(syntax:use-syntax '(#:xyz.shunter.mstrings shorthand-mstrings))
(named-readtables:in-readtable full-mstring-syntax)