This project is archived and unmaintained.
Binaries are unavailable as of May 1, 2021.
Please switch to mdoc. See the migration guide.
doc/tutorial generator for scala
License: MIT License
This project is archived and unmaintained.
Binaries are unavailable as of May 1, 2021.
Please switch to mdoc. See the migration guide.
To support copy and pasting code from our books we'd like cleaner output from Tut. Specifically:
scala>
and no |
continuation character.So
object Foo {
def foo(a: Int): Int = a + 1
}
renders as
object Foo {
def foo(a: Int): Int = a + 1
}
// defined module Foo
not
scala> object Foo {
| def foo(a: Int): Int = a + 1
| }
defined module Foo
It would be nice to be able to refer to code in tut blocks defined in other files. Either through some type of import statement, possibly tut-specific or by declaring a top-level ordering of the files to be loaded.
For example:
// Inside a tut documented file, file_1.md:
tut-import other_file1
<Some statement using a definition from other_file1>
In order to do this you would (at least) need to define page ordering or have each page generate a module with a predictable name. One option is to generate it from the filename. Particularly, if tut-imports are kept different from normal imports, name clashes could be avoided by converting the import statement to a normal import statement (possibly prepended by a tut generated package hierarchy). This is probably less intrusive than letting the user have to define a module name.
It seems that tut 0.4.1 breaks tab completion in sbt in multi-project builds. This project is a minimal example for reproducing the problem: https://github.com/fthomas/sbt-test
Pressing tab after sbt loads, yields this exception:
$ sbt
Loading /usr/share/sbt/bin/sbt-launch-lib.bash
[info] Loading global plugins from /home/frank/.sbt/0.13/plugins
[info] Loading project definition from /home/frank/data/code/sbt-test/project
[info] Set current project to sbt-test (in build file:/home/frank/data/code/sbt-test/)
> java.lang.RuntimeException: sbt-test/.:.::tutSourceDirectory is undefined.
at scala.sys.package$.error(package.scala:27)
at sbt.Extracted$$anonfun$getOrError$2.apply(Extracted.scala:96)
at sbt.Extracted$$anonfun$getOrError$2.apply(Extracted.scala:96)
at scala.Option.getOrElse(Option.scala:120)
at sbt.Extracted.getOrError(Extracted.scala:96)
at sbt.Extracted.get(Extracted.scala:21)
at tut.Plugin$$anonfun$tutSettings$10$$anonfun$apply$11.apply(Plugin.scala:70)
at tut.Plugin$$anonfun$tutSettings$10$$anonfun$apply$11.apply(Plugin.scala:68)
at sbt.InputTask$$anonfun$free$1.apply(InputTask.scala:58)
at sbt.InputTask$$anonfun$free$1.apply(InputTask.scala:58)
at sbt.InputTask$$anonfun$mapTask$1.apply(InputTask.scala:12)
at sbt.InputTask$$anonfun$mapTask$1.apply(InputTask.scala:12)
at sbt.Aggregation$$anonfun$6.apply(Aggregation.scala:109)
at sbt.Aggregation$$anonfun$6.apply(Aggregation.scala:109)
at scala.collection.TraversableLike$WithFilter$$anonfun$map$2.apply(TraversableLike.scala:722)
at scala.collection.immutable.List.foreach(List.scala:318)
at scala.collection.TraversableLike$WithFilter.map(TraversableLike.scala:721)
at sbt.Aggregation$.applyDynamicTasks(Aggregation.scala:109)
at sbt.Aggregation$.evaluatingParser(Aggregation.scala:147)
at sbt.Act$$anonfun$sbt$Act$$actParser0$1.sbt$Act$$anonfun$$evaluate$1(Act.scala:240)
at sbt.Act$$anonfun$sbt$Act$$actParser0$1$$anonfun$apply$12.apply(Act.scala:249)
at sbt.Act$$anonfun$sbt$Act$$actParser0$1$$anonfun$apply$12.apply(Act.scala:249)
at sbt.complete.BindParser$$anonfun$completions$3.apply(Parser.scala:661)
at sbt.complete.BindParser$$anonfun$completions$3.apply(Parser.scala:658)
at sbt.complete.Completions$$anonfun$flatMap$1$$anonfun$apply$1.apply(Completions.scala:19)
at sbt.complete.Completions$$anonfun$flatMap$1$$anonfun$apply$1.apply(Completions.scala:19)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.immutable.HashSet$HashSet1.foreach(HashSet.scala:153)
at scala.collection.immutable.HashSet$HashTrieSet.foreach(HashSet.scala:306)
at scala.collection.immutable.HashSet$HashTrieSet.foreach(HashSet.scala:306)
at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:251)
at scala.collection.AbstractTraversable.flatMap(Traversable.scala:105)
at sbt.complete.Completions$$anonfun$flatMap$1.apply(Completions.scala:19)
at sbt.complete.Completions$$anonfun$flatMap$1.apply(Completions.scala:19)
at sbt.complete.Completions$$anon$1.get$lzycompute(Completions.scala:27)
at sbt.complete.Completions$$anon$1.get(Completions.scala:27)
at sbt.complete.Completions$$anonfun$map$1.apply(Completions.scala:20)
at sbt.complete.Completions$$anonfun$map$1.apply(Completions.scala:20)
at sbt.complete.Completions$$anon$1.get$lzycompute(Completions.scala:27)
at sbt.complete.Completions$$anon$1.get(Completions.scala:27)
at sbt.complete.Completions$$anonfun$flatMap$1$$anonfun$apply$1.apply(Completions.scala:19)
at sbt.complete.Completions$$anonfun$flatMap$1$$anonfun$apply$1.apply(Completions.scala:19)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.immutable.Set$Set3.foreach(Set.scala:115)
at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:251)
at scala.collection.AbstractTraversable.flatMap(Traversable.scala:105)
at sbt.complete.Completions$$anonfun$flatMap$1.apply(Completions.scala:19)
at sbt.complete.Completions$$anonfun$flatMap$1.apply(Completions.scala:19)
at sbt.complete.Completions$$anon$1.get$lzycompute(Completions.scala:27)
at sbt.complete.Completions$$anon$1.get(Completions.scala:27)
at sbt.complete.Completions$$anonfun$$plus$plus$1.apply(Completions.scala:14)
at sbt.complete.Completions$$anonfun$$plus$plus$1.apply(Completions.scala:14)
at sbt.complete.Completions$$anon$1.get$lzycompute(Completions.scala:27)
at sbt.complete.Completions$$anon$1.get(Completions.scala:27)
at sbt.complete.Completions$$anonfun$$plus$plus$1.apply(Completions.scala:14)
at sbt.complete.Completions$$anonfun$$plus$plus$1.apply(Completions.scala:14)
at sbt.complete.Completions$$anon$1.get$lzycompute(Completions.scala:27)
at sbt.complete.Completions$$anon$1.get(Completions.scala:27)
at sbt.complete.Completions$$anonfun$flatMap$1.apply(Completions.scala:19)
at sbt.complete.Completions$$anonfun$flatMap$1.apply(Completions.scala:19)
at sbt.complete.Completions$$anon$1.get$lzycompute(Completions.scala:27)
at sbt.complete.Completions$$anon$1.get(Completions.scala:27)
at sbt.complete.JLineCompletion$.convertCompletions(JLineCompletion.scala:56)
at sbt.complete.JLineCompletion$$anonfun$parserAsCompletor$1.apply(JLineCompletion.scala:52)
at sbt.complete.JLineCompletion$$anonfun$parserAsCompletor$1.apply(JLineCompletion.scala:52)
at sbt.complete.JLineCompletion$$anonfun$customCompletor$1$$anonfun$2.apply(JLineCompletion.scala:75)
at sbt.complete.JLineCompletion$$anonfun$customCompletor$1$$anonfun$2.apply(JLineCompletion.scala:75)
at sbt.complete.JLineCompletion$.complete(JLineCompletion.scala:94)
at sbt.complete.JLineCompletion$$anonfun$customCompletor$1.apply(JLineCompletion.scala:75)
at sbt.complete.JLineCompletion$$anonfun$customCompletor$1.apply(JLineCompletion.scala:74)
at sbt.complete.JLineCompletion$CustomHandler.complete(JLineCompletion.scala:30)
at jline.console.ConsoleReader.complete(ConsoleReader.java:3082)
at jline.console.ConsoleReader.readLine(ConsoleReader.java:2501)
at jline.console.ConsoleReader.readLine(ConsoleReader.java:2162)
at sbt.JLine.sbt$JLine$$readLineDirectRaw(LineReader.scala:42)
at sbt.JLine$$anonfun$readLineDirect$2.apply(LineReader.scala:34)
at sbt.JLine$$anonfun$readLineDirect$2.apply(LineReader.scala:34)
at sbt.Signals0.withHandler(Signal.scala:81)
at sbt.Signals$.withHandler(Signal.scala:11)
at sbt.JLine.readLineDirect(LineReader.scala:34)
at sbt.JLine.readLineWithHistory(LineReader.scala:27)
at sbt.JLine.sbt$JLine$$unsynchronizedReadLine(LineReader.scala:19)
at sbt.JLine$$anonfun$readLine$1.apply(LineReader.scala:16)
at sbt.JLine$$anonfun$readLine$1.apply(LineReader.scala:16)
at sbt.JLine$$anonfun$withJLine$1.apply(LineReader.scala:114)
at sbt.JLine$$anonfun$withJLine$1.apply(LineReader.scala:112)
at sbt.JLine$.withTerminal(LineReader.scala:86)
at sbt.JLine$.withJLine(LineReader.scala:112)
at sbt.JLine.readLine(LineReader.scala:16)
at sbt.BasicCommands$$anonfun$shell$1.apply(BasicCommands.scala:174)
at sbt.BasicCommands$$anonfun$shell$1.apply(BasicCommands.scala:170)
at sbt.Command$$anonfun$command$1$$anonfun$apply$1.apply(Command.scala:30)
at sbt.Command$$anonfun$command$1$$anonfun$apply$1.apply(Command.scala:30)
at sbt.Command$.process(Command.scala:93)
at sbt.MainLoop$$anonfun$1$$anonfun$apply$1.apply(MainLoop.scala:98)
at sbt.MainLoop$$anonfun$1$$anonfun$apply$1.apply(MainLoop.scala:98)
at sbt.State$$anon$1.process(State.scala:184)
at sbt.MainLoop$$anonfun$1.apply(MainLoop.scala:98)
at sbt.MainLoop$$anonfun$1.apply(MainLoop.scala:98)
at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:17)
at sbt.MainLoop$.next(MainLoop.scala:98)
at sbt.MainLoop$.run(MainLoop.scala:91)
at sbt.MainLoop$$anonfun$runWithNewLog$1.apply(MainLoop.scala:70)
at sbt.MainLoop$$anonfun$runWithNewLog$1.apply(MainLoop.scala:65)
at sbt.Using.apply(Using.scala:24)
at sbt.MainLoop$.runWithNewLog(MainLoop.scala:65)
at sbt.MainLoop$.runAndClearLast(MainLoop.scala:48)
at sbt.MainLoop$.runLoggedLoop(MainLoop.scala:32)
at sbt.MainLoop$.runLogged(MainLoop.scala:24)
at sbt.StandardMain$.runManaged(Main.scala:53)
at sbt.xMain.run(Main.scala:28)
at xsbt.boot.Launch$$anonfun$run$1.apply(Launch.scala:57)
at xsbt.boot.Launch$.withContextLoader(Launch.scala:77)
at xsbt.boot.Launch$.run(Launch.scala:57)
at xsbt.boot.Launch$$anonfun$explicit$1.apply(Launch.scala:45)
at xsbt.boot.Launch$.launch(Launch.scala:65)
at xsbt.boot.Launch$.apply(Launch.scala:16)
at xsbt.boot.Boot$.runImpl(Boot.scala:32)
at xsbt.boot.Boot$.main(Boot.scala:21)
at xsbt.boot.Boot.main(Boot.scala)
Exception occurred while determining completions.java.lang.RuntimeException: sbt-test/.:.::tutSourceDirectory is undefined.
at scala.sys.package$.error(package.scala:27)
at sbt.Extracted$$anonfun$getOrError$2.apply(Extracted.scala:96)
at sbt.Extracted$$anonfun$getOrError$2.apply(Extracted.scala:96)
at scala.Option.getOrElse(Option.scala:120)
at sbt.Extracted.getOrError(Extracted.scala:96)
at sbt.Extracted.get(Extracted.scala:21)
at tut.Plugin$$anonfun$tutSettings$10$$anonfun$apply$11.apply(Plugin.scala:70)
at tut.Plugin$$anonfun$tutSettings$10$$anonfun$apply$11.apply(Plugin.scala:68)
at sbt.InputTask$$anonfun$free$1.apply(InputTask.scala:58)
at sbt.InputTask$$anonfun$free$1.apply(InputTask.scala:58)
at sbt.InputTask$$anonfun$mapTask$1.apply(InputTask.scala:12)
at sbt.InputTask$$anonfun$mapTask$1.apply(InputTask.scala:12)
at sbt.Aggregation$$anonfun$6.apply(Aggregation.scala:109)
at sbt.Aggregation$$anonfun$6.apply(Aggregation.scala:109)
at scala.collection.TraversableLike$WithFilter$$anonfun$map$2.apply(TraversableLike.scala:722)
at scala.collection.immutable.List.foreach(List.scala:318)
at scala.collection.TraversableLike$WithFilter.map(TraversableLike.scala:721)
at sbt.Aggregation$.applyDynamicTasks(Aggregation.scala:109)
at sbt.Aggregation$.evaluatingParser(Aggregation.scala:147)
at sbt.Act$$anonfun$sbt$Act$$actParser0$1.sbt$Act$$anonfun$$evaluate$1(Act.scala:240)
at sbt.Act$$anonfun$sbt$Act$$actParser0$1$$anonfun$apply$12.apply(Act.scala:249)
at sbt.Act$$anonfun$sbt$Act$$actParser0$1$$anonfun$apply$12.apply(Act.scala:249)
at sbt.complete.BindParser$$anonfun$completions$3.apply(Parser.scala:661)
at sbt.complete.BindParser$$anonfun$completions$3.apply(Parser.scala:658)
at sbt.complete.Completions$$anonfun$flatMap$1$$anonfun$apply$1.apply(Completions.scala:19)
at sbt.complete.Completions$$anonfun$flatMap$1$$anonfun$apply$1.apply(Completions.scala:19)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.immutable.HashSet$HashSet1.foreach(HashSet.scala:153)
at scala.collection.immutable.HashSet$HashTrieSet.foreach(HashSet.scala:306)
at scala.collection.immutable.HashSet$HashTrieSet.foreach(HashSet.scala:306)
at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:251)
at scala.collection.AbstractTraversable.flatMap(Traversable.scala:105)
at sbt.complete.Completions$$anonfun$flatMap$1.apply(Completions.scala:19)
at sbt.complete.Completions$$anonfun$flatMap$1.apply(Completions.scala:19)
at sbt.complete.Completions$$anon$1.get$lzycompute(Completions.scala:27)
at sbt.complete.Completions$$anon$1.get(Completions.scala:27)
at sbt.complete.Completions$$anonfun$map$1.apply(Completions.scala:20)
at sbt.complete.Completions$$anonfun$map$1.apply(Completions.scala:20)
at sbt.complete.Completions$$anon$1.get$lzycompute(Completions.scala:27)
at sbt.complete.Completions$$anon$1.get(Completions.scala:27)
at sbt.complete.Completions$$anonfun$flatMap$1$$anonfun$apply$1.apply(Completions.scala:19)
at sbt.complete.Completions$$anonfun$flatMap$1$$anonfun$apply$1.apply(Completions.scala:19)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.immutable.Set$Set3.foreach(Set.scala:115)
at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:251)
at scala.collection.AbstractTraversable.flatMap(Traversable.scala:105)
at sbt.complete.Completions$$anonfun$flatMap$1.apply(Completions.scala:19)
at sbt.complete.Completions$$anonfun$flatMap$1.apply(Completions.scala:19)
at sbt.complete.Completions$$anon$1.get$lzycompute(Completions.scala:27)
at sbt.complete.Completions$$anon$1.get(Completions.scala:27)
at sbt.complete.Completions$$anonfun$$plus$plus$1.apply(Completions.scala:14)
at sbt.complete.Completions$$anonfun$$plus$plus$1.apply(Completions.scala:14)
at sbt.complete.Completions$$anon$1.get$lzycompute(Completions.scala:27)
at sbt.complete.Completions$$anon$1.get(Completions.scala:27)
at sbt.complete.Completions$$anonfun$$plus$plus$1.apply(Completions.scala:14)
at sbt.complete.Completions$$anonfun$$plus$plus$1.apply(Completions.scala:14)
at sbt.complete.Completions$$anon$1.get$lzycompute(Completions.scala:27)
at sbt.complete.Completions$$anon$1.get(Completions.scala:27)
at sbt.complete.Completions$$anonfun$flatMap$1.apply(Completions.scala:19)
at sbt.complete.Completions$$anonfun$flatMap$1.apply(Completions.scala:19)
at sbt.complete.Completions$$anon$1.get$lzycompute(Completions.scala:27)
at sbt.complete.Completions$$anon$1.get(Completions.scala:27)
at sbt.complete.JLineCompletion$.convertCompletions(JLineCompletion.scala:56)
at sbt.complete.JLineCompletion$$anonfun$parserAsCompletor$1.apply(JLineCompletion.scala:52)
at sbt.complete.JLineCompletion$$anonfun$parserAsCompletor$1.apply(JLineCompletion.scala:52)
at sbt.complete.JLineCompletion$$anonfun$customCompletor$1$$anonfun$2.apply(JLineCompletion.scala:75)
at sbt.complete.JLineCompletion$$anonfun$customCompletor$1$$anonfun$2.apply(JLineCompletion.scala:75)
at sbt.complete.JLineCompletion$.complete(JLineCompletion.scala:94)
at sbt.complete.JLineCompletion$$anonfun$customCompletor$1.apply(JLineCompletion.scala:75)
at sbt.complete.JLineCompletion$$anonfun$customCompletor$1.apply(JLineCompletion.scala:74)
at sbt.complete.JLineCompletion$CustomHandler.complete(JLineCompletion.scala:30)
at jline.console.ConsoleReader.complete(ConsoleReader.java:3082)
at jline.console.ConsoleReader.readLine(ConsoleReader.java:2501)
at jline.console.ConsoleReader.readLine(ConsoleReader.java:2162)
at sbt.JLine.sbt$JLine$$readLineDirectRaw(LineReader.scala:42)
at sbt.JLine$$anonfun$readLineDirect$2.apply(LineReader.scala:34)
at sbt.JLine$$anonfun$readLineDirect$2.apply(LineReader.scala:34)
at sbt.Signals0.withHandler(Signal.scala:81)
at sbt.Signals$.withHandler(Signal.scala:11)
at sbt.JLine.readLineDirect(LineReader.scala:34)
at sbt.JLine.readLineWithHistory(LineReader.scala:27)
at sbt.JLine.sbt$JLine$$unsynchronizedReadLine(LineReader.scala:19)
at sbt.JLine$$anonfun$readLine$1.apply(LineReader.scala:16)
at sbt.JLine$$anonfun$readLine$1.apply(LineReader.scala:16)
at sbt.JLine$$anonfun$withJLine$1.apply(LineReader.scala:114)
at sbt.JLine$$anonfun$withJLine$1.apply(LineReader.scala:112)
at sbt.JLine$.withTerminal(LineReader.scala:86)
at sbt.JLine$.withJLine(LineReader.scala:112)
at sbt.JLine.readLine(LineReader.scala:16)
at sbt.BasicCommands$$anonfun$shell$1.apply(BasicCommands.scala:174)
at sbt.BasicCommands$$anonfun$shell$1.apply(BasicCommands.scala:170)
at sbt.Command$$anonfun$command$1$$anonfun$apply$1.apply(Command.scala:30)
at sbt.Command$$anonfun$command$1$$anonfun$apply$1.apply(Command.scala:30)
at sbt.Command$.process(Command.scala:93)
at sbt.MainLoop$$anonfun$1$$anonfun$apply$1.apply(MainLoop.scala:98)
at sbt.MainLoop$$anonfun$1$$anonfun$apply$1.apply(MainLoop.scala:98)
at sbt.State$$anon$1.process(State.scala:184)
at sbt.MainLoop$$anonfun$1.apply(MainLoop.scala:98)
at sbt.MainLoop$$anonfun$1.apply(MainLoop.scala:98)
at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:17)
at sbt.MainLoop$.next(MainLoop.scala:98)
at sbt.MainLoop$.run(MainLoop.scala:91)
at sbt.MainLoop$$anonfun$runWithNewLog$1.apply(MainLoop.scala:70)
at sbt.MainLoop$$anonfun$runWithNewLog$1.apply(MainLoop.scala:65)
at sbt.Using.apply(Using.scala:24)
at sbt.MainLoop$.runWithNewLog(MainLoop.scala:65)
at sbt.MainLoop$.runAndClearLast(MainLoop.scala:48)
at sbt.MainLoop$.runLoggedLoop(MainLoop.scala:32)
at sbt.MainLoop$.runLogged(MainLoop.scala:24)
at sbt.StandardMain$.runManaged(Main.scala:53)
at sbt.xMain.run(Main.scala:28)
at xsbt.boot.Launch$$anonfun$run$1.apply(Launch.scala:57)
at xsbt.boot.Launch$.withContextLoader(Launch.scala:77)
at xsbt.boot.Launch$.run(Launch.scala:57)
at xsbt.boot.Launch$$anonfun$explicit$1.apply(Launch.scala:45)
at xsbt.boot.Launch$.launch(Launch.scala:65)
at xsbt.boot.Launch$.apply(Launch.scala:16)
at xsbt.boot.Boot$.runImpl(Boot.scala:32)
at xsbt.boot.Boot$.main(Boot.scala:21)
at xsbt.boot.Boot.main(Boot.scala)
Exception occurred while determining completions.
Downgrading to 0.4.0 fixes the problem.
I think 2.11 binaries are not available on bintray.
This probably doesn't work well together. Circle back and make sure.
Is it possible to create links to reference Scala Library classes using the square-bracket syntax (e.g. [[scala.Option]] ) in tut? We're moving some of our scaladoc examples over to md and are seeing many embedded links in the docs.
This will remove the need to specify the tpolecat-sbt-plugin-releases
resolver
Could be tricky since it wants a constant writer.
I feel like I've heard people ask whether Tut can support literate programming in Scala. And when I try to explain my (perennially-unreleased) sbt-plugin for literate programming (https://github.com/non/literati), people always say "Oh, like Tut right?"
It might be nice for me to try to fold my work into Tut (which people have heard about and seems to be getting some momentum) rather than having a totally separate plugin for something that seems very similar (at least on the surface).
The main difference between the two comes down to how the compiler is used.
Tut (AFAIK) wants to paste code into one (or more) REPL sessions to ensure that when a reader opens a REPL, the code examples all work as advertised (at least, with the right classpath). It also wants to (potentially) rewrite your Markdown to show the REPL output you'd expect to see.
Literati wants to transform your markdown file into a Scala file (whose line numbers match), and then run the standard compiler on that, producing bytecode, jars, and so on via managed_src. This ends up looking a lot like codegen. It doesn't transform the Markdown in any way, since the assumption is that the code is compiled, not run.
I could imagine using a Markdown header, like Jekyll does, to "configure" Tut's behavior. This would be the current (default) behavior:
---
mode: repl
---
and this might be a configuration for literate programming:
---
mode: compile
package: my.example.project
---
(Other optional settings might include object: TopLevelObject
or app: TopLevelApp
, to optionally wrap the code in an object (or an object extending App
).)
The nice thing is that we have one tool to do Markdown-related Scala programming. The downside is that these two modes will share almost no code -- their strategies are orthogonal.
What do you think?
I've been trying and failing to get tut to interpret kind-projector's type lambda syntax - it seems like tut just doesn't inherit the project's compiler plugins.
This instinctively feels like it might be related to #17, but I really couldn't tell for sure either way.
Discovered in version 0.4.0.
If a tut shed ends when a normal REPL would prompt for more input, tut doesn't complain that the code is incomplete.
example input (I'm using apostophes because I can't figure out how to escape backticks in GitHub markdown):
'''tut
{
'''
what I see in output:
scala> {
I seem to forget closing braces and hit this often :)
Edit: I had been using tut:silent
a lot and forgot that tut
includes the scala>
prompt in the output, so I wrote an irrelevant detail.
Have you tried scalakata? We are trying to accomplish a similar task.
From the Gitter channel:
@fthomas are there plans to check function / type names outside of tut sheds? I just stumbled about a doc where I've renamed a function but forgot to update the reference in the surrounding description. It would be awesome if tut could also check those.
Maybe a variant of the inline variable substitution people keep asking for? tut is all about aiming low, so what's the simplest thing that might work?
/cc @non
See here.
There doesn't seem to be a way to specify compiler options to tut.
This would for example be useful for cases like this:
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
This results in the following "noisy" output"
scala> trait Functor[F[_]] {
| def map[A, B](fa: F[A])(f: A => B): F[B]
| }
warning: there was one feature warning; re-run with -feature for details
defined trait Functor
I realise that I can bring language.higherKinds
in scope to disable the warning, but that just feels like adding some different kind of noise.
Also, there might very well be a way to do this that I missed, in which case I apologise for wasting your time.
StateT
and IO
probably need to be trampolined.
In one of my tut files I want to show the output of an external process and I'm currently doing it like this:
'''tut
import scala.sys.process._
"z3 -version".!!.trim
'''
which expands to:
scala> import scala.sys.process._
import scala.sys.process._
scala> "z3 -version".!!.trim
res0: String = Z3 version 4.4.0
It would be nice to have something like a shell
option that works like this
'''tut:shell
z3 -version
'''
which expands to:
$ z3 -version
Z3 version 4.4.0
The REPL can show the bytecode of a class or file:
scala> class Foo(i: Int)
defined class Foo
scala> :javap -c Foo
Compiled from "<console>"
public class Foo {
public Foo(int);
Code:
0: aload_0
1: invokespecial #10 // Method java/lang/Object."<init>":()V
4: return
}
It would be awesome if tut could also do this via a tut:javap
modifier or something similar.
Some code snippets generate images as side effects. For instance, at the end of some snippets are expressions like:
[...]
png(chart, "images/attendeesByAge.png")
I'd like the ability to embed that image below the code snippet.
What is the easiest way to configure how the paths in the snippet map to urls?
I would like to have String interpolation in tut template files. I am aware that this is somewhat of a separate concern, and would like to open up the discussion to alternate solutions.
I have though about providing an alternative plugin that can integrate with sbt-site to interpolate files with scala code. Then, however, one would have to modify sbt-site to be able to chain text transformation plugins, since I have a use case where I both want to have tut examples and String interpolation within the same file. This seems reasonable and would be a modular design although there might be some concerns around clashing between plugins and ordering.
In the meantime it might be reasonable to implement the feature directly in tut itself.
Thoughts?
It is sometimes difficult to read the output of the REPL, could it be possible to use something like pprint
def computeFancyPairs[Fancy[_]](fancyX: Fancy[Int], fancyY: Fancy[Int]): Fancy[Int] =
for {
x <- fancyX
y <- fancyY
} yield compute(x,y)
yields
scala> def computeFancyPairs[Fancy[_]](fancyX: Fancy[Int], fancyY: Fancy[Int]): Fancy[Int] =
| for {
| x <- fancyX
| y <- fancyY
| } yield compute(x,y)
<console>:10: error: value flatMap is not a member of type parameter Fancy[Int]
x <- fancyX
^
<console>:11: error: value map is not a member of type parameter Fancy[Int]
y <- fancyY
^
<console>:12: error: not found: value compute
} yield compute(x,y)
^
Not sure if you can see my issue's source, but it starts with <triple-tick>tut:nofail
I find that most of the tut
pages I write need a bunch of import statements that, while necessary, really aren't something I want to bring attention to nor put at the top of my output document. Sometimes you just want to focus on the content and not on the boilerplate required to get to it.
It'd be nice to have to have an invisible
modifier that would execute the code but not display any output.
As mentioned in the docs, tut tries to read all the files (which seems to include directories) under src/main/tut
.
This leads to an exception like the following if any directories are present in src/main/tut
:
[info] Running tut.TutMain /Users/moe/Workspaces/scala/bayes-scala/doc/src/main/tut /Users/moe/Workspaces/scala/bayes-scala/doc/target/scala-2.10/tut
[tut] compiling: /Users/moe/Workspaces/scala/bayes-scala/doc/src/main/tut/1d_kalman_filter
[error] (run-main-3) java.io.FileNotFoundException: /Users/moe/Workspaces/scala/bayes-scala/doc/src/main/tut/1d_kalman_filter (Is a directory)
A related problem occurs if there are non-md files like png images in src/main/tut
:
[info] Running tut.TutMain /Users/moe/Workspaces/scala/bayes-scala/doc/src/main/tut /Users/moe/Workspaces/scala/bayes-scala/doc/target/scala-2.10/tut
[tut] compiling: /Users/moe/Workspaces/scala/bayes-scala/doc/src/main/tut/1d_kalman_filter.md
[tut] compiling: /Users/moe/Workspaces/scala/bayes-scala/doc/src/main/tut/clutter_problem.md
[tut] compiling: /Users/moe/Workspaces/scala/bayes-scala/doc/src/main/tut/clutter_problem.png
[error] (run-main-5) java.nio.charset.MalformedInputException: Input length = 1
Would it be possible to run tut only against .md
files?
Thanks!
Martin
It only looks for .md
files, needs to honor tutNameFilter
.
Would it be possible to make tut only recompile files that have changed?
Currently tut has the :nofail
modifier that will allow examples that fail to compile. I think I always either want to ensure that a given example does compile or that it does not compile. I don't think I ever want to show its output but not care whether or not it compiles.
For example, if I'm showing off my type-safe ===
operator, I probably want one example that shows that 1 === 1
evaluates to true
and one that shows that 1 == 2
evaluates to false
. I probably want another one to show that 1 == "1"
doesn't even compile. If I use :nofail
, I won't be warned if I have a bug and my example actually does compile.
What do you think about a tut:fail
or tut:fails
or similar modifier that will only fail if the example does compile?
It would be nice if there would be a modifier that suppresses the output of import statements. Imports are just repeated in the Scala REPL which is not very useful. So sheds like this:
import scala.collection._
import scala.util._
1 + 1
would be transformed into
scala> import scala.collection._
scala> import scala.util._
scala> 1 + 1
res0: Int = 2
instead of
scala> import scala.collection._
import scala.collection._
scala> import scala.util._
import scala.util._
scala> 1 + 1
res0: Int = 2
So I'm not exactly an expert in dependencies scopes, but it seems that tut should not be transitively pulled if you use a Jar of a library depending on it.
That's especially problematic in Play projects because of this.
As reported by @non
it seems like there is possibly a bug with tutOnly -- i added a new .md file and until i restarted SBT i could not run tutOnly on it. after the restart it was fine.
The command parser looks at the file layout for tab completion when the project loads ... may or may not be able to do this on the fly.
The following code taken verbatim from some documentation I'm trying to tut:fail
import concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
def something[A](futL: Future[List[Int]])(f: Int => A): Future[List[A]] = for{
list <- futL
item <- list //won't compile since "list" isn't a Future and hence, doesn't compose!
} yield f(item)
gives me the following output:
[tut] *** Error reported at Transformers.md:17: failure was asserted but no failure occurred
import concurrent.Future
[tut] *** Error reported at Transformers.md:18: failure was asserted but no failure occurred
import scala.concurrent.ExecutionContext.Implicits.global
I'm assuming this is a bug or is it supposed to be overeager? Removing the :fail
causes the expected compilation errors.
Sometimes it's nice to avoid package namespacing or namemangling and just start again building out abstractions.
I talked to @tpolecat about this on IRC, and he's got the bright idea that it should be optionally a visible REPL reset
I guess it would be something like:
```tut:reset
```
which would become
```
scala> :reset
Resetting interpreter state.
Forgetting all expression results and named terms: $intp
```
and could be mixed with other modifiers like :silent and :invisible.
It would be nice to be more liberal in parsing code sheds:
tut
. So ```````tut` parses.~~~
as a code shed delimiter, as supported by some Markdown parsers.This is a very low priority request.
Really need to do the sbt plugin test thing. It's getting hard to eyeball everything.
Somehow :-)
tut:silent
doesn't work because of the trailing space.
@milessabin asked if types could be rewritten ... perhaps by removing prefixes like shapeless.
or scalaz.
and then rewriting selected type constructors like (::
and \/
) in infix form. Would be nice if this could be done without rewriting the output stream, but so far IMain
has been immune to hacking attempts. Worth another look.
They don't work because compiler errors are worded differently; need specific expect
files for each scala version we're testing.
It would be nice to have a :paste option that would make the entire fence have
the same semantic as a REPL :paste, so we could define companion objects nicely
without boilerplate:
```tut:paste
class A
object A
```
which should probably just yield the normal REPL response:
```
scala> :paste
// Entering paste mode (ctrl-D to finish)
class A
object A
// Exiting paste mode, now interpreting.
defined class A
defined object A
```
And it should mix fine with other modifiers like :silent and :invisible
ideally.
Right now if I am getting a single file working, I have to recompile every .md
file every time. It would be great if there was a documented way to run it for only one file, e.g. tut-only *foo.md
or similar.
There were some REPL changes in 2.11.7 ... nothing that looks like it will break tut but who knows. Need to verify that nothing's broken.
scala.io.StdIn.readLine()
Will cause any tut enable doc to not make progress when running sbt tut
.
Ideally something like
tut:noninteractive
or some other combinator could make it not stop if the Scala REPL supports this (I have not been able to find a way to do so)
You might be interested in linking tut to the sbt organization in bintray so that there wouldn't be a need to add any resolver.
I added the tut v4.0.0 plugin as directed and have a single file: src/main/tut/Foo.md (note I don't have the leading slash there, but was trying to figure out how to escape the triple backticks:
Here is how you add two numbers:
\```tut
1 + 1
\```
When I run tut
, I get this:
[info] Running tut.TutMain /Users/mhughes/ccad/development/ipdc/terminal-topology/src/main/tut /Users/mhughes/ccad/development/ipdc/terminal-topology/target/scala-2.11/tut .*\.(md|txt|htm|html) -deprecation -encoding UTF-8 -feature -unchecked -Xfatal-warnings -Xlint -Yno-adapted-args -Ywarn-numeric-widen -Ywarn-value-discard -Xfuture -target:jvm-1.7 -Ywarn-unused-import -Ywarn-infer-any:false
[info] [tut] compiling: /Users/mhughes/tut-test/src/main/tut/Foo.md
[error] Exception in thread "main" java.lang.NullPointerException
[error] at scala.reflect.internal.SymbolTable.exitingPhase(SymbolTable.scala:256)
[error] at scala.tools.nsc.interpreter.IMain$Request.x$20$lzycompute(IMain.scala:860)
[error] at scala.tools.nsc.interpreter.IMain$Request.x$20(IMain.scala:859)
[error] at scala.tools.nsc.interpreter.IMain$Request.importsPreamble$lzycompute(IMain.scala:859)
[error] at scala.tools.nsc.interpreter.IMain$Request.importsPreamble(IMain.scala:859)
[error] at scala.tools.nsc.interpreter.IMain$Request$Wrapper.preamble(IMain.scala:882)
[error] at scala.tools.nsc.interpreter.IMain$CodeAssembler$$anonfun$apply$23.apply(IMain.scala:1284)
[error] at scala.tools.nsc.interpreter.IMain$CodeAssembler$$anonfun$apply$23.apply(IMain.scala:1283)
[error] at scala.tools.nsc.util.package$.stringFromWriter(package.scala:64)
[error] at scala.tools.nsc.interpreter.IMain$CodeAssembler$class.apply(IMain.scala:1283)
[error] at scala.tools.nsc.interpreter.IMain$Request$Wrapper.apply(IMain.scala:872)
[error] at scala.tools.nsc.interpreter.IMain$Request.compile$lzycompute(IMain.scala:958)
[error] at scala.tools.nsc.interpreter.IMain$Request.compile(IMain.scala:953)
[error] at scala.tools.nsc.interpreter.IMain.compile(IMain.scala:550)
[error] at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:538)
[error] at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:536)
[error] at tut.TutMain$$anonfun$interp$1$$anonfun$apply$52$$anonfun$apply$53$$anonfun$apply$54$$anonfun$apply$55.apply(Tut.scala:218)
[error] at tut.TutMain$$anonfun$interp$1$$anonfun$apply$52$$anonfun$apply$53$$anonfun$apply$54$$anonfun$apply$55.apply(Tut.scala:218)
[error] at tut.Zed$IO$$anonfun$apply$5.apply(Zed.scala:78)
[error] at tut.Zed$IO$$anonfun$apply$5.apply(Zed.scala:78)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$IOOps$$anonfun$ensuring$1.apply(Zed.scala:87)
[error] at tut.Zed$IOOps$$anonfun$ensuring$1.apply(Zed.scala:87)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$map$1.apply(Zed.scala:30)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$State$$anonfun$flatMap$1.apply(Zed.scala:31)
[error] at tut.Zed$IOOps.unsafePerformIO(Zed.scala:88)
[error] at tut.TutMain$.main(Tut.scala:75)
[error] at tut.TutMain.main(Tut.scala)
Hi there! First things first: thanks for publishing this plugin, it's just what I was looking for.
I've got a block of code that I'd like to keep as noise-free as possible, so I want tut
to output only the relevant lines (and nothing more like returned statements), but tut:silent
inserts newlines in between:
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{ Await, Future }
turns into:
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{ Await, Future }
but I just want:
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{ Await, Future }
Is there any way to make that happen or is it by design?
Not an issue, just some ideas that I have across, mostly not pure tut, but related to.
Some of these are easily added via jekyll modules but ghpages does not support all modules. So either the site would have to be pre-processed, the functionality replaced in tut, or just not done.
Or use pandoc.
This is trivial using mathjax, see the cats layout.
Add some yaml lists to the start of the markdown, as for example here in https://github.com/non/cats/issues/403 (who spotted that the tags were yaml Lists?). "Recaps" might be better than "Repeats".
As another example, this scalaz document on the fourth line "As a prerequisite, I assume knowledge of type classes as they are implemented and used in Scala."
Adding a "Requires" tags just helps to in the document management.
There are jekyll plugins for bibtex, and pandoc has this. So rather than link directly, go via URL citations in the CM file/page. This can also be coupled with the previous idea to see that links are not introduced to concepts not marked as Requires or Recaps
Here's my motivation: I don't want to have to pre-compile my Markdown before making them visible on GitHub. I want to be able to just have plain .md
files in my repo, and I want people to be able to view them in final form, with all the code fully intact and highlighting functional.
In short, I want to be able to use scala
blocks in my markdown, but I still want documentation verification. This should take two forms.
First, and most basic, I want the "does it compile" verification that tut provides, but on scala
blocks rather than tut
blocks:
We can use a `Sink` as a "capstone" to a process network:
```scala
import scalaz.stream._
val p = Process constant 1 take 10
(p to io.stdOutLines run).run
```
The above would be checked for compilation only; no output value checks or transformation would be performed. I would just point tut at my doc/
directory and it would check, but not modify, the files that are there. The same "import carryover" features that are currently available for successive tut
blocks in the same document would apply here.
This one takes advantage of an existing convention in the community: denoting line output with // => result
where relevant. Again, no transformation of the files is required, but this would allow a form of unit testing in the documentation. Modifying the above slightly:
The results of `observe` are the values that passed through the `Sink`:
```scala
import scalaz.stream._
val p = Process constant 1 take 10
(p observe io.stdOutLines runLog).run // => Seq(1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
```
The above would be compiled and run, and the output of the last line would be checked against the value to the right of the // =>
, when such a symbolic sequence is found at the end of a line. As in the compile verification case, the build would fail if the output does not match, but even in the event that the build passes, no file modifications (or output files!) would be performed.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.