GithubHelp home page GithubHelp logo

tut's Introduction

tut

This project is archived and unmaintained.

Binaries are unavailable as of May 1, 2021.

Please switch to mdoc. See the migration guide.

tut's People

Contributors

adelbertc avatar aeons avatar ceedubs avatar channingwalton avatar chriscoffey avatar christopherdavenport avatar d6y avatar daddykotex avatar eed3si9n avatar felixmulder avatar fthomas avatar gitter-badger avatar guersam avatar imarios avatar jentsch avatar juanpedromoreno avatar kailuowang avatar kxbmap avatar larsrh avatar metasim avatar nequissimus avatar readmecritic avatar rossabaker avatar ruippeixotog avatar salanki avatar sethtisue avatar slakah avatar stew avatar tpolecat avatar xuwei-k avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tut's Issues

Feature: Cleaner output

To support copy and pasting code from our books we'd like cleaner output from Tut. Specifically:

  • no console prompt cruft. No scala> and no | continuation character.
  • console output is placed within comments

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

Support reference code of other tut code by generating modules or enforcing ordering

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.

0.4.1 breaks sbt's tab completion

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.

Scaladoc linking

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.

Literate programming versus REPL-based tutorials

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?

Adding support for compiler plugins

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.

Incomplete code in tut sheds doesn't fail

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.

scalakata

Have you tried scalakata? We are trying to accomplish a similar task.

Check names outside of sheds?

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

Adding support for compiler flags

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.

shell option that shows the output of external processes

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

Add option to use javap

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.

embed images produced as a side effect

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?

Scala interpolation

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?

fail in a tut:nofail? (v0.3.1)

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

Default / hidden import statements

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.

tut fails if there are any directories under src/main/tut

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

Assert that example fails to compile

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?

Add modifier that suppresses the output of imports

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    

tutOnly requires reload to see new file

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.

tut:fail is failing

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.

:reset option

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.

Feature: More liberal parsing of code sheds

It would be nice to be more liberal in parsing code sheds:

  • allow space between the shed delimiter and tut. So ```````tut` parses.
  • allow ~~~ as a code shed delimiter, as supported by some Markdown parsers.

This is a very low priority request.

Add proper tests :-\

Really need to do the sbt plugin test thing. It's getting hard to eyeball everything.

Type rewriting?

@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.

:paste option

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.

Run tut on a single file?

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.

test with scala 2.11.7

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.

Get NPE when trying to follow README instructions

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)

tut:silent inserts newlines in between lines

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?

Some new feature ideas

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.

Tex support

This is trivial using mathjax, see the cats layout.

Add knowledge metadata

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.

Add Link management via citation 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

Feature Request: Verified, but not compiled, code blocks

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.

Compile Verification

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.

Output Verification

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.