├── .git-blame-ignore-revs
├── .github
├── FUNDING.yml
├── dependabot.yml
└── workflows
│ ├── publish-artifacts.yml
│ └── run-tests.yml
├── .gitignore
├── .mill-version
├── .scalafmt.conf
├── LICENSE
├── amm-template.sh
├── amm
├── compiler
│ ├── interface
│ │ └── src
│ │ │ └── main
│ │ │ └── scala
│ │ │ └── ammonite
│ │ │ └── compiler
│ │ │ └── iface
│ │ │ ├── CodeWrapper.scala
│ │ │ ├── Compiler.scala
│ │ │ ├── CompilerBuilder.scala
│ │ │ ├── CompilerLifecycleManager.scala
│ │ │ ├── Parser.scala
│ │ │ └── Preprocessor.scala
│ └── src
│ │ ├── main
│ │ ├── scala-2.12.0_12
│ │ │ └── ammonite
│ │ │ │ └── compiler
│ │ │ │ └── CompilerCompatibility.scala
│ │ ├── scala-2.12.0_8
│ │ │ └── ammonite
│ │ │ │ └── compiler
│ │ │ │ └── ExtraCompilerCompatibility.scala
│ │ ├── scala-2.12.10-2.13.1+
│ │ │ └── scala
│ │ │ │ └── tools
│ │ │ │ └── nsc
│ │ │ │ ├── AmmClassPath.scala
│ │ │ │ └── WhiteListClasspath.scala
│ │ ├── scala-2.12.13+
│ │ │ └── ammonite
│ │ │ │ └── compiler
│ │ │ │ ├── CompilerCompatibility.scala
│ │ │ │ └── MakeReporter.scala
│ │ ├── scala-2.12.9+
│ │ │ └── ammonite
│ │ │ │ └── compiler
│ │ │ │ └── ExtraCompilerCompatibility.scala
│ │ ├── scala-2.13.1-2.13.11
│ │ │ └── ammonite
│ │ │ │ └── compiler
│ │ │ │ └── MakeReporter.scala
│ │ ├── scala-2.13.12+
│ │ │ └── ammonite
│ │ │ │ └── compiler
│ │ │ │ └── MakeReporter.scala
│ │ ├── scala-2.13
│ │ │ └── ammonite
│ │ │ │ └── compiler
│ │ │ │ └── CompilerCompatibility.scala
│ │ ├── scala-2
│ │ │ ├── ammonite
│ │ │ │ └── compiler
│ │ │ │ │ ├── AmmonitePlugin.scala
│ │ │ │ │ ├── Compiler.scala
│ │ │ │ │ ├── CompilerBuilder.scala
│ │ │ │ │ ├── CompilerExtensions.scala
│ │ │ │ │ ├── CompilerLifecycleManager.scala
│ │ │ │ │ ├── DefaultPreprocessor.scala
│ │ │ │ │ ├── Highlighter.scala
│ │ │ │ │ ├── Parsers.scala
│ │ │ │ │ ├── Pressy.scala
│ │ │ │ │ ├── internal
│ │ │ │ │ └── CustomURLZipArchive.scala
│ │ │ │ │ └── tools
│ │ │ │ │ ├── HighlightJava.scala
│ │ │ │ │ ├── SourceRuntime.scala
│ │ │ │ │ ├── desugar.scala
│ │ │ │ │ └── source.scala
│ │ │ └── scala
│ │ │ │ └── tools
│ │ │ │ └── nsc
│ │ │ │ └── CustomZipAndJarFileLookupFactory.scala
│ │ ├── scala-3.0.0-3.3.1
│ │ │ ├── ammonite
│ │ │ │ └── compiler
│ │ │ │ │ ├── AmmonitePhase.scala
│ │ │ │ │ ├── Compiler.scala
│ │ │ │ │ ├── DirectoryClassPath.scala
│ │ │ │ │ ├── Preprocessor.scala
│ │ │ │ │ └── SyntaxHighlighting.scala
│ │ │ └── dotty
│ │ │ │ └── ammonite
│ │ │ │ └── compiler
│ │ │ │ └── AmmCompletion.scala
│ │ ├── scala-3.0.0-3.6.2
│ │ │ └── ammonite
│ │ │ │ └── compiler
│ │ │ │ └── DottyParser.scala
│ │ ├── scala-3.3.2+
│ │ │ ├── ammonite
│ │ │ │ └── compiler
│ │ │ │ │ ├── AmmonitePhase.scala
│ │ │ │ │ ├── Compiler.scala
│ │ │ │ │ ├── DirectoryClassPath.scala
│ │ │ │ │ ├── Preprocessor.scala
│ │ │ │ │ └── SyntaxHighlighting.scala
│ │ │ └── dotty
│ │ │ │ └── ammonite
│ │ │ │ └── compiler
│ │ │ │ └── AmmCompletion.scala
│ │ ├── scala-3.4.2+
│ │ │ ├── ammonite
│ │ │ │ └── compiler
│ │ │ │ │ ├── AmmonitePhase.scala
│ │ │ │ │ ├── Compiler.scala
│ │ │ │ │ ├── DirectoryClassPath.scala
│ │ │ │ │ ├── Preprocessor.scala
│ │ │ │ │ └── SyntaxHighlighting.scala
│ │ │ └── dotty
│ │ │ │ └── ammonite
│ │ │ │ └── compiler
│ │ │ │ └── AmmCompletion.scala
│ │ ├── scala-3.5.0+
│ │ │ ├── ammonite
│ │ │ │ └── compiler
│ │ │ │ │ ├── AmmonitePhase.scala
│ │ │ │ │ ├── Compiler.scala
│ │ │ │ │ ├── DirectoryClassPath.scala
│ │ │ │ │ ├── Preprocessor.scala
│ │ │ │ │ └── SyntaxHighlighting.scala
│ │ │ └── dotty
│ │ │ │ └── ammonite
│ │ │ │ └── compiler
│ │ │ │ └── AmmCompletion.scala
│ │ ├── scala-3.6.3+
│ │ │ └── ammonite
│ │ │ │ └── compiler
│ │ │ │ └── DottyParser.scala
│ │ ├── scala-3
│ │ │ ├── ammonite
│ │ │ │ └── compiler
│ │ │ │ │ ├── AsmPositionUpdater.scala
│ │ │ │ │ ├── CompatibilityParser.scala
│ │ │ │ │ ├── CompilerBuilder.scala
│ │ │ │ │ ├── CompilerExtensions.scala
│ │ │ │ │ ├── CompilerLifecycleManager.scala
│ │ │ │ │ ├── Extensions.scala
│ │ │ │ │ ├── Parsers.scala
│ │ │ │ │ ├── internal
│ │ │ │ │ └── CompilerHelper.scala
│ │ │ │ │ └── tools
│ │ │ │ │ ├── desugar.scala
│ │ │ │ │ └── source.scala
│ │ │ └── dotty
│ │ │ │ └── ammonite
│ │ │ │ └── compiler
│ │ │ │ ├── AmmCompletionExtras.scala
│ │ │ │ └── WhiteListClassPath.scala
│ │ ├── scala-not-2.12.10-2.13.1+
│ │ │ └── scala
│ │ │ │ └── tools
│ │ │ │ └── nsc
│ │ │ │ ├── AmmClassPath.scala
│ │ │ │ └── WhiteListClasspath.scala
│ │ ├── scala-not-2.12.13+-2.13.1+
│ │ │ └── ammonite
│ │ │ │ └── compiler
│ │ │ │ └── MakeReporter.scala
│ │ └── scala
│ │ │ └── ammonite
│ │ │ └── compiler
│ │ │ ├── CodeClassWrapper.scala
│ │ │ ├── CompilerUtil.scala
│ │ │ └── DefaultCodeWrapper.scala
│ │ └── test
│ │ ├── scala-2
│ │ └── ammonite
│ │ │ └── compiler
│ │ │ └── test
│ │ │ └── CompilerTestExtensions.scala
│ │ └── scala-3
│ │ └── ammonite
│ │ └── compiler
│ │ └── test
│ │ └── CompilerTestExtensions.scala
├── helper
│ └── src
│ │ └── main
│ │ └── scala-3
│ │ └── ammonite
│ │ └── helper
│ │ └── Helper.scala
├── interp
│ ├── api
│ │ └── src
│ │ │ └── main
│ │ │ └── scala
│ │ │ └── ammonite
│ │ │ ├── Stubs.scala
│ │ │ └── interp
│ │ │ └── api
│ │ │ ├── APIHolder.scala
│ │ │ ├── AmmoniteExit.scala
│ │ │ ├── InterpAPI.scala
│ │ │ └── IvyConstructor.scala
│ └── src
│ │ └── main
│ │ └── scala
│ │ └── ammonite
│ │ └── interp
│ │ ├── DependencyLoader.scala
│ │ ├── Interpreter.scala
│ │ ├── IvyThing.scala
│ │ ├── PredefInitialization.scala
│ │ ├── Watchable.scala
│ │ └── script
│ │ ├── AmmoniteBuildServer.scala
│ │ ├── Diagnostic.scala
│ │ ├── DummyBuildServerImplems.scala
│ │ ├── Script.scala
│ │ ├── ScriptCache.scala
│ │ ├── ScriptCompileResult.scala
│ │ ├── ScriptCompiler.scala
│ │ ├── ScriptProcessor.scala
│ │ ├── SemanticdbProcessor.scala
│ │ └── SingleScriptCompiler.scala
├── repl
│ ├── api
│ │ └── src
│ │ │ └── main
│ │ │ ├── scala-2.12
│ │ │ └── ammonite
│ │ │ │ └── repl
│ │ │ │ └── api
│ │ │ │ └── History.scala
│ │ │ ├── scala-2.13-or-3
│ │ │ └── ammonite
│ │ │ │ └── repl
│ │ │ │ └── api
│ │ │ │ └── History.scala
│ │ │ ├── scala-2
│ │ │ └── ammonite
│ │ │ │ └── repl
│ │ │ │ ├── FullReplAPIScalaVersionSpecific.scala
│ │ │ │ └── api
│ │ │ │ └── ReplAPIScalaVersionSpecific.scala
│ │ │ ├── scala-3
│ │ │ └── ammonite
│ │ │ │ └── repl
│ │ │ │ ├── FullReplAPIScalaVersionSpecific.scala
│ │ │ │ └── api
│ │ │ │ └── ReplAPIScalaVersionSpecific.scala
│ │ │ └── scala
│ │ │ └── ammonite
│ │ │ ├── repl
│ │ │ ├── FullReplAPI.scala
│ │ │ ├── api
│ │ │ │ ├── FrontEnd.scala
│ │ │ │ ├── FrontEndAPI.scala
│ │ │ │ ├── ReplAPI.scala
│ │ │ │ └── SessionChanged.scala
│ │ │ └── tools
│ │ │ │ └── Util.scala
│ │ │ └── runtime
│ │ │ └── tools
│ │ │ ├── Tools.scala
│ │ │ └── package.scala
│ └── src
│ │ ├── main
│ │ ├── scala-2
│ │ │ └── ammonite
│ │ │ │ └── main
│ │ │ │ └── DefaultsScalaVersionSpecific.scala
│ │ ├── scala-3
│ │ │ └── ammonite
│ │ │ │ └── main
│ │ │ │ └── DefaultsScalaVersionSpecific.scala
│ │ └── scala
│ │ │ └── ammonite
│ │ │ ├── main
│ │ │ └── Defaults.scala
│ │ │ └── repl
│ │ │ ├── AmmoniteFrontEnd.scala
│ │ │ ├── ApiImpls.scala
│ │ │ ├── FrontEndUtils.scala
│ │ │ ├── FrontEnds.scala
│ │ │ ├── PPrints.scala
│ │ │ ├── Repl.scala
│ │ │ ├── Signaller.scala
│ │ │ └── package.scala
│ │ └── test
│ │ ├── scala-2.12
│ │ └── ammonite
│ │ │ └── unit
│ │ │ └── SourceTests212.scala
│ │ └── scala
│ │ └── ammonite
│ │ ├── DualTestRepl.scala
│ │ ├── SerializationUtil.scala
│ │ ├── TestRepl.scala
│ │ ├── TestReplBridge.scala
│ │ ├── TestUtils.scala
│ │ ├── interp
│ │ ├── AutocompleteTests.scala
│ │ └── PrintTests.scala
│ │ ├── session
│ │ ├── AdvancedTests.scala
│ │ ├── BuiltinTests.scala
│ │ ├── EulerTests.scala
│ │ ├── EvaluatorTests.scala
│ │ ├── FailureTests.scala
│ │ ├── ImportHookTests.scala
│ │ ├── ImportTests.scala
│ │ ├── ProjectTests.scala
│ │ └── SerializationTests.scala
│ │ ├── testcode
│ │ └── PaulpImports.scala
│ │ └── unit
│ │ ├── ClipboardTests.scala
│ │ ├── HighlightTests.scala
│ │ ├── ParserTests.scala
│ │ └── SourceTests.scala
├── runtime
│ └── src
│ │ └── main
│ │ └── scala
│ │ └── ammonite
│ │ └── runtime
│ │ ├── ClassLoaders.scala
│ │ ├── Evaluator.scala
│ │ ├── ImportHook.scala
│ │ ├── Storage.scala
│ │ └── package.scala
├── src
│ ├── main
│ │ └── scala
│ │ │ └── ammonite
│ │ │ ├── AmmoniteMain.scala
│ │ │ ├── Main.scala
│ │ │ ├── MainRunner.scala
│ │ │ └── main
│ │ │ ├── Config.scala
│ │ │ ├── ProxyFromEnv.scala
│ │ │ ├── Scripts.scala
│ │ │ ├── TrapExitSecurityManager.scala
│ │ │ └── package.scala
│ └── test
│ │ ├── resources
│ │ ├── bsp
│ │ │ ├── comment
│ │ │ │ └── script.sc
│ │ │ ├── dash-1
│ │ │ │ └── main-1.sc
│ │ │ ├── error
│ │ │ │ ├── error-and-invalid-import-file.sc
│ │ │ │ ├── foo.sc
│ │ │ │ └── invalid-import-file.sc
│ │ │ ├── import-file
│ │ │ │ ├── lib.sc
│ │ │ │ └── script.sc
│ │ │ ├── multi
│ │ │ │ ├── lib1.sc
│ │ │ │ ├── lib2.sc
│ │ │ │ ├── lib3.sc
│ │ │ │ └── script.sc
│ │ │ ├── semdb
│ │ │ │ ├── other.sc
│ │ │ │ └── script.sc
│ │ │ └── simple
│ │ │ │ └── script.sc
│ │ ├── importHooks
│ │ │ ├── Basic.sc
│ │ │ ├── BasicTwo.sc
│ │ │ ├── Deep.sc
│ │ │ ├── DeepImport.sc
│ │ │ ├── FileImport.sc
│ │ │ ├── IndirectFileImport.sc
│ │ │ ├── IvyImport.sc
│ │ │ └── UrlImport.sc
│ │ ├── lineNumbers
│ │ │ ├── CompilationErrorLineNumberTest.sc
│ │ │ ├── ErrorLineNumberTest.sc
│ │ │ ├── MultipleCompilationUnitErrorMsgTest1.sc
│ │ │ ├── MultipleCompilationUnitErrorMsgTest2.sc
│ │ │ ├── RuntimeCompilationErrorLineNumberTest.sc
│ │ │ ├── compilationErrorInClass.sc
│ │ │ ├── compilationErrorInFourthBlock.sc
│ │ │ ├── compilationErrorInSecondBlock.sc
│ │ │ ├── compilationErrorWithCommentsAtTop.sc
│ │ │ └── sourceCodeMetadata.sc
│ │ ├── loadable
│ │ │ └── hello
│ │ │ │ └── Hello.java
│ │ ├── mains
│ │ │ ├── ArgList.sc
│ │ │ ├── Args.sc
│ │ │ ├── Args2.sc
│ │ │ ├── CompilerCrash.sc
│ │ │ ├── Hello.sc
│ │ │ ├── Main.sc
│ │ │ ├── MultiMain.sc
│ │ │ ├── MultiMainDoc.sc
│ │ │ └── Varargs.sc
│ │ ├── scriptCompilerSettings
│ │ │ ├── configureCompiler.sc
│ │ │ ├── preConfigureCompiler.sc
│ │ │ ├── yRangepos.sc
│ │ │ └── yRangeposError.sc
│ │ ├── scriptLevelCaching
│ │ │ ├── QuickSort.sc
│ │ │ ├── fileToBeImported.sc
│ │ │ ├── ivyCacheTest.sc
│ │ │ ├── ivyCachedResourceTest.sc
│ │ │ ├── runTimeExceptions.sc
│ │ │ ├── scriptOne.sc
│ │ │ ├── scriptToBeLoaded.sc
│ │ │ ├── scriptTwo.sc
│ │ │ ├── testFileImport.sc
│ │ │ └── testLoadModule.sc
│ │ ├── scripts
│ │ │ ├── Annotation.sc
│ │ │ ├── BlockSepSyntax.sc
│ │ │ ├── CompilationError.sc
│ │ │ ├── Encapsulation.sc
│ │ │ ├── LimitImports.sc
│ │ │ ├── LoadIvy.sc
│ │ │ ├── MultiBlockError.sc
│ │ │ ├── MultilineSheBang.sc
│ │ │ ├── NestedScripts.sc
│ │ │ ├── OneBlock.sc
│ │ │ ├── PreserveImports.sc
│ │ │ ├── Resolvers.sc
│ │ │ ├── ResolversFail.sc
│ │ │ ├── ResolversStatic.sc
│ │ │ ├── ScriptDontUnwrap.sc
│ │ │ ├── SheBang.sc
│ │ │ ├── SyntaxError.sc
│ │ │ ├── TagBase.sc
│ │ │ ├── TagPrevCommand.sc
│ │ │ ├── ThreeBlocks.sc
│ │ │ ├── TwoBlocks.sc
│ │ │ ├── cachedCompilerInit.sc
│ │ │ ├── caching
│ │ │ │ ├── scalatagsPredef.sc
│ │ │ │ └── scalatagsScript.sc
│ │ │ ├── loadIvyAdvanced.sc
│ │ │ └── predefWithLoad
│ │ │ │ ├── Loaded.sc
│ │ │ │ ├── PredefLoadExec.sc
│ │ │ │ ├── PredefLoadModule.sc
│ │ │ │ └── PredefMagicImport.sc
│ │ └── testdata
│ │ │ ├── Resume.docx
│ │ │ └── images
│ │ │ ├── GettingStarted.png
│ │ │ ├── Highlighting.png
│ │ │ └── SystemShell.png
│ │ └── scala
│ │ └── ammonite
│ │ ├── interp
│ │ ├── CachingTests.scala
│ │ ├── CompilerSettingsTests.scala
│ │ ├── YRangeposTests.scala
│ │ └── script
│ │ │ ├── AmmoniteBuildServerTests.scala
│ │ │ └── TestBuildClient.scala
│ │ ├── main
│ │ ├── InProcessMainMethodRunner.scala
│ │ ├── InProcessMainMethodRunnerRawArgs.scala
│ │ ├── LineNumberTests.scala
│ │ └── MainTests.scala
│ │ ├── readme.md
│ │ └── session
│ │ └── ScriptTests.scala
└── util
│ └── src
│ └── main
│ ├── java
│ └── io
│ │ └── github
│ │ └── retronym
│ │ └── java9rtexport
│ │ ├── Copy.java
│ │ └── Export.java
│ └── scala
│ └── ammonite
│ └── util
│ ├── Classpath.scala
│ ├── Frame.scala
│ ├── Imports.scala
│ ├── Model.scala
│ ├── Position.scala
│ ├── PositionOffsetConversion.scala
│ ├── ReplClassLoader.scala
│ ├── Res.scala
│ ├── Util.scala
│ └── WhiteListClassLoader.scala
├── build.mill
├── build.sbt
├── ci
├── deploy_master_docs.sh
├── package.mill
└── upload.mill
├── integration
└── src
│ └── test
│ ├── resources
│ ├── ammonite
│ │ └── integration
│ │ │ ├── basic
│ │ │ ├── Complex.sc
│ │ │ ├── Failure.sc
│ │ │ ├── Hello.sc
│ │ │ ├── HttpApi.sc
│ │ │ ├── MultiMain.sc
│ │ │ ├── PlayFramework.sc
│ │ │ ├── Print.sc
│ │ │ ├── QuickSort.sc
│ │ │ ├── Resources.sc
│ │ │ ├── SourceDownload.sc
│ │ │ ├── Spark.sc
│ │ │ ├── Spark2.json
│ │ │ ├── Spark2.sc
│ │ │ ├── Varargs.sc
│ │ │ ├── http-api-data.json
│ │ │ ├── ivyResolveItv1.sc
│ │ │ ├── ivyResolveItv2.sc
│ │ │ ├── ivyResolveSnapshot1.sc
│ │ │ ├── ivyResolveSnapshot2.sc
│ │ │ ├── scalaTags.sc
│ │ │ └── wrongIvyCordinates.sc
│ │ │ ├── errorTruncation
│ │ │ ├── compileError.sc
│ │ │ ├── compileErrorMultiExpr.sc
│ │ │ ├── parseError.sc
│ │ │ └── runtimeError.sc
│ │ │ └── lineNumbers
│ │ │ └── compilationErrorInSecondBlock.sc
│ └── some-dummy-library
│ │ ├── build.sbt
│ │ └── project
│ │ └── build.properties
│ ├── scala-2.13
│ └── ammonite
│ │ └── integration
│ │ └── ProjectTests213.scala
│ └── scala
│ └── ammonite
│ └── integration
│ ├── AmmoniteBridge.scala
│ ├── BasicTests.scala
│ ├── ErrorTruncationTests.scala
│ ├── LineNumberTests.scala
│ ├── ProjectTests.scala
│ ├── TestMain.scala
│ └── TestUtils.scala
├── internals-docs
├── layering.md
├── packages.md
└── predef.md
├── mill
├── project
├── build.properties
└── plugins.sbt
├── readme.md
├── readme
├── ANSI.scala
├── Cookbook.scalatex
├── Footer.scalatex
├── Index.scalatex
├── Repl.scalatex
├── Sample.scala
├── Scripts.scalatex
└── resources
│ ├── Browse.gif
│ ├── ColoredTraces.png
│ ├── Debugging.png
│ ├── DebuggingViaSshd.png
│ ├── Desugar.png
│ ├── Editing.gif
│ ├── GettingStarted.png
│ ├── Highlighting.png
│ ├── HistorySearch.gif
│ ├── IvyComplete.gif
│ ├── ScriptFolderLayout.png
│ ├── ScriptRepl.gif
│ ├── Source.gif
│ ├── Swing1.png
│ ├── Swing2.png
│ ├── Swing3.png
│ ├── SystemShell.png
│ ├── UndoRedo.gif
│ ├── Watch.gif
│ ├── favicon-old.png
│ ├── favicon.png
│ ├── smaller-favicon.png
│ └── square-favicon.png
├── sshd
└── src
│ ├── main
│ └── scala
│ │ └── ammonite
│ │ └── sshd
│ │ ├── ShellSession.scala
│ │ ├── SshServer.scala
│ │ ├── SshServerConfig.scala
│ │ ├── SshdRepl.scala
│ │ └── util
│ │ └── Environment.scala
│ └── test
│ └── scala
│ └── ammonite
│ └── sshd
│ ├── Main.scala
│ ├── ScalaCheckSupport.scala
│ ├── SshServerTests.scala
│ ├── SshTestingUtils.scala
│ └── SshdReplTest.scala
└── terminal
└── src
├── main
└── scala
│ └── ammonite
│ └── terminal
│ ├── ConsoleDim.scala
│ ├── Filter.scala
│ ├── FilterTools.scala
│ ├── LineReader.scala
│ ├── Protocol.scala
│ ├── SpecialKeys.scala
│ ├── Terminal.scala
│ ├── Utils.scala
│ └── filters
│ ├── BasicFilters.scala
│ ├── GUILikeFilters.scala
│ ├── HistoryFilter.scala
│ ├── ReadlineFilters.scala
│ └── UndoFilter.scala
└── test
├── resource
└── toobig.txt
└── scala
└── ammonite
└── terminal
├── Checker.scala
├── EditTests.scala
├── HeightTests.scala
├── HistoryTests.scala
├── NavigationTests.scala
└── TestMain.scala
/.git-blame-ignore-revs:
--------------------------------------------------------------------------------
1 | # Reformatted scala code
2 | 78d98a149f2a4d7ad81f398edc72475a4fe8c5bf
3 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: lihaoyi
4 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # documentation for all configuration options:
2 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
3 |
4 | version: 2
5 | updates:
6 | - package-ecosystem: "github-actions"
7 | directory: "/"
8 | schedule:
9 | interval: "weekly"
10 |
--------------------------------------------------------------------------------
/.github/workflows/publish-artifacts.yml:
--------------------------------------------------------------------------------
1 | name: Publish Artifacts
2 |
3 | on:
4 | push:
5 | tags:
6 | - '**'
7 | workflow_dispatch:
8 |
9 | jobs:
10 | publish-maven:
11 |
12 | runs-on: ubuntu-latest
13 | env:
14 | MILL_SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
15 | MILL_SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
16 | MILL_PGP_SECRET_BASE64: ${{ secrets.SONATYPE_PGP_PRIVATE_KEY }}
17 | MILL_PGP_PASSPHRASE: ${{ secrets.SONATYPE_PGP_PRIVATE_KEY_PASSWORD }}
18 | LANG: "en_US.UTF-8"
19 | LC_MESSAGES: "en_US.UTF-8"
20 | LC_ALL: "en_US.UTF-8"
21 |
22 | steps:
23 | - uses: actions/checkout@v4
24 | - uses: actions/setup-java@v3
25 | with:
26 | distribution: 'temurin'
27 | java-version: 11
28 | - name: Publish to Maven Central
29 | run: ./mill -i mill.scalalib.PublishModule/
30 |
31 | publish-docs:
32 | runs-on: ubuntu-latest
33 | env:
34 | DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
35 | steps:
36 | - uses: actions/checkout@v4
37 | with:
38 | fetch-depth: 0
39 | - uses: actions/setup-java@v4
40 | with:
41 | java-version: '11'
42 | distribution: temurin
43 |
44 | - name: Setup sbt launcher
45 | uses: sbt/setup-sbt@v1
46 |
47 | - name: publish docs
48 | shell: 'script -q -e -c "bash {0}"'
49 | run: echo "Hello World" && ./mill -i publishDocs
50 | env:
51 | TERM: xterm-256color
52 |
53 | publish-executable:
54 | runs-on: ubuntu-latest
55 | env:
56 | AMMONITE_BOT_AUTH_TOKEN: ${{ secrets.AMMONITE_BOT_AUTH_TOKEN }}
57 | steps:
58 | - uses: actions/checkout@v4
59 | with:
60 | fetch-depth: 0
61 | - uses: actions/setup-java@v4
62 | with:
63 | java-version: '11'
64 | distribution: temurin
65 | - run: ./mill -i publishExecutable
66 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | *.iml
3 | .idea
4 | .settings
5 | .classpath
6 | .project
7 | .cache
8 | .sbtserver
9 | project/.sbtserver
10 | tags
11 | nohup.out
12 | out
13 | .bloop
14 | .vscode
15 | .metals
16 | .bsp
17 |
--------------------------------------------------------------------------------
/.mill-version:
--------------------------------------------------------------------------------
1 | 0.12.0
2 |
--------------------------------------------------------------------------------
/.scalafmt.conf:
--------------------------------------------------------------------------------
1 | # Newer versions won't work with Java 8!
2 | version = "3.7.15"
3 |
4 | align.openParenCallSite = false
5 | align.preset = none
6 | align.stripMargin = true
7 |
8 | assumeStandardLibraryStripMargin = true
9 |
10 | continuationIndent.callSite = 2
11 | continuationIndent.defnSite = 4
12 |
13 | docstrings.oneline = keep
14 | docstrings.style = Asterisk
15 | docstrings.wrap = no
16 |
17 | maxColumn = 100
18 |
19 | newlines.source = keep
20 |
21 | project.git = true
22 |
23 | runner.dialect = scala213
24 |
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2015 Li Haoyi (haoyi.sg@gmail.com)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/amm-template.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # This is a wrapper script, that automatically download ammonite from GitHub release pages
4 | # You can give the required ammonite version with AMM_VERSION env variable
5 | # If no version is given, it falls back to the value of DEFAULT_AMM_VERSION
6 | DEFAULT_AMM_VERSION=
7 | DEFAULT_SCALA_VERSION=
8 | set -e
9 |
10 | if [ -z "$AMM_VERSION" ] ; then
11 | AMM_VERSION=$DEFAULT_AMM_VERSION
12 | fi
13 | if [ -z "$SCALA_VERSION" ] ; then
14 | SCALA_VERSION=$DEFAULT_SCALA_VERSION
15 | fi
16 |
17 | if [ "x${XDG_CACHE_HOME}" != "x" ] ; then
18 | AMM_DOWNLOAD_PATH="${XDG_CACHE_HOME}/ammonite/download"
19 | else
20 | AMM_DOWNLOAD_PATH="${HOME}/.cache/ammonite/download"
21 | fi
22 | AMM_EXEC_PATH="${AMM_DOWNLOAD_PATH}/${AMM_VERSION}_$SCALA_VERSION"
23 |
24 | if [ ! -x "$AMM_EXEC_PATH" ] ; then
25 | mkdir -p $AMM_DOWNLOAD_PATH
26 | DOWNLOAD_FILE=$AMM_EXEC_PATH-tmp-download
27 | AMM_VERSION_TAG=$(echo $AMM_VERSION | sed -E 's/([^-]+)(-M[0-9]+)?(-.*)?/\1\2/')
28 | AMM_DOWNLOAD_URL="https://github.com/lihaoyi/ammonite/releases/download/${AMM_VERSION_TAG}/$SCALA_VERSION-$AMM_VERSION"
29 | curl --fail -L -o "$DOWNLOAD_FILE" "$AMM_DOWNLOAD_URL"
30 | chmod +x "$DOWNLOAD_FILE"
31 | mv "$DOWNLOAD_FILE" "$AMM_EXEC_PATH"
32 | unset DOWNLOAD_FILE
33 | unset AMM_DOWNLOAD_URL
34 | fi
35 |
36 | unset AMM_DOWNLOAD_PATH
37 | unset AMM_VERSION
38 |
39 | exec $AMM_EXEC_PATH "$@"
40 |
--------------------------------------------------------------------------------
/amm/compiler/interface/src/main/scala/ammonite/compiler/iface/CodeWrapper.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler.iface
2 |
3 | import ammonite.util.{Imports, Name}
4 | import ammonite.util.Util.CodeSource
5 |
6 | abstract class CodeWrapper {
7 | def wrapperPath: Seq[Name] = Nil
8 | def apply(
9 | code: String,
10 | source: CodeSource,
11 | imports: Imports,
12 | printCode: String,
13 | indexedWrapper: Name,
14 | extraCode: String
15 | ): (String, String, Int)
16 |
17 | def wrapCode(
18 | codeSource: CodeSource,
19 | indexedWrapperName: Name,
20 | code: String,
21 | printCode: String,
22 | imports: Imports,
23 | extraCode: String,
24 | markScript: Boolean
25 | ) = {
26 |
27 | // we need to normalize topWrapper and bottomWrapper in order to ensure
28 | // the snippets always use the platform-specific newLine
29 | val extraCode0 =
30 | if (markScript) extraCode + "/**/"
31 | else extraCode
32 | val (topWrapper, bottomWrapper, userCodeNestingLevel) =
33 | apply(code, codeSource, imports, printCode, indexedWrapperName, extraCode0)
34 | val (topWrapper0, bottomWrapper0) =
35 | if (markScript) (topWrapper + "/**/ /**/" + bottomWrapper)
36 | else (topWrapper, bottomWrapper)
37 | val importsLen = topWrapper0.length
38 |
39 | (topWrapper0 + code + bottomWrapper0, importsLen, userCodeNestingLevel)
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/amm/compiler/interface/src/main/scala/ammonite/compiler/iface/Compiler.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler.iface
2 |
3 | import ammonite.util.{Imports, Printer}
4 |
5 | abstract class Compiler {
6 |
7 | def compile(
8 | src: Array[Byte],
9 | printer: Printer,
10 | importsLen: Int,
11 | userCodeNestingLevel: Int,
12 | fileName: String
13 | ): Option[Compiler.Output]
14 |
15 | def preprocessor(fileName: String, markGeneratedSections: Boolean = false): Preprocessor
16 |
17 | }
18 |
19 | object Compiler {
20 |
21 | case class Output(
22 | classFiles: Vector[(String, Array[Byte])],
23 | imports: Imports,
24 | usedEarlierDefinitions: Option[Seq[String]]
25 | )
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/amm/compiler/interface/src/main/scala/ammonite/compiler/iface/CompilerBuilder.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler.iface
2 |
3 | import java.net.URL
4 | import java.nio.file.Path
5 |
6 | import ammonite.util.Frame
7 |
8 | abstract class CompilerBuilder {
9 |
10 | def newManager(
11 | rtCacheDir: Option[Path],
12 | headFrame: => Frame,
13 | dependencyCompleter: => Option[String => (Int, Seq[String])],
14 | whiteList: Set[Seq[String]],
15 | initialClassLoader: ClassLoader,
16 | settings: Seq[String]
17 | ): CompilerLifecycleManager
18 |
19 | def create(
20 | initialClassPath: Seq[URL],
21 | classPath: Seq[URL],
22 | dynamicClassPath: Seq[(String, Array[Byte])],
23 | evalClassLoader: ClassLoader,
24 | pluginClassLoader: ClassLoader,
25 | reporter: Option[CompilerBuilder.Message => Unit],
26 | settings: Seq[String],
27 | classPathWhiteList: Set[Seq[String]],
28 | lineNumberModifier: Boolean
29 | ): Compiler
30 |
31 | def scalaVersion: String
32 | }
33 |
34 | object CompilerBuilder {
35 |
36 | case class Message(
37 | severity: String,
38 | start: Int,
39 | end: Int,
40 | message: String
41 | )
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/amm/compiler/interface/src/main/scala/ammonite/compiler/iface/CompilerLifecycleManager.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler.iface
2 |
3 | import java.nio.file.Path
4 |
5 | import ammonite.util.{Frame, Printer}
6 | import ammonite.util.Util.ClassFiles
7 |
8 | abstract class CompilerLifecycleManager {
9 | def compiler: Compiler
10 | def compilationCount: Int
11 |
12 | def preprocess(fileName: String): Preprocessor
13 |
14 | def scalaVersion: String
15 |
16 | def outputDir: Option[Path]
17 |
18 | def init(force: Boolean = false): Unit
19 |
20 | def complete(
21 | offset: Int,
22 | previousImports: String,
23 | snippet: String
24 | ): (Int, Seq[String], Seq[String])
25 |
26 | def compileClass(
27 | processed: Preprocessor.Output,
28 | printer: Printer,
29 | fileName: String
30 | ): Option[Compiler.Output]
31 |
32 | def addToClasspath(classFiles: ClassFiles): Unit
33 |
34 | def shutdownPressy(): Unit
35 | }
36 |
--------------------------------------------------------------------------------
/amm/compiler/interface/src/main/scala/ammonite/compiler/iface/Parser.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler.iface
2 |
3 | import ammonite.util.ImportTree
4 | import ammonite.util.Util.CodeSource
5 |
6 | abstract class Parser {
7 |
8 | def split(
9 | code: String,
10 | ignoreIncomplete: Boolean = true,
11 | fileName: String = "(console)"
12 | ): Option[Either[String, Seq[String]]]
13 |
14 | final def parseImportHooks(
15 | source: CodeSource,
16 | stmts: Seq[String]
17 | ): (Seq[String], Seq[ImportTree]) =
18 | parseImportHooksWithIndices(source, stmts.map((0, _)))
19 | def parseImportHooksWithIndices(
20 | source: CodeSource,
21 | stmts: Seq[(Int, String)]
22 | ): (Seq[String], Seq[ImportTree])
23 |
24 | /**
25 | * Splits up a script file into its constituent blocks, each of which
26 | * is a tuple of (leading-whitespace, statements). Leading whitespace
27 | * is returned separately so we can later manipulate the statements e.g.
28 | * by adding `val res2 = ` without the whitespace getting in the way
29 | */
30 | def splitScript(
31 | rawCode: String,
32 | fileName: String
33 | ): Either[String, IndexedSeq[(String, Seq[String])]]
34 |
35 | def scriptBlocksWithStartIndices(
36 | rawCode: String,
37 | fileName: String
38 | ): Either[Parser.ScriptSplittingError, Seq[Parser.ScriptBlock]]
39 |
40 | def defaultHighlight(
41 | buffer: Vector[Char],
42 | comment: fansi.Attrs,
43 | `type`: fansi.Attrs,
44 | literal: fansi.Attrs,
45 | keyword: fansi.Attrs,
46 | reset: fansi.Attrs,
47 | notImplemented: fansi.Attrs
48 | ): Vector[Char]
49 |
50 | def isObjDef(code: String): Boolean
51 | }
52 |
53 | object Parser {
54 |
55 | case class ParsedImportHooks(
56 | hookStatements: Seq[String],
57 | importTrees: Seq[ImportTree]
58 | )
59 |
60 | case class ScriptBlock(
61 | startIndex: Int,
62 | ncomment: String,
63 | codeWithStartIndices: Seq[(Int, String)]
64 | )
65 |
66 | object ScriptBlock {
67 | def apply(
68 | ncomment: String,
69 | codeWithStartIndices: Seq[(Int, String)]
70 | ): ScriptBlock =
71 | ScriptBlock(0, ncomment, codeWithStartIndices)
72 | }
73 |
74 | class ScriptSplittingError(
75 | message: String,
76 | val index: Int = -1,
77 | val expected: String = ""
78 | ) extends Exception(message)
79 | }
80 |
--------------------------------------------------------------------------------
/amm/compiler/interface/src/main/scala/ammonite/compiler/iface/Preprocessor.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler.iface
2 |
3 | import ammonite.util.{Imports, Name, Res}
4 | import ammonite.util.Util.CodeSource
5 |
6 | /**
7 | * Responsible for all scala-source-code-munging that happens within the
8 | * Ammonite REPL.
9 | *
10 | * Performs several tasks:
11 | *
12 | * - Takes top-level Scala expressions and assigns them to `res{1, 2, 3, ...}`
13 | * values so they can be accessed later in the REPL
14 | *
15 | * - Wraps the code snippet with an wrapper `object` since Scala doesn't allow
16 | * top-level expressions
17 | *
18 | * - Mangles imports from our [[ammonite.util.ImportData]] data structure into a source
19 | * String
20 | *
21 | * - Combines all of these into a complete compilation unit ready to feed into
22 | * the Scala compiler
23 | */
24 | abstract class Preprocessor {
25 |
26 | def transform(
27 | stmts: Seq[String],
28 | resultIndex: String,
29 | leadingSpaces: String,
30 | codeSource: CodeSource,
31 | indexedWrapperName: Name,
32 | imports: Imports,
33 | printerTemplate: String => String,
34 | extraCode: String,
35 | skipEmpty: Boolean,
36 | markScript: Boolean,
37 | codeWrapper: CodeWrapper
38 | ): Res[Preprocessor.Output]
39 |
40 | }
41 |
42 | object Preprocessor {
43 |
44 | case class Output(
45 | code: String,
46 | prefixCharLength: Int,
47 | userCodeNestingLevel: Int
48 | )
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-2.12.0_12/ammonite/compiler/CompilerCompatibility.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler
2 |
3 | import ammonite.util.Classpath
4 |
5 | import scala.reflect.internal.util.Position
6 | import scala.reflect.io.FileZipArchive
7 | import scala.tools.nsc
8 | import scala.tools.nsc.{Global, Settings}
9 | import scala.tools.nsc.classpath.{AggregateClassPath, ZipAndJarClassPathFactory}
10 | import scala.tools.nsc.interactive.{InteractiveAnalyzer, Global => InteractiveGlobal}
11 | import scala.tools.nsc.plugins.Plugin
12 | import scala.tools.nsc.reporters.AbstractReporter
13 | import scala.tools.nsc.typechecker.Analyzer
14 |
15 | object CompilerCompatibility extends ExtraCompilerCompatibility {
16 | def analyzer(g: Global, cl: ClassLoader): Analyzer { val global: g.type } = {
17 | new { val global: g.type = g } with Analyzer {
18 | override def findMacroClassLoader() = cl
19 | }
20 | }
21 |
22 | def interactiveAnalyzer(
23 | g: InteractiveGlobal,
24 | cl: ClassLoader
25 | ): InteractiveAnalyzer { val global: g.type } = {
26 | new { val global: g.type = g } with InteractiveAnalyzer {
27 | override def findMacroClassLoader() = cl
28 | }
29 | }
30 | def importInfo(g: Global)(t: g.Import) =
31 | new g.analyzer.ImportInfo(t, 0)
32 |
33 | def initGlobal(
34 | settings: Settings,
35 | reporter: AbstractReporter,
36 | jcp: AggregateClassPath,
37 | evalClassloader: ClassLoader,
38 | createPlugins: Global => List[Plugin]
39 | ): Global = {
40 |
41 | new nsc.Global(settings, reporter) { g =>
42 | override lazy val plugins = createPlugins(g)
43 |
44 | // Actually jcp, avoiding a path-dependent type issue in 2.10 here
45 | override def classPath = jcp
46 |
47 | override lazy val platform: ThisPlatform = new GlobalPlatform {
48 | override val global = g
49 | override val settings = g.settings
50 | override val classPath = jcp
51 | }
52 |
53 | override lazy val analyzer = CompilerCompatibility.analyzer(g, evalClassloader)
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-2.12.0_8/ammonite/compiler/ExtraCompilerCompatibility.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler
2 |
3 | import scala.reflect.io.FileZipArchive
4 | import scala.tools.nsc.Settings
5 | import scala.tools.nsc.classpath.ZipAndJarClassPathFactory
6 |
7 | abstract class ExtraCompilerCompatibility {
8 |
9 | def createZipJarFactory(arc: FileZipArchive, settings: Settings) = {
10 | ZipAndJarClassPathFactory.create(arc, settings)
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-2.12.10-2.13.1+/scala/tools/nsc/AmmClassPath.scala:
--------------------------------------------------------------------------------
1 | package scala.tools.nsc
2 |
3 | import java.io.File
4 | import java.net.URL
5 |
6 | import ammonite.compiler.internal.CustomURLZipArchive
7 |
8 | import scala.reflect.io.AbstractFile
9 | import scala.tools.nsc.classpath.FileUtils.AbstractFileOps
10 | import scala.tools.nsc.classpath.{ClassPathEntries, _}
11 | import scala.tools.nsc.util.{ClassPath, ClassRepresentation}
12 |
13 | trait AmmClassPath extends ClassPath {
14 | def zipUrl: URL
15 | def ammPackages(inPackage: String): Seq[PackageEntry]
16 | def packages(inPackage: scala.tools.nsc.classpath.PackageName): Seq[PackageEntry] = {
17 | ammPackages(inPackage.dottedString)
18 | }
19 |
20 | def ammList(inPackage: String): ClassPathEntries
21 | def list(inPackage: scala.tools.nsc.classpath.PackageName): ClassPathEntries = {
22 | ammList(inPackage.dottedString)
23 | }
24 |
25 | def ammClasses(inPackage: String): Seq[ClassFileEntry]
26 | def classes(inPackage: scala.tools.nsc.classpath.PackageName): Seq[ClassFileEntry] = {
27 | ammClasses(inPackage.dottedString)
28 | }
29 |
30 | def ammHasPackage(pkg: String): Boolean
31 | def hasPackage(pkg: scala.tools.nsc.classpath.PackageName) = ammHasPackage(pkg.dottedString)
32 | }
33 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-2.12.10-2.13.1+/scala/tools/nsc/WhiteListClasspath.scala:
--------------------------------------------------------------------------------
1 | package scala.tools.nsc
2 |
3 | import ammonite.util.Util
4 |
5 | import scala.tools.nsc.classpath.ClassPathEntries
6 | import scala.tools.nsc.util.ClassPath
7 |
8 | class WhiteListClasspath(aggregates: Seq[ClassPath], whitelist: Set[Seq[String]])
9 | extends scala.tools.nsc.classpath.AggregateClassPath(aggregates) {
10 | override def findClassFile(name: String) = {
11 | val tokens = name.split('.')
12 | if (Util.lookupWhiteList(whitelist, tokens.init ++ Seq(tokens.last + ".class"))) {
13 | super.findClassFile(name)
14 | } else None
15 | }
16 | override def list(inPackage: scala.tools.nsc.classpath.PackageName) = {
17 | val superList = super.list(inPackage)
18 | ClassPathEntries(
19 | superList.packages.filter { p => Util.lookupWhiteList(whitelist, p.name.split('.')) },
20 | superList.classesAndSources.filter { t =>
21 | Util.lookupWhiteList(whitelist, inPackage.dottedString.split('.') ++ Seq(t.name + ".class"))
22 | }
23 | )
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-2.12.13+/ammonite/compiler/CompilerCompatibility.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler
2 |
3 | import ammonite.util.Classpath
4 |
5 | import scala.reflect.internal.util.Position
6 | import scala.reflect.io.FileZipArchive
7 | import scala.tools.nsc
8 | import scala.tools.nsc.classpath.{AggregateClassPath, ZipAndJarClassPathFactory}
9 | import scala.tools.nsc.{Global, Settings}
10 | import scala.tools.nsc.interactive.{InteractiveAnalyzer, Global => InteractiveGlobal}
11 | import scala.tools.nsc.plugins.Plugin
12 | import scala.tools.nsc.reporters.Reporter
13 | import scala.tools.nsc.typechecker.Analyzer
14 |
15 | object CompilerCompatibility {
16 |
17 | def analyzer(g: Global, cl: ClassLoader): Analyzer { val global: g.type } = {
18 | new { val global: g.type = g } with Analyzer {
19 | override def findMacroClassLoader() = cl
20 | }
21 | }
22 |
23 | def interactiveAnalyzer(
24 | g: InteractiveGlobal,
25 | cl: ClassLoader
26 | ): InteractiveAnalyzer { val global: g.type } = {
27 | new { val global: g.type = g } with InteractiveAnalyzer
28 | }
29 |
30 | def importInfo(g: Global)(t: g.Import) =
31 | new g.analyzer.ImportInfo(t, 0)
32 |
33 | def initGlobal(
34 | settings: Settings,
35 | reporter: Reporter,
36 | jcp: AggregateClassPath,
37 | evalClassloader: ClassLoader,
38 | createPlugins: Global => List[Plugin]
39 | ): Global = {
40 |
41 | new nsc.Global(settings, reporter) { g =>
42 | override lazy val plugins = createPlugins(g)
43 |
44 | override def classPath = jcp
45 |
46 | override lazy val platform: ThisPlatform = new GlobalPlatform {
47 | override val global = g
48 | override val settings = g.settings
49 | override val classPath = jcp
50 | }
51 |
52 | override lazy val analyzer = CompilerCompatibility.analyzer(g, evalClassloader)
53 | }
54 | }
55 |
56 | def createZipJarFactory(arc: FileZipArchive, settings: Settings) = {
57 | ZipAndJarClassPathFactory.create(arc, settings, new scala.tools.nsc.CloseableRegistry())
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-2.12.13+/ammonite/compiler/MakeReporter.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler
2 |
3 | import ammonite.util.Classpath
4 |
5 | import scala.reflect.internal.util.Position
6 | import scala.reflect.io.FileZipArchive
7 | import scala.tools.nsc
8 | import scala.tools.nsc.classpath.{AggregateClassPath, ZipAndJarClassPathFactory}
9 | import scala.tools.nsc.{Global, Settings}
10 | import scala.tools.nsc.interactive.{InteractiveAnalyzer, Global => InteractiveGlobal}
11 | import scala.tools.nsc.plugins.Plugin
12 | import scala.tools.nsc.reporters.FilteringReporter
13 | import scala.tools.nsc.typechecker.Analyzer
14 |
15 | object MakeReporter {
16 |
17 | type Reporter = scala.tools.nsc.reporters.Reporter
18 |
19 | def makeReporter(
20 | errorLogger: (Position, String) => Unit,
21 | warningLogger: (Position, String) => Unit,
22 | infoLogger: (Position, String) => Unit,
23 | outerSettings: Settings
24 | ): Reporter =
25 | new FilteringReporter {
26 |
27 | def doReport(
28 | pos: scala.reflect.internal.util.Position,
29 | msg: String,
30 | severity: Severity
31 | ): Unit =
32 | display(pos, msg, severity)
33 |
34 | def display(pos: Position, msg: String, severity: Severity) =
35 | severity match {
36 | case ERROR =>
37 | Classpath.traceClasspathProblem(s"ERROR: $msg")
38 | errorLogger(pos, msg)
39 | case WARNING =>
40 | warningLogger(pos, msg)
41 | case INFO =>
42 | infoLogger(pos, msg)
43 | }
44 |
45 | def settings = outerSettings
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-2.12.9+/ammonite/compiler/ExtraCompilerCompatibility.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler
2 |
3 | import scala.reflect.io.FileZipArchive
4 | import scala.tools.nsc.Settings
5 | import scala.tools.nsc.classpath.ZipAndJarClassPathFactory
6 |
7 | abstract class ExtraCompilerCompatibility {
8 |
9 | def createZipJarFactory(arc: FileZipArchive, settings: Settings) = {
10 | ZipAndJarClassPathFactory.create(arc, settings, new scala.tools.nsc.CloseableRegistry())
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-2.13.1-2.13.11/ammonite/compiler/MakeReporter.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler
2 |
3 | import ammonite.util.Classpath
4 |
5 | import scala.reflect.internal.util.Position
6 | import scala.reflect.io.FileZipArchive
7 | import scala.tools.nsc
8 | import scala.tools.nsc.classpath.{AggregateClassPath, ZipAndJarClassPathFactory}
9 | import scala.tools.nsc.{Global, Settings}
10 | import scala.tools.nsc.interactive.{InteractiveAnalyzer, Global => InteractiveGlobal}
11 | import scala.tools.nsc.plugins.Plugin
12 | import scala.tools.nsc.reporters.FilteringReporter
13 | import scala.tools.nsc.typechecker.Analyzer
14 |
15 | object MakeReporter {
16 |
17 | type Reporter = scala.tools.nsc.reporters.Reporter
18 |
19 | def makeReporter(
20 | errorLogger: (Position, String) => Unit,
21 | warningLogger: (Position, String) => Unit,
22 | infoLogger: (Position, String) => Unit,
23 | outerSettings: Settings
24 | ): Reporter =
25 | new FilteringReporter {
26 |
27 | def doReport(
28 | pos: scala.reflect.internal.util.Position,
29 | msg: String,
30 | severity: Severity
31 | ): Unit =
32 | display(pos, msg, severity)
33 |
34 | def display(pos: Position, msg: String, severity: Severity) =
35 | severity match {
36 | case ERROR =>
37 | Classpath.traceClasspathProblem(s"ERROR: $msg")
38 | errorLogger(pos, msg)
39 | case WARNING =>
40 | warningLogger(pos, msg)
41 | case INFO =>
42 | infoLogger(pos, msg)
43 | }
44 |
45 | def settings = outerSettings
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-2.13.12+/ammonite/compiler/MakeReporter.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler
2 |
3 | import ammonite.util.Classpath
4 |
5 | import scala.reflect.internal.util.{CodeAction, Position}
6 | import scala.reflect.io.FileZipArchive
7 | import scala.tools.nsc
8 | import scala.tools.nsc.classpath.{AggregateClassPath, ZipAndJarClassPathFactory}
9 | import scala.tools.nsc.{Global, Settings}
10 | import scala.tools.nsc.interactive.{InteractiveAnalyzer, Global => InteractiveGlobal}
11 | import scala.tools.nsc.plugins.Plugin
12 | import scala.tools.nsc.reporters.FilteringReporter
13 | import scala.tools.nsc.typechecker.Analyzer
14 |
15 | object MakeReporter {
16 |
17 | type Reporter = scala.tools.nsc.reporters.Reporter
18 |
19 | def makeReporter(
20 | errorLogger: (Position, String) => Unit,
21 | warningLogger: (Position, String) => Unit,
22 | infoLogger: (Position, String) => Unit,
23 | outerSettings: Settings
24 | ): Reporter =
25 | new FilteringReporter {
26 |
27 | override def doReport(
28 | pos: scala.reflect.internal.util.Position,
29 | msg: String,
30 | severity: Severity,
31 | actions: List[CodeAction]
32 | ): Unit =
33 | display(pos, msg, severity)
34 |
35 | def display(pos: Position, msg: String, severity: Severity) =
36 | severity match {
37 | case ERROR =>
38 | Classpath.traceClasspathProblem(s"ERROR: $msg")
39 | errorLogger(pos, msg)
40 | case WARNING =>
41 | warningLogger(pos, msg)
42 | case INFO =>
43 | infoLogger(pos, msg)
44 | }
45 |
46 | def settings = outerSettings
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-2.13/ammonite/compiler/CompilerCompatibility.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler
2 |
3 | import ammonite.util.Classpath
4 |
5 | import scala.reflect.internal.util.Position
6 | import scala.reflect.io.FileZipArchive
7 | import scala.tools.nsc
8 | import scala.tools.nsc.classpath.{AggregateClassPath, ZipAndJarClassPathFactory}
9 | import scala.tools.nsc.{Global, Settings}
10 | import scala.tools.nsc.interactive.{InteractiveAnalyzer, Global => InteractiveGlobal}
11 | import scala.tools.nsc.plugins.Plugin
12 | import scala.tools.nsc.reporters.Reporter
13 | import scala.tools.nsc.typechecker.Analyzer
14 | import scala.tools.nsc.typechecker.MacroAnnotationNamers
15 |
16 | object CompilerCompatibility {
17 |
18 | def analyzer(g: Global, cl: ClassLoader): Analyzer { val global: g.type } = {
19 |
20 | // Adding MacroAnnotationNamers like scalac does, see
21 | // https://github.com/scala/scala/blob/434a3d78/src/compiler/scala/tools/nsc/Global.scala#L481
22 | val macroAnnotations = g.settings.YmacroAnnotations.value
23 |
24 | if (macroAnnotations)
25 | new { val global: g.type = g } with Analyzer with MacroAnnotationNamers {
26 | override def defaultMacroClassloader = global.findMacroClassLoader
27 | }
28 | else
29 | new { val global: g.type = g } with Analyzer {
30 | override def defaultMacroClassloader = global.findMacroClassLoader
31 | }
32 | }
33 |
34 | def interactiveAnalyzer(
35 | g: InteractiveGlobal,
36 | cl: ClassLoader
37 | ): InteractiveAnalyzer { val global: g.type } = {
38 | new { val global: g.type = g } with InteractiveAnalyzer {}
39 | }
40 |
41 | def importInfo(g: Global)(t: g.Import) =
42 | new g.analyzer.ImportInfo(t, 0, false)
43 |
44 | def initGlobal(
45 | settings: Settings,
46 | reporter: Reporter,
47 | jcp: AggregateClassPath,
48 | evalClassloader: ClassLoader,
49 | createPlugins: Global => List[Plugin]
50 | ): Global = {
51 |
52 | new nsc.Global(settings, reporter) { g =>
53 | override lazy val plugins = createPlugins(g)
54 |
55 | // Actually jcp, avoiding a path-dependent type issue in 2.10 here
56 | override def classPath = jcp
57 | override def findMacroClassLoader() = evalClassloader
58 | override lazy val platform: ThisPlatform = new GlobalPlatform {
59 | override val global = g
60 | override val settings = g.settings
61 | override val classPath = jcp
62 | }
63 |
64 | override lazy val analyzer = CompilerCompatibility.analyzer(g, evalClassloader)
65 | }
66 | }
67 |
68 | def createZipJarFactory(arc: FileZipArchive, settings: Settings) = {
69 | ZipAndJarClassPathFactory.create(arc, settings, new scala.tools.nsc.CloseableRegistry())
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-2/ammonite/compiler/CompilerExtensions.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler
2 |
3 | import ammonite.interp.api.InterpAPI
4 | import ammonite.repl.api.ReplAPI
5 |
6 | import java.nio.file.Path
7 |
8 | object CompilerExtensions {
9 |
10 | implicit class CompilerInterpAPIExtensions(private val api: InterpAPI) extends AnyVal {
11 |
12 | private def compilerManager = api._compilerManager.asInstanceOf[CompilerLifecycleManager]
13 |
14 | /**
15 | * Configures the current compiler, or if the compiler hasn't been initialized
16 | * yet, registers the configuration callback and applies it to the compiler
17 | * when it ends up being initialized later
18 | */
19 | def configureCompiler(c: scala.tools.nsc.Global => Unit): Unit =
20 | compilerManager.configureCompiler(c)
21 |
22 | /**
23 | * Pre-configures the next compiler. Useful for tuning options that are
24 | * used during parsing such as -Yrangepos
25 | */
26 | def preConfigureCompiler(c: scala.tools.nsc.Settings => Unit): Unit =
27 | compilerManager.preConfigureCompiler(c)
28 |
29 | /**
30 | * Directory where the byte code resulting from compiling the user code is written.
31 | * This is non-empty only if the `--output-directory` or `--tmp-output-directory` options
32 | * are passed to Ammonite upon launch.
33 | */
34 | def outputDir: Option[Path] =
35 | compilerManager.outputDir
36 | }
37 |
38 | implicit class CompilerReplAPIExtensions(private val api: ReplAPI) extends AnyVal {
39 |
40 | private def compilerManager = api._compilerManager.asInstanceOf[CompilerLifecycleManager]
41 |
42 | /**
43 | * Access the compiler to do crazy things if you really want to!
44 | */
45 | def compiler: scala.tools.nsc.Global =
46 | compilerManager.compiler.compiler
47 |
48 | /**
49 | * Access the presentation compiler to do even crazier things if you really want to!
50 | */
51 | def interactiveCompiler: scala.tools.nsc.interactive.Global =
52 | compilerManager.pressy.compiler
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-2/ammonite/compiler/tools/desugar.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler.tools
2 |
3 | import sourcecode.Compat._
4 | import scala.language.experimental.macros
5 |
6 | class Desugared(s: String) {
7 | override def toString() = s
8 | }
9 | object desugar {
10 | def transformer(c: Context)(expr: c.Expr[Any]): c.Expr[Desugared] = {
11 | import c.universe._
12 | c.Expr[Desugared](
13 | q"ammonite.compiler.tools.SourceRuntime.desugarImpl(${c.universe.showCode(expr.tree)})"
14 | )
15 | }
16 |
17 | def apply(expr: Any): Desugared = macro transformer
18 | }
19 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-3.0.0-3.3.1/ammonite/compiler/DirectoryClassPath.scala:
--------------------------------------------------------------------------------
1 | package dotty.ammonite.compiler
2 |
3 | import java.io.{File => JFile}
4 | import dotty.tools.dotc.classpath
5 | import dotty.tools.io.{AbstractFile, PlainFile, ClassPath, ClassRepresentation, EfficientClassPath}
6 | import classpath.FileUtils._
7 |
8 | case class DirectoryClassPath(dir: JFile)
9 | extends classpath.JFileDirectoryLookup[classpath.ClassFileEntryImpl]
10 | with classpath.NoSourcePaths {
11 | override def findClass(className: String): Option[ClassRepresentation] =
12 | findClassFile(className) map classpath.ClassFileEntryImpl
13 |
14 | def findClassFile(className: String): Option[AbstractFile] = {
15 | val relativePath = classpath.FileUtils.dirPath(className)
16 | val classFile = new JFile(dir, relativePath + ".class")
17 | if (classFile.exists) {
18 | val wrappedClassFile = new dotty.tools.io.File(classFile.toPath)
19 | val abstractClassFile = new PlainFile(wrappedClassFile)
20 | Some(abstractClassFile)
21 | } else None
22 | }
23 |
24 | protected def createFileEntry(file: AbstractFile): classpath.ClassFileEntryImpl =
25 | classpath.ClassFileEntryImpl(file)
26 | protected def isMatchingFile(f: JFile): Boolean =
27 | f.isClass
28 |
29 | private[dotty] def classes(inPackage: classpath.PackageName): Seq[classpath.ClassFileEntry] =
30 | files(inPackage)
31 | }
32 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-3.0.0-3.6.2/ammonite/compiler/DottyParser.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler
2 |
3 | import dotty.tools.dotc
4 | import dotc.ast.untpd
5 | import dotc.core.Contexts.Context
6 | import dotc.core.Flags
7 | import dotc.core.StdNames.nme
8 | import dotc.parsing.Parsers.{Location, Parser}
9 | import dotc.parsing.Tokens
10 | import dotc.reporting.IllegalStartOfStatement
11 | import dotc.util.SourceFile
12 |
13 | import scala.collection.mutable
14 |
15 | class DottyParser(source: SourceFile)(using Context) extends Parser(source) with CompatibilityParser {
16 |
17 | // From
18 | // https://github.com/lampepfl/dotty/blob/3.0.0-M3/
19 | // compiler/src/dotty/tools/dotc/parsing/Parsers.scala/#L67-L71
20 | extension (buf: mutable.ListBuffer[untpd.Tree])
21 | def +++=(x: untpd.Tree) = x match {
22 | case x: untpd.Thicket => buf ++= x.trees
23 | case x => buf += x
24 | }
25 |
26 | private val oursLocalModifierTokens = Tokens.localModifierTokens + Tokens.PRIVATE
27 |
28 | override def localDef(
29 | start: Int,
30 | implicitMods: untpd.Modifiers = untpd.EmptyModifiers
31 | ): untpd.Tree = {
32 | var mods = defAnnotsMods(oursLocalModifierTokens)
33 | for (imod <- implicitMods.mods) mods = addMod(mods, imod)
34 | if (mods.is(Flags.Final))
35 | // A final modifier means the local definition is "class-like".
36 | // FIXME: Deal with modifiers separately
37 | tmplDef(start, mods)
38 | else
39 | defOrDcl(start, mods)
40 | }
41 |
42 | // Adapted from
43 | // https://github.com/lampepfl/dotty/blob/3.2.0/
44 | // compiler/src/dotty/tools/dotc/parsing/Parsers.scala#L4075-L4094
45 | // Unlike it, we accept private modifiers for top-level definitions.
46 | override def blockStatSeq(): List[untpd.Tree] = checkNoEscapingPlaceholders {
47 | val stats = new mutable.ListBuffer[untpd.Tree]
48 | while
49 | var empty = false
50 | if (in.token == Tokens.IMPORT)
51 | stats ++= compatibilityImportClause()
52 | else if (isExprIntro)
53 | stats += expr(Location.InBlock)
54 | else if in.token == Tokens.IMPLICIT && !in.inModifierPosition() then
55 | stats += closure(
56 | in.offset,
57 | Location.InBlock,
58 | modifiers(scala.collection.immutable.BitSet(Tokens.IMPLICIT))
59 | )
60 | else if isIdent(nme.extension) && followingIsExtension() then
61 | stats += extension()
62 | else if isDefIntro(oursLocalModifierTokens, excludedSoftModifiers = Set(nme.`opaque`)) then
63 | stats +++= localDef(in.offset)
64 | else
65 | empty = true
66 | statSepOrEnd(stats, noPrevStat = empty, altEnd = Tokens.CASE)
67 | do ()
68 | stats.toList
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-3.3.2+/ammonite/compiler/DirectoryClassPath.scala:
--------------------------------------------------------------------------------
1 | package dotty.ammonite.compiler
2 |
3 | import java.io.{File => JFile}
4 | import dotty.tools.dotc.classpath
5 | import dotty.tools.io.{AbstractFile, PlainFile, ClassPath, ClassRepresentation, EfficientClassPath}
6 | import classpath.FileUtils._
7 |
8 | case class DirectoryClassPath(dir: JFile)
9 | extends classpath.JFileDirectoryLookup[classpath.ClassFileEntryImpl]
10 | with classpath.NoSourcePaths {
11 | override def findClass(className: String): Option[ClassRepresentation] =
12 | findClassFile(className) map classpath.ClassFileEntryImpl
13 |
14 | def findClassFile(className: String): Option[AbstractFile] = {
15 | val relativePath = classpath.FileUtils.dirPath(className)
16 | val classFile = new JFile(dir, relativePath + ".class")
17 | if (classFile.exists) {
18 | val wrappedClassFile = new dotty.tools.io.File(classFile.toPath)
19 | val abstractClassFile = new PlainFile(wrappedClassFile)
20 | Some(abstractClassFile)
21 | } else None
22 | }
23 |
24 | protected def createFileEntry(file: AbstractFile): classpath.ClassFileEntryImpl =
25 | classpath.ClassFileEntryImpl(file)
26 | protected def isMatchingFile(f: JFile): Boolean =
27 | f.isClass
28 |
29 | private[dotty] def classes(inPackage: classpath.PackageName): Seq[classpath.ClassFileEntry] =
30 | files(inPackage)
31 | }
32 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-3.4.2+/ammonite/compiler/DirectoryClassPath.scala:
--------------------------------------------------------------------------------
1 | package dotty.ammonite.compiler
2 |
3 | import java.io.{File => JFile}
4 | import dotty.tools.dotc.classpath
5 | import dotty.tools.io.{AbstractFile, PlainFile, ClassPath, ClassRepresentation, EfficientClassPath}
6 | import classpath.FileUtils._
7 |
8 | case class DirectoryClassPath(dir: JFile)
9 | extends classpath.JFileDirectoryLookup[classpath.BinaryFileEntry]
10 | with classpath.NoSourcePaths {
11 | override def findClass(className: String): Option[ClassRepresentation] =
12 | findClassFile(className) map classpath.BinaryFileEntry.apply
13 |
14 | def findClassFile(className: String): Option[AbstractFile] = {
15 | val relativePath = classpath.FileUtils.dirPath(className)
16 | val classFile = new JFile(dir, relativePath + ".class")
17 | if (classFile.exists) {
18 | val wrappedClassFile = new dotty.tools.io.File(classFile.toPath)
19 | val abstractClassFile = new PlainFile(wrappedClassFile)
20 | Some(abstractClassFile)
21 | } else None
22 | }
23 |
24 | protected def createFileEntry(file: AbstractFile): classpath.BinaryFileEntry =
25 | classpath.BinaryFileEntry(file)
26 | protected def isMatchingFile(f: JFile): Boolean =
27 | f.isClass
28 |
29 | private[dotty] def classes(inPackage: classpath.PackageName): Seq[classpath.BinaryFileEntry] =
30 | files(inPackage)
31 | }
32 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-3.5.0+/ammonite/compiler/DirectoryClassPath.scala:
--------------------------------------------------------------------------------
1 | package dotty.ammonite.compiler
2 |
3 | import java.io.{File => JFile}
4 | import dotty.tools.dotc.classpath
5 | import dotty.tools.io.{AbstractFile, PlainFile, ClassPath, ClassRepresentation, EfficientClassPath}
6 | import classpath.FileUtils._
7 |
8 | case class DirectoryClassPath(dir: JFile)
9 | extends classpath.JFileDirectoryLookup[classpath.BinaryFileEntry]
10 | with classpath.NoSourcePaths {
11 |
12 | def findClassFile(className: String): Option[AbstractFile] = {
13 | val relativePath = classpath.FileUtils.dirPath(className)
14 | val classFile = new JFile(dir, relativePath + ".class")
15 | if (classFile.exists) {
16 | val wrappedClassFile = new dotty.tools.io.File(classFile.toPath)
17 | val abstractClassFile = new PlainFile(wrappedClassFile)
18 | Some(abstractClassFile)
19 | } else None
20 | }
21 |
22 | protected def createFileEntry(file: AbstractFile): classpath.BinaryFileEntry =
23 | classpath.BinaryFileEntry(file)
24 | protected def isMatchingFile(f: JFile): Boolean =
25 | f.isClass
26 |
27 | private[dotty] def classes(inPackage: classpath.PackageName): Seq[classpath.BinaryFileEntry] =
28 | files(inPackage)
29 | }
30 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-3.6.3+/ammonite/compiler/DottyParser.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler
2 |
3 | import dotty.tools.dotc
4 | import dotc.ast.untpd
5 | import dotc.core.Contexts.Context
6 | import dotc.core.Flags
7 | import dotc.core.StdNames.nme
8 | import dotc.parsing.Parsers.{Location, Parser}
9 | import dotc.parsing.Tokens
10 | import dotc.reporting.IllegalStartOfStatement
11 | import dotc.util.SourceFile
12 |
13 | import scala.collection.mutable
14 |
15 | class DottyParser(source: SourceFile)(using Context) extends Parser(source) with CompatibilityParser {
16 |
17 | // From
18 | // https://github.com/lampepfl/dotty/blob/3.0.0-M3/
19 | // compiler/src/dotty/tools/dotc/parsing/Parsers.scala/#L67-L71
20 | extension (buf: mutable.ListBuffer[untpd.Tree])
21 | def +++=(x: untpd.Tree) = x match {
22 | case x: untpd.Thicket => buf ++= x.trees
23 | case x => buf += x
24 | }
25 |
26 | private val oursLocalModifierTokens = Tokens.localModifierTokens + Tokens.PRIVATE
27 |
28 | override def localDef(
29 | start: Int,
30 | implicitMods: untpd.Modifiers = untpd.EmptyModifiers
31 | ): untpd.Tree = {
32 | var mods = defAnnotsMods(oursLocalModifierTokens)
33 | for (imod <- implicitMods.mods) mods = addMod(mods, imod)
34 | if (mods.is(Flags.Final))
35 | // A final modifier means the local definition is "class-like".
36 | // FIXME: Deal with modifiers separately
37 | tmplDef(start, mods)
38 | else
39 | defOrDcl(start, mods)
40 | }
41 |
42 | // Adapted from
43 | // https://github.com/lampepfl/dotty/blob/3.2.0/
44 | // compiler/src/dotty/tools/dotc/parsing/Parsers.scala#L4075-L4094
45 | // Unlike it, we accept private modifiers for top-level definitions.
46 | override def blockStatSeq(outermost: Boolean = false): List[untpd.Tree] = checkNoEscapingPlaceholders {
47 | val stats = new mutable.ListBuffer[untpd.Tree]
48 | while
49 | var empty = false
50 | if (in.token == Tokens.IMPORT)
51 | stats ++= compatibilityImportClause()
52 | else if (isExprIntro)
53 | stats += expr(Location.InBlock)
54 | else if in.token == Tokens.IMPLICIT && !in.inModifierPosition() then
55 | stats += closure(
56 | in.offset,
57 | Location.InBlock,
58 | modifiers(scala.collection.immutable.BitSet(Tokens.IMPLICIT))
59 | )
60 | else if isIdent(nme.extension) && followingIsExtension() then
61 | stats += extension()
62 | else if isDefIntro(oursLocalModifierTokens, excludedSoftModifiers = Set(nme.`opaque`)) then
63 | stats +++= localDef(in.offset)
64 | else
65 | empty = true
66 | statSepOrEnd(stats, noPrevStat = empty, altEnd = Tokens.CASE)
67 | do ()
68 | stats.toList
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-3/ammonite/compiler/AsmPositionUpdater.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler
2 |
3 | // originally based on https://github.com/VirtusLab/scala-cli/blob/67db91cfbaa74de806fd1d5ed00096affa0125c0/modules/build/src/main/scala/scala/build/postprocessing/AsmPositionUpdater.scala
4 |
5 | import org.objectweb.asm
6 | import java.io.InputStream
7 |
8 | object AsmPositionUpdater {
9 |
10 | private class LineNumberTableMethodVisitor(
11 | lineShift: Int,
12 | delegate: asm.MethodVisitor
13 | ) extends asm.MethodVisitor(asm.Opcodes.ASM9, delegate) {
14 | override def visitLineNumber(line: Int, start: asm.Label): Unit =
15 | super.visitLineNumber(line + lineShift, start)
16 | }
17 |
18 | private class LineNumberTableClassVisitor(
19 | mappings: Map[String, (String, Int)],
20 | cw: asm.ClassWriter
21 | ) extends asm.ClassVisitor(asm.Opcodes.ASM9, cw) {
22 | private var lineShiftOpt = Option.empty[Int]
23 | def mappedStuff = lineShiftOpt.nonEmpty
24 | override def visitSource(source: String, debug: String): Unit =
25 | mappings.get(source) match {
26 | case None =>
27 | super.visitSource(source, debug)
28 | case Some((newSource, lineShift)) =>
29 | lineShiftOpt = Some(lineShift)
30 | super.visitSource(newSource, debug)
31 | }
32 | override def visitMethod(
33 | access: Int,
34 | name: String,
35 | descriptor: String,
36 | signature: String,
37 | exceptions: Array[String]
38 | ): asm.MethodVisitor = {
39 | val main = super.visitMethod(access, name, descriptor, signature, exceptions)
40 | lineShiftOpt match {
41 | case None => main
42 | case Some(lineShift) => new LineNumberTableMethodVisitor(lineShift, main)
43 | }
44 | }
45 | }
46 |
47 | def postProcess(
48 | mappings: Map[String, (String, Int)],
49 | clsInputStream: InputStream
50 | ): Option[Array[Byte]] = {
51 | val reader = new asm.ClassReader(clsInputStream)
52 | val writer = new asm.ClassWriter(reader, 0)
53 | val checker = new LineNumberTableClassVisitor(mappings, writer)
54 | reader.accept(checker, 0)
55 | if (checker.mappedStuff) Some(writer.toByteArray)
56 | else None
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-3/ammonite/compiler/CompatibilityParser.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler
2 |
3 | import dotty.tools.dotc.parsing.Parsers.Parser
4 | import dotty.tools.dotc.parsing.Tokens
5 |
6 | trait CompatibilityParser { self: Parser =>
7 |
8 | def compatibilityImportClause() =
9 | importClause()
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-3/ammonite/compiler/CompilerBuilder.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler
2 |
3 | import java.net.URL
4 | import java.nio.file.Path
5 |
6 | import ammonite.compiler.iface.{
7 | Compiler => ICompiler,
8 | CompilerBuilder => ICompilerBuilder,
9 | CompilerLifecycleManager => ICompilerLifecycleManager,
10 | _
11 | }
12 | import ammonite.util.Frame
13 | import dotty.tools.io.AbstractFile
14 |
15 | case class CompilerBuilder(
16 | outputDir: Option[Path] = None
17 | ) extends ICompilerBuilder:
18 |
19 | def create(
20 | initialClassPath: Seq[URL],
21 | classPath: Seq[URL],
22 | dynamicClassPath: Seq[(String, Array[Byte])],
23 | evalClassLoader: ClassLoader,
24 | pluginClassLoader: ClassLoader,
25 | reporter: Option[ICompilerBuilder.Message => Unit],
26 | settings: Seq[String],
27 | classPathWhiteList: Set[Seq[String]],
28 | lineNumberModifier: Boolean
29 | ): ICompiler = {
30 | val tempDir = AbstractFile.getDirectory(outputDir.getOrElse(os.temp.dir().toNIO))
31 | Compiler.addToClasspath(dynamicClassPath, tempDir, outputDir)
32 | new Compiler(
33 | tempDir,
34 | initialClassPath,
35 | classPath,
36 | evalClassLoader,
37 | classPathWhiteList,
38 | settings = settings,
39 | reporter = reporter
40 | )
41 | }
42 |
43 | def scalaVersion = CompilerBuilder.scalaVersion
44 |
45 | def newManager(
46 | rtCacheDir: Option[Path],
47 | headFrame: => Frame,
48 | dependencyCompleter: => Option[String => (Int, Seq[String])],
49 | whiteList: Set[Seq[String]],
50 | initialClassLoader: ClassLoader,
51 | settings: Seq[String]
52 | ): ICompilerLifecycleManager =
53 | new CompilerLifecycleManager(
54 | rtCacheDir,
55 | headFrame,
56 | dependencyCompleter,
57 | whiteList,
58 | initialClassLoader,
59 | outputDir,
60 | settings
61 | )
62 |
63 | object CompilerBuilder:
64 | def scalaVersion = dotty.tools.dotc.config.Properties.versionNumberString
65 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-3/ammonite/compiler/CompilerExtensions.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler
2 |
3 | import ammonite.interp.api.InterpAPI
4 | import ammonite.repl.api.ReplAPI
5 |
6 | import java.nio.file.Path
7 |
8 | object CompilerExtensions {
9 |
10 | implicit class CompilerInterpAPIExtensions(private val api: InterpAPI) extends AnyVal {
11 |
12 | private def compilerManager = api._compilerManager.asInstanceOf[CompilerLifecycleManager]
13 |
14 | /**
15 | * Configures the current compiler, or if the compiler hasn't been initialized
16 | * yet, registers the configuration callback and applies it to the compiler
17 | * when it ends up being initialized later
18 | */
19 | def configureCompiler(c: dotty.tools.dotc.Compiler => Unit): Unit =
20 | compilerManager.configureCompiler(c)
21 |
22 | /**
23 | * Pre-configures the next compiler context. Useful for tuning options that are
24 | * used during parsing.
25 | */
26 | def preConfigureCompiler(c: dotty.tools.dotc.core.Contexts.FreshContext => Unit): Unit =
27 | compilerManager.preConfigureCompiler(c)
28 |
29 | /**
30 | * Directory where the byte code resulting from compiling the user code is written.
31 | * This is non-empty only if the `--output-directory` or `--tmp-output-directory` options
32 | * are passed to Ammonite upon launch.
33 | */
34 | def outputDir: Option[Path] =
35 | compilerManager.outputDir
36 | }
37 |
38 | implicit class CompilerReplAPIExtensions(private val api: ReplAPI) extends AnyVal {
39 |
40 | private def compilerManager = api._compilerManager.asInstanceOf[CompilerLifecycleManager]
41 |
42 | def initialContext: dotty.tools.dotc.core.Contexts.Context =
43 | compilerManager.compiler.initialCtx
44 |
45 | /**
46 | * Access the compiler to do crazy things if you really want to!
47 | */
48 | def compiler: dotty.tools.dotc.Compiler =
49 | compilerManager.compiler.compiler
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-3/ammonite/compiler/Extensions.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler
2 |
3 | import ammonite.interp.api.InterpAPI
4 |
5 | object Extensions {
6 |
7 | implicit class CompilerInterAPIExtensions(private val self: InterpAPI) extends AnyVal
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-3/ammonite/compiler/internal/CompilerHelper.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler.internal
2 |
3 | import dotty.tools.dotc.core.Contexts._
4 | import dotty.tools.dotc.parsing.Parser
5 | import dotty.tools.dotc.reporting.{Diagnostic, MessageRendering}
6 | import dotty.tools.dotc.typer.TyperPhase
7 |
8 | object CompilerHelper {
9 | def frontEndPhases = List(
10 | List(new Parser),
11 | List(new TyperPhase)
12 | )
13 | def messageAndPos(messageRenderer: MessageRendering, diagnostic: Diagnostic)(implicit
14 | ctx: Context
15 | ) =
16 | messageRenderer.messageAndPos(diagnostic)
17 | }
18 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-3/ammonite/compiler/tools/desugar.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler.tools
2 |
3 | object desugar
4 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-3/ammonite/compiler/tools/source.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler.tools
2 |
3 | import ammonite.util.Util.Location
4 |
5 | object source {
6 |
7 | def load(f: => Any): Location = ???
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-3/dotty/ammonite/compiler/AmmCompletionExtras.scala:
--------------------------------------------------------------------------------
1 | package dotty.ammonite.compiler
2 |
3 | import dotty.tools.dotc.interactive.Completion
4 |
5 | trait AmmCompletionExtras {
6 |
7 | def maybeBackticked(input: String, hasBackTick: Boolean): Completion =
8 | Completion.backtickCompletions(Completion(input, "", Nil), hasBackTick)
9 | def backtick(completion: Completion): Completion =
10 | Completion.backtickCompletions(completion, completion.label.startsWith("`"))
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-3/dotty/ammonite/compiler/WhiteListClassPath.scala:
--------------------------------------------------------------------------------
1 | package dotty.ammonite.compiler
2 |
3 | import ammonite.util.Util
4 |
5 | import dotty.tools.dotc.classpath.{ClassPathEntries, PackageName}
6 | import dotty.tools.io.ClassPath
7 |
8 | class WhiteListClasspath(aggregates: Seq[ClassPath], whitelist: Set[Seq[String]])
9 | extends dotty.tools.dotc.classpath.AggregateClassPath(aggregates) {
10 | override def findClassFile(name: String) = {
11 | val tokens = name.split('.')
12 | if (Util.lookupWhiteList(whitelist, tokens.init ++ Seq(tokens.last + ".class"))) {
13 | super.findClassFile(name)
14 | } else None
15 | }
16 |
17 | override def list(inPackage: PackageName) = {
18 | val superList = super.list(inPackage)
19 | ClassPathEntries(
20 | superList.packages.filter { p => Util.lookupWhiteList(whitelist, p.name.split('.')) },
21 | superList.classesAndSources.filter { t =>
22 | Util.lookupWhiteList(whitelist, inPackage.dottedString.split('.') ++ Seq(t.name + ".class"))
23 | }
24 | )
25 | }
26 |
27 | override def toString: String =
28 | s"WhiteListClasspath($aggregates, ${whitelist.size} white-listed elements)"
29 | }
30 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-not-2.12.10-2.13.1+/scala/tools/nsc/AmmClassPath.scala:
--------------------------------------------------------------------------------
1 | package scala.tools.nsc
2 |
3 | import java.io.File
4 | import java.net.URL
5 |
6 | import ammonite.compiler.internal.CustomURLZipArchive
7 |
8 | import scala.reflect.io.AbstractFile
9 | import scala.tools.nsc.classpath.FileUtils.AbstractFileOps
10 | import scala.tools.nsc.classpath.{ClassPathEntries, _}
11 | import scala.tools.nsc.util.{ClassPath, ClassRepresentation}
12 |
13 | trait AmmClassPath extends ClassPath {
14 | def zipUrl: URL
15 | def ammPackages(inPackage: String): Seq[PackageEntry]
16 | def packages(inPackage: String): Seq[PackageEntry] = {
17 | ammPackages(inPackage)
18 | }
19 |
20 | def ammList(inPackage: String): ClassPathEntries
21 | def list(inPackage: String): ClassPathEntries = {
22 | ammList(inPackage)
23 | }
24 |
25 | def ammClasses(inPackage: String): Seq[ClassFileEntry]
26 | def classes(inPackage: String): Seq[ClassFileEntry] = {
27 | ammClasses(inPackage)
28 | }
29 |
30 | def ammHasPackage(pkg: String): Boolean
31 | def hasPackage(pkg: String) = ammHasPackage(pkg)
32 | }
33 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-not-2.12.10-2.13.1+/scala/tools/nsc/WhiteListClasspath.scala:
--------------------------------------------------------------------------------
1 | package scala.tools.nsc
2 |
3 | import ammonite.util.Util
4 |
5 | import scala.tools.nsc.classpath.ClassPathEntries
6 | import scala.tools.nsc.util.ClassPath
7 |
8 | class WhiteListClasspath(aggregates: Seq[ClassPath], whitelist: Set[Seq[String]])
9 | extends scala.tools.nsc.classpath.AggregateClassPath(aggregates) {
10 | override def findClassFile(name: String) = {
11 | val tokens = name.split('.')
12 | if (Util.lookupWhiteList(whitelist, tokens.init ++ Seq(tokens.last + ".class"))) {
13 | super.findClassFile(name)
14 | } else None
15 | }
16 | override def list(inPackage: String) = {
17 | val superList = super.list(inPackage)
18 | ClassPathEntries(
19 | superList.packages.filter { p => Util.lookupWhiteList(whitelist, p.name.split('.')) },
20 | superList.classesAndSources.filter { t =>
21 | Util.lookupWhiteList(whitelist, inPackage.split('.') ++ Seq(t.name + ".class"))
22 | }
23 | )
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala-not-2.12.13+-2.13.1+/ammonite/compiler/MakeReporter.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler
2 |
3 | import ammonite.util.Classpath
4 |
5 | import scala.reflect.internal.util.Position
6 | import scala.reflect.io.FileZipArchive
7 | import scala.tools.nsc
8 | import scala.tools.nsc.{Global, Settings}
9 | import scala.tools.nsc.classpath.{AggregateClassPath, ZipAndJarClassPathFactory}
10 | import scala.tools.nsc.interactive.{InteractiveAnalyzer, Global => InteractiveGlobal}
11 | import scala.tools.nsc.plugins.Plugin
12 | import scala.tools.nsc.reporters.AbstractReporter
13 | import scala.tools.nsc.typechecker.Analyzer
14 |
15 | object MakeReporter {
16 |
17 | type Reporter = AbstractReporter
18 |
19 | def makeReporter(
20 | errorLogger: (Position, String) => Unit,
21 | warningLogger: (Position, String) => Unit,
22 | infoLogger: (Position, String) => Unit,
23 | outerSettings: Settings
24 | ): Reporter =
25 | new AbstractReporter {
26 | def displayPrompt(): Unit = ???
27 |
28 | def display(pos: Position, msg: String, severity: Severity) = {
29 | severity match {
30 | case ERROR =>
31 | Classpath.traceClasspathProblem(s"ERROR: $msg")
32 | errorLogger(pos, msg)
33 | case WARNING =>
34 | warningLogger(pos, msg)
35 | case INFO =>
36 | infoLogger(pos, msg)
37 | }
38 | }
39 |
40 | val settings = outerSettings
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala/ammonite/compiler/CompilerUtil.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler
2 |
3 | object CompilerUtil {
4 |
5 | val ignoredSyms = Set(
6 | "package class-use",
7 | "object package-info",
8 | "class package-info"
9 | )
10 | val ignoredNames = Set(
11 | // Probably synthetic
12 | "",
13 | "",
14 | "$main",
15 | // Don't care about this
16 | "toString",
17 | "equals",
18 | "wait",
19 | "notify",
20 | "notifyAll",
21 | "synchronized",
22 | "hashCode",
23 | "getClass",
24 | "eq",
25 | "ne",
26 | "##",
27 | "==",
28 | "!=",
29 | "isInstanceOf",
30 | "asInstanceOf",
31 | // Behaves weird in 2.10.x, better to just ignore.
32 | "_"
33 | )
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/amm/compiler/src/main/scala/ammonite/compiler/DefaultCodeWrapper.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler
2 |
3 | import ammonite.compiler.iface.CodeWrapper
4 | import ammonite.util._
5 | import ammonite.util.Util.{CodeSource, normalizeNewlines}
6 |
7 | object DefaultCodeWrapper extends CodeWrapper {
8 | private val userCodeNestingLevel = 1
9 | def apply(
10 | code: String,
11 | source: CodeSource,
12 | imports: Imports,
13 | printCode: String,
14 | indexedWrapperName: Name,
15 | extraCode: String
16 | ) = {
17 | import source.pkgName
18 | val top = normalizeNewlines(s"""
19 | package ${pkgName.head.encoded}
20 | package ${Util.encodeScalaSourcePath(pkgName.tail)}
21 | $imports
22 |
23 | object ${indexedWrapperName.backticked}{\n""")
24 | val bottom = normalizeNewlines(s"""\ndef $$main() = { $printCode }
25 | override def toString = "${indexedWrapperName.encoded}"
26 | $extraCode
27 | }
28 | """)
29 |
30 | (top, bottom, userCodeNestingLevel)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/amm/compiler/src/test/scala-2/ammonite/compiler/test/CompilerTestExtensions.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler.test
2 |
3 | object CompilerTestExtensions
4 |
--------------------------------------------------------------------------------
/amm/compiler/src/test/scala-3/ammonite/compiler/test/CompilerTestExtensions.scala:
--------------------------------------------------------------------------------
1 | package ammonite.compiler.test
2 |
3 | import dotty.tools.dotc.{Compiler => DottyCompiler}
4 |
5 | object CompilerTestExtensions {
6 | implicit class DottyCompilerExtensions(private val self: DottyCompiler) extends AnyVal {
7 | // scala.tools.nsc.Global in Scala 2 has that.
8 | // We only add it here so that code calling that compiles, and
9 | // make sure this method is not called at the end when the
10 | // Scala 3 amm-compiler module is used.
11 | def useOffsetPositions: Boolean = ???
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/amm/helper/src/main/scala-3/ammonite/helper/Helper.scala:
--------------------------------------------------------------------------------
1 | package ammonite.helper
2 |
3 | abstract class Helper
4 |
--------------------------------------------------------------------------------
/amm/interp/api/src/main/scala/ammonite/Stubs.scala:
--------------------------------------------------------------------------------
1 | package ammonite
2 |
3 | // Dummy packages just to populate the existence of these top-level synthetic
4 | // packages in the Scala compiler.
5 |
6 | /**
7 | * Package that gets filled with any script files that the user imports
8 | */
9 | package $file {
10 | object $
11 | }
12 |
13 | /**
14 | * Package that gets filled with any script files that the user imports
15 | */
16 | package $exec {
17 | object $
18 | }
19 |
20 | /**
21 | * Package that gets filled with ivy artifacts the user loads
22 | */
23 | package $ivy {
24 | object $
25 | }
26 |
27 | /**
28 | * Package that gets filled with any web scripts people load from http URLs
29 | */
30 | package $url {
31 | object $
32 | }
33 |
34 | /**
35 | * Package to import from when you don't want to import anything
36 | */
37 | package $stub {
38 | object $
39 | }
40 |
41 | /**
42 | * Package to import from when you don't want to import anything
43 | */
44 | package $cp {
45 | object $
46 | }
47 |
48 | /**
49 | * Package to import from when you don't want to import anything
50 | */
51 | package $plugin {
52 | object $
53 | }
54 |
55 | package $repo {
56 | object $
57 | }
58 |
--------------------------------------------------------------------------------
/amm/interp/api/src/main/scala/ammonite/interp/api/APIHolder.scala:
--------------------------------------------------------------------------------
1 | package ammonite.interp.api
2 |
3 | class APIHolder[T >: Null <: AnyRef] {
4 | var value0: T = null
5 | implicit final lazy val value: T = value0
6 | }
7 |
--------------------------------------------------------------------------------
/amm/interp/api/src/main/scala/ammonite/interp/api/AmmoniteExit.scala:
--------------------------------------------------------------------------------
1 | package ammonite.interp.api
2 |
3 | import scala.util.control.ControlThrowable
4 |
5 | /**
6 | * Thrown to exit the REPL cleanly
7 | */
8 | case class AmmoniteExit(value: Any) extends ControlThrowable
9 |
--------------------------------------------------------------------------------
/amm/interp/api/src/main/scala/ammonite/interp/api/InterpAPI.scala:
--------------------------------------------------------------------------------
1 | package ammonite.interp.api
2 |
3 | import ammonite.util.{Colors, Ref}
4 | import coursierapi.{Dependency, Fetch, Repository}
5 |
6 | import scala.collection.mutable
7 |
8 | object InterpBridge extends APIHolder[InterpAPI]
9 |
10 | trait InterpAPI {
11 |
12 | /**
13 | * When running a script in `--watch` mode, re-run the main script if this
14 | * file changes. By default, this happens for all script files, but you can
15 | * call this to watch arbitrary files your script may depend on
16 | */
17 | def watch(p: os.Path): Unit
18 |
19 | /**
20 | * A generalization of [[watch]], allows watching arbitrary values and not
21 | * just the contents of file paths.
22 | */
23 | def watchValue[T](v: => T): T
24 |
25 | /**
26 | * The colors that will be used to render the Ammonite REPL in the terminal,
27 | * or for rendering miscellaneous info messages when running scripts.
28 | */
29 | val colors: Ref[Colors]
30 |
31 | /**
32 | * Tools related to loading external scripts and code into the REPL
33 | */
34 | def load: InterpLoad
35 |
36 | /**
37 | * resolvers to use when loading jars
38 | */
39 | def repositories: Ref[List[Repository]]
40 |
41 | /**
42 | * Functions that will be chained and called on the coursier
43 | * Fetch object right before they are run
44 | */
45 | val resolutionHooks: mutable.Buffer[Fetch => Fetch]
46 |
47 | /**
48 | * Exit the Ammonite REPL. You can also use Ctrl-D to exit
49 | */
50 | def exit = throw AmmoniteExit(())
51 |
52 | /**
53 | * Exit the Ammonite REPL. You can also use Ctrl-D to exit
54 | */
55 | def exit(value: Any) = throw AmmoniteExit(value)
56 |
57 | /**
58 | * Functions that will be chained and called on the
59 | * exitValue before the repl exits
60 | */
61 | val beforeExitHooks: mutable.Buffer[Any => Any]
62 |
63 | implicit def scalaVersion: ScalaVersion
64 |
65 | def _compilerManager: ammonite.compiler.iface.CompilerLifecycleManager
66 | }
67 |
68 | trait LoadJar {
69 |
70 | /**
71 | * Load a `.jar` file or directory into your JVM classpath
72 | */
73 | def cp(jar: os.Path): Unit
74 |
75 | /**
76 | * Load a `.jar` from a URL into your JVM classpath
77 | */
78 | def cp(jar: java.net.URL): Unit
79 |
80 | /**
81 | * Load one or more `.jar` files or directories into your JVM classpath
82 | */
83 | def cp(jars: Seq[os.Path]): Unit
84 |
85 | /**
86 | * Load a library from its maven/ivy coordinates
87 | */
88 | def ivy(coordinates: Dependency*): Unit
89 | }
90 |
91 | trait InterpLoad extends LoadJar {
92 |
93 | def module(path: os.Path): Unit
94 |
95 | def plugin: LoadJar
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/amm/interp/api/src/main/scala/ammonite/interp/api/IvyConstructor.scala:
--------------------------------------------------------------------------------
1 | package ammonite.interp.api
2 |
3 | import coursierapi.{Dependency, Module}
4 |
5 | case class ScalaVersion(value: String)
6 |
7 | object IvyConstructor extends IvyConstructor {
8 |
9 | def scalaBinaryVersion(sv: String) = {
10 | val retain = if (sv.startsWith("2")) 2 else 1
11 | sv.split('.').take(retain).mkString(".")
12 | }
13 |
14 | }
15 | trait IvyConstructor {
16 | implicit class GroupIdExt(groupId: String) {
17 | def %(artifactId: String) = Module.of(groupId, artifactId)
18 | def %%(artifactId: String)(implicit sv: ScalaVersion) = Module.of(
19 | groupId,
20 | artifactId + "_" + IvyConstructor.scalaBinaryVersion(sv.value)
21 | )
22 | }
23 | implicit class ArtifactIdExt(t: Module) {
24 | def %(version: String) = Dependency.of(t, version)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/amm/interp/src/main/scala/ammonite/interp/DependencyLoader.scala:
--------------------------------------------------------------------------------
1 | package ammonite.interp
2 |
3 | import java.io.File
4 |
5 | import ammonite.runtime.Storage
6 | import ammonite.util.Printer
7 | import coursierapi.{Dependency, Fetch, Repository}
8 |
9 | final class DependencyLoader(
10 | printer: Printer,
11 | storage: Storage,
12 | alreadyLoadedDependencies: Seq[Dependency],
13 | verboseOutput: Boolean
14 | ) {
15 |
16 | private val alwaysExclude = alreadyLoadedDependencies
17 | .map(dep => (dep.getModule.getOrganization, dep.getModule.getName))
18 | .toSet
19 |
20 | def load(
21 | coordinates: Seq[Dependency],
22 | repositories: => Seq[Repository],
23 | resolutionHooks: Seq[Fetch => Fetch]
24 | ): Either[String, Seq[File]] = {
25 | val repositories0 = repositories
26 | val cacheKey = (
27 | repositories0.hashCode.toString,
28 | coordinates
29 | // FIXME Add resolutionHooks somehow?
30 | )
31 |
32 | storage.ivyCache().get(cacheKey) match {
33 | case Some(res) => Right(res.map(new java.io.File(_)))
34 | case None =>
35 | ammonite.runtime.tools.IvyThing.resolveArtifact(
36 | repositories0,
37 | coordinates
38 | .filter(dep => !alwaysExclude((dep.getModule.getOrganization, dep.getModule.getName)))
39 | .map { dep =>
40 | alwaysExclude.iterator.foldLeft(Dependency.of(dep))((dep, excl) =>
41 | dep.addExclusion(excl._1, excl._2)
42 | )
43 | },
44 | verbose = verboseOutput,
45 | output = printer.errStream,
46 | hooks = resolutionHooks
47 | ) match {
48 | case Right((canBeCached, loaded)) =>
49 | if (canBeCached)
50 | storage.ivyCache() = storage.ivyCache().updated(
51 | cacheKey,
52 | loaded.map(_.getAbsolutePath)
53 | )
54 | Right(loaded)
55 | case Left(l) =>
56 | Left(l)
57 | }
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/amm/interp/src/main/scala/ammonite/interp/IvyThing.scala:
--------------------------------------------------------------------------------
1 | package ammonite.runtime.tools
2 |
3 | import java.io.PrintStream
4 |
5 | import coursierapi.{Cache, Dependency, Fetch, Logger, Repository}
6 |
7 | import scala.collection.JavaConverters._
8 | import scala.util.Try
9 |
10 | object IvyThing {
11 | def completer(
12 | repositories: Seq[Repository],
13 | verbose: Boolean
14 | ): String => (Int, Seq[String]) = {
15 | val cache = Cache.create()
16 | .withLogger(if (verbose) Logger.progressBars() else Logger.nop)
17 | val sv = scala.util.Properties.versionNumberString
18 | val sbv = sv.split('.').take(2).mkString(".")
19 |
20 | s =>
21 | val res = coursierapi.Complete.create()
22 | .withCache(cache)
23 | .withScalaVersion(sv)
24 | .withScalaBinaryVersion(sbv)
25 | .withInput(s)
26 | .complete()
27 | (res.getFrom, res.getCompletions.asScala.toVector)
28 | }
29 | def resolveArtifact(
30 | repositories: Seq[Repository],
31 | dependencies: Seq[Dependency],
32 | verbose: Boolean,
33 | output: PrintStream,
34 | hooks: Seq[Fetch => Fetch]
35 | ) = synchronized {
36 | val fetch = Fetch.create()
37 | .addDependencies(dependencies: _*)
38 | .withRepositories(repositories: _*)
39 | .withCache(
40 | Cache.create()
41 | .withLogger(if (verbose) Logger.progressBars(output) else Logger.nop)
42 | )
43 | .withMainArtifacts()
44 | .addClassifiers("sources")
45 |
46 | val finalFetch = Function.chain(hooks)(fetch)
47 | Try(finalFetch.fetchResult()).toEither match {
48 | case Left(err) => Left("Failed to resolve ivy dependencies:" + err.getMessage)
49 | case Right(res) =>
50 | // should really be fetch != finalFetch, but coursierapi.Fetch is mutable for now
51 | val customParams = hooks.nonEmpty
52 | def noChangingArtifact = res.getArtifacts.asScala.forall(!_.getKey.isChanging)
53 | def noVersionInterval = dependencies.map(_.getVersion).forall { v =>
54 | !v.startsWith("latest.") &&
55 | !v.exists(Set('[', ']', '(', ')')) &&
56 | !v.endsWith("+")
57 | }
58 | val files = res.getFiles.asScala.toList
59 | Right((!customParams && noChangingArtifact && noVersionInterval, files))
60 | }
61 | }
62 |
63 | val defaultRepositories = Repository.defaults().asScala.toList
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/amm/interp/src/main/scala/ammonite/interp/PredefInitialization.scala:
--------------------------------------------------------------------------------
1 | package ammonite.interp
2 |
3 | import ammonite.interp.api.InterpAPI
4 | import ammonite.runtime.{SpecialClassLoader, Storage}
5 | import ammonite.util.ScriptOutput.Metadata
6 | import ammonite.util.{ImportData, Imports, Name, PredefInfo, Res}
7 | import ammonite.util.Util.CodeSource
8 |
9 | /**
10 | * The logic around executing an [[Interpreter]]'s predef during
11 | * initialization
12 | */
13 | object PredefInitialization {
14 | def initBridge[T >: Null <: AnyRef](classloader: SpecialClassLoader, name: String, t: T) = {
15 | classloader.findClassPublic(name + "$")
16 | classloader.findClassPublic(name)
17 | .getDeclaredMethods
18 | .find(_.getName == "value0_$eq")
19 | .get
20 | .invoke(null, t)
21 | }
22 | def initBridges(bridges: Seq[(String, String)]): Imports = {
23 |
24 | val allImports =
25 | for ((name, shortName) <- bridges)
26 | yield Imports(
27 | Seq(ImportData(
28 | Name("value"),
29 | Name(shortName),
30 | // FIXME Not sure special chars / backticked things in name are fine here
31 | Name("_root_") +: name.stripPrefix("_root_.").split('.').map(Name(_)).toSeq,
32 | ImportData.Term
33 | ))
34 | )
35 |
36 | allImports.foldLeft(Imports())(_ ++ _)
37 | }
38 | def initBridges(
39 | bridges: Seq[(String, String, AnyRef)],
40 | evalClassloader: SpecialClassLoader
41 | ): Imports = {
42 |
43 | for ((name, shortName, bridge) <- bridges)
44 | initBridge(evalClassloader, name, bridge)
45 |
46 | initBridges(bridges.map { case (name, shortName, _) => (name, shortName) })
47 | }
48 | def apply(
49 | interpApi: InterpAPI,
50 | storage: Storage,
51 | basePredefs: Seq[PredefInfo],
52 | customPredefs: Seq[PredefInfo],
53 | processModule: (String, CodeSource, Boolean) => Res[Metadata],
54 | addImports: Imports => Unit,
55 | watch: os.Path => Unit
56 | ): Res[_] = {
57 |
58 | val predefs = {
59 | basePredefs ++
60 | storage.loadPredef.map {
61 | case (code, path) =>
62 | PredefInfo(Name(path.last.stripSuffix(".sc")), code, false, Some(path))
63 | } ++
64 | customPredefs
65 | }
66 |
67 | Res.fold((), predefs) { (_, predefInfo) =>
68 | predefInfo.path.foreach(watch)
69 | if (predefInfo.code.isEmpty) Res.Success(())
70 | else {
71 | processModule(
72 | predefInfo.code,
73 | CodeSource(
74 | predefInfo.name,
75 | Seq(),
76 | Seq(Name("ammonite"), Name("predef")),
77 | predefInfo.path
78 | ),
79 | predefInfo.hardcoded
80 | ) match {
81 | case Res.Skip => Res.Success(())
82 | case Res.Success(processed) =>
83 | addImports(processed.blockInfo.last.hookInfo.imports)
84 | addImports(processed.blockInfo.last.finalImports)
85 | Res.Success(())
86 |
87 | case x => x.map(_ => ())
88 | }
89 |
90 | }
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/amm/interp/src/main/scala/ammonite/interp/Watchable.scala:
--------------------------------------------------------------------------------
1 | package ammonite.interp
2 |
3 | trait Watchable {
4 | def poll(): Long
5 | }
6 | object Watchable {
7 | def mtimeIfExists(p: os.Path) = if (os.exists(p)) os.mtime(p) else 0L
8 |
9 | /**
10 | * Recursively mtimes things, with the sole purpose of providing a number
11 | * that will change if that file changes or that folder's contents changes
12 | *
13 | * Ensure we include the file paths within a folder as part of the folder
14 | * signature, as file moves often do not update the mtime but we want to
15 | * trigger a "something changed" event anyway
16 | */
17 | def pathSignature(p: os.Path) =
18 | if (!os.exists(p)) 0L
19 | else
20 | try {
21 | if (os.isDir(p)) os.walk(p).map(x => x.hashCode + mtimeIfExists(x)).sum
22 | else os.mtime(p)
23 | } catch {
24 | case e: java.nio.file.NoSuchFileException =>
25 | 0L
26 | }
27 | case class Path(p: os.Path) extends Watchable {
28 | def poll() = pathSignature(p)
29 | }
30 | case class Value(f: () => Long) extends Watchable {
31 | def poll() = f()
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/amm/interp/src/main/scala/ammonite/interp/script/Diagnostic.scala:
--------------------------------------------------------------------------------
1 | package ammonite.interp.script
2 |
3 | import ammonite.util.Position
4 |
5 | final case class Diagnostic(
6 | severity: String,
7 | start: Position,
8 | end: Position,
9 | message: String
10 | )
11 |
--------------------------------------------------------------------------------
/amm/interp/src/main/scala/ammonite/interp/script/DummyBuildServerImplems.scala:
--------------------------------------------------------------------------------
1 | package ammonite.interp.script
2 |
3 | import java.util.concurrent.CompletableFuture
4 | import ch.epfl.scala.bsp4j._
5 | import scala.collection.JavaConverters._
6 |
7 | private[script] trait DummyBuildServerImplems extends BuildServer with ScalaBuildServer {
8 | override def buildTargetDependencyModules(dmp: DependencyModulesParams)
9 | : CompletableFuture[DependencyModulesResult] =
10 | CompletableFuture.completedFuture(new DependencyModulesResult(List.empty.asJava))
11 |
12 | override def buildTargetOutputPaths(opp: OutputPathsParams)
13 | : CompletableFuture[OutputPathsResult] =
14 | CompletableFuture.completedFuture(new OutputPathsResult(List.empty.asJava))
15 |
16 | override def buildTargetResources(params: ResourcesParams): CompletableFuture[ResourcesResult] = {
17 | val items = params.getTargets.asScala.toList.map { target =>
18 | new ResourcesItem(target, List.empty[String].asJava)
19 | }
20 | val result = new ResourcesResult(items.asJava)
21 | CompletableFuture.completedFuture(result)
22 | }
23 |
24 | override def buildTargetRun(params: RunParams): CompletableFuture[RunResult] = {
25 | val result = new RunResult(StatusCode.ERROR)
26 | result.setOriginId(params.getOriginId)
27 | CompletableFuture.completedFuture(result)
28 | }
29 |
30 | override def buildTargetTest(params: TestParams): CompletableFuture[TestResult] = {
31 | val result = new TestResult(StatusCode.ERROR)
32 | result.setOriginId(params.getOriginId)
33 | CompletableFuture.completedFuture(result)
34 | }
35 |
36 | override def buildTargetScalaMainClasses(
37 | params: ScalaMainClassesParams
38 | ): CompletableFuture[ScalaMainClassesResult] = {
39 | val items = params.getTargets.asScala.map { target =>
40 | new ScalaMainClassesItem(target, List.empty[ScalaMainClass].asJava)
41 | }
42 | val result = new ScalaMainClassesResult(items.asJava)
43 | CompletableFuture.completedFuture(result)
44 | }
45 |
46 | override def buildTargetScalaTestClasses(
47 | params: ScalaTestClassesParams
48 | ): CompletableFuture[ScalaTestClassesResult] = {
49 | val items = params.getTargets.asScala.map { target =>
50 | new ScalaTestClassesItem(target, List.empty[String].asJava)
51 | }
52 | val result = new ScalaTestClassesResult(items.asJava)
53 | CompletableFuture.completedFuture(result)
54 | }
55 |
56 | override def debugSessionStart(dsp: DebugSessionParams): CompletableFuture[DebugSessionAddress] =
57 | CompletableFuture.completedFuture(new DebugSessionAddress(""))
58 |
59 | override def onBuildExit(): Unit = ()
60 | override def onBuildInitialized(): Unit = ()
61 |
62 | override def workspaceReload(): CompletableFuture[Object] =
63 | CompletableFuture.completedFuture(new {})
64 | }
65 |
--------------------------------------------------------------------------------
/amm/interp/src/main/scala/ammonite/interp/script/ScriptCompileResult.scala:
--------------------------------------------------------------------------------
1 | package ammonite.interp.script
2 |
3 | import ammonite.compiler.iface.Compiler.Output
4 |
5 | final case class ScriptCompileResult(
6 | diagnostics: Seq[Diagnostic],
7 | errorOrOutput: Either[String, Seq[Output]]
8 | )
9 |
--------------------------------------------------------------------------------
/amm/repl/api/src/main/scala-2.12/ammonite/repl/api/History.scala:
--------------------------------------------------------------------------------
1 | package ammonite.repl.api
2 |
3 | import scala.collection.generic.CanBuildFrom
4 | import scala.collection.{IndexedSeqLike, mutable}
5 |
6 | class History(s: Vector[String])
7 | extends IndexedSeq[String]
8 | with IndexedSeqLike[String, History] {
9 | def length: Int = s.length
10 | def apply(idx: Int): String = s.apply(idx)
11 | override def newBuilder = History.builder
12 | }
13 |
14 | object History {
15 | def builder = new mutable.Builder[String, History] {
16 | val buffer = mutable.Buffer.empty[String]
17 | def +=(elem: String): this.type = { buffer += elem; this }
18 |
19 | def result(): History = new History(buffer.toVector)
20 |
21 | def clear(): Unit = buffer.clear()
22 | }
23 | implicit def cbf = new CanBuildFrom[History, String, History] {
24 | def apply(from: History) = builder
25 | def apply() = builder
26 | }
27 | implicit def toHistory(s: Seq[String]): History = new History(s.toVector)
28 | }
29 |
--------------------------------------------------------------------------------
/amm/repl/api/src/main/scala-2.13-or-3/ammonite/repl/api/History.scala:
--------------------------------------------------------------------------------
1 | package ammonite.repl.api
2 |
3 | import scala.collection.generic.IsSeq
4 | import scala.collection.{Iterable, SeqOps, mutable}
5 |
6 | class History(s: Vector[String])
7 | extends IndexedSeq[String] {
8 | def length: Int = s.length
9 | def apply(idx: Int): String = s.apply(idx)
10 |
11 | override protected def newSpecificBuilder: mutable.Builder[String, History] =
12 | History.builder
13 | }
14 |
15 | object History {
16 | def builder = new mutable.Builder[String, History] {
17 | val buffer = mutable.Buffer.empty[String]
18 | def addOne(elem: String): this.type = { buffer += elem; this }
19 |
20 | def result(): History = new History(buffer.toVector)
21 |
22 | def clear(): Unit = buffer.clear()
23 | }
24 | implicit def toHistory(s: Seq[String]): History = new History(s.toVector)
25 | }
26 |
--------------------------------------------------------------------------------
/amm/repl/api/src/main/scala-2/ammonite/repl/FullReplAPIScalaVersionSpecific.scala:
--------------------------------------------------------------------------------
1 | package ammonite.repl
2 |
3 | import scala.reflect.runtime.universe._
4 |
5 | trait FullReplAPIScalaVersionSpecific {
6 |
7 | def typeOf[T: WeakTypeTag] = scala.reflect.runtime.universe.weakTypeOf[T]
8 | def typeOf[T: WeakTypeTag](t: => T) = scala.reflect.runtime.universe.weakTypeOf[T]
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/amm/repl/api/src/main/scala-2/ammonite/repl/api/ReplAPIScalaVersionSpecific.scala:
--------------------------------------------------------------------------------
1 | package ammonite.repl.api
2 |
3 | import scala.reflect.runtime.universe._
4 |
5 | trait ReplAPIScalaVersionSpecific {
6 |
7 | /**
8 | * Get the `Type` object of [[T]]. Useful for finding
9 | * what its methods are and what you can do with it
10 | */
11 | def typeOf[T: WeakTypeTag]: Type
12 |
13 | /**
14 | * Get the `Type` object representing the type of `t`. Useful
15 | * for finding what its methods are and what you can do with it
16 | */
17 | def typeOf[T: WeakTypeTag](t: => T): Type
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/amm/repl/api/src/main/scala-3/ammonite/repl/FullReplAPIScalaVersionSpecific.scala:
--------------------------------------------------------------------------------
1 | package ammonite.repl
2 |
3 | trait FullReplAPIScalaVersionSpecific
4 |
--------------------------------------------------------------------------------
/amm/repl/api/src/main/scala-3/ammonite/repl/api/ReplAPIScalaVersionSpecific.scala:
--------------------------------------------------------------------------------
1 | package ammonite.repl.api
2 |
3 | trait ReplAPIScalaVersionSpecific
4 |
--------------------------------------------------------------------------------
/amm/repl/api/src/main/scala/ammonite/repl/api/FrontEnd.scala:
--------------------------------------------------------------------------------
1 | package ammonite.repl.api
2 |
3 | import java.io.{InputStream, OutputStream}
4 |
5 | import ammonite.util.{Colors, Res}
6 |
7 | /** JLine interface */
8 | trait FrontEnd {
9 | def width: Int
10 | def height: Int
11 | def action(
12 | input: InputStream,
13 | reader: java.io.Reader,
14 | output: OutputStream,
15 | prompt: String,
16 | colors: Colors,
17 | compilerComplete: (Int, String) => (Int, Seq[String], Seq[String]),
18 | history: IndexedSeq[String],
19 | addHistory: String => Unit
20 | ): Res[(String, Seq[String])]
21 | }
22 |
--------------------------------------------------------------------------------
/amm/repl/api/src/main/scala/ammonite/repl/api/FrontEndAPI.scala:
--------------------------------------------------------------------------------
1 | package ammonite.repl.api
2 |
3 | import ammonite.interp.api.APIHolder
4 |
5 | trait FrontEndAPI {
6 | def apply(name: String): FrontEnd
7 | }
8 |
9 | object FrontEndBridge extends APIHolder[FrontEndAPI]
10 |
--------------------------------------------------------------------------------
/amm/repl/api/src/main/scala/ammonite/repl/api/SessionChanged.scala:
--------------------------------------------------------------------------------
1 | package ammonite.repl.api
2 |
3 | trait SessionChanged {
4 | def removedImports: Set[scala.Symbol]
5 | def addedImports: Set[scala.Symbol]
6 | def removedJars: Set[java.net.URL]
7 | def addedJars: Set[java.net.URL]
8 | }
9 |
--------------------------------------------------------------------------------
/amm/repl/api/src/main/scala/ammonite/repl/tools/Util.scala:
--------------------------------------------------------------------------------
1 | package ammonite.repl.tools
2 |
3 | object Util {
4 |
5 | /**
6 | * Additional [[mainargs.TokensReader]] instance to teach it how to read Ammonite paths
7 | */
8 | implicit object PathRead extends mainargs.TokensReader.Simple[os.Path] {
9 | def shortName = "path"
10 | def read(strs: Seq[String]) = Right(os.Path(strs.last, os.pwd))
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/amm/repl/api/src/main/scala/ammonite/runtime/tools/package.scala:
--------------------------------------------------------------------------------
1 | package ammonite
2 |
3 | /**
4 | * Things that are available inside the Ammonite REPL, are really convenient
5 | * to have available.
6 | */
7 | package object tools
8 |
--------------------------------------------------------------------------------
/amm/repl/src/main/scala-2/ammonite/main/DefaultsScalaVersionSpecific.scala:
--------------------------------------------------------------------------------
1 | package ammonite.main
2 |
3 | import ammonite.util.{ImportData, Imports}
4 |
5 | private[main] trait DefaultsScalaVersionSpecific {
6 | val replImports = Imports(
7 | ImportData("""ammonite.repl.ReplBridge.value.{
8 | codeColorsImplicit,
9 | tprintColorsImplicit,
10 | show,
11 | typeOf
12 | }""")
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/amm/repl/src/main/scala-3/ammonite/main/DefaultsScalaVersionSpecific.scala:
--------------------------------------------------------------------------------
1 | package ammonite.main
2 |
3 | import ammonite.util.{ImportData, Imports}
4 |
5 | private[main] trait DefaultsScalaVersionSpecific {
6 | val replImports = Imports(
7 | ImportData("""ammonite.repl.ReplBridge.value.{
8 | codeColorsImplicit,
9 | tprintColorsImplicit,
10 | show
11 | }""")
12 | )
13 | }
14 |
--------------------------------------------------------------------------------
/amm/repl/src/main/scala/ammonite/main/Defaults.scala:
--------------------------------------------------------------------------------
1 | package ammonite.main
2 |
3 | import java.io.InputStream
4 |
5 | import ammonite.util.Util
6 | import coursierapi.Dependency
7 |
8 | import scala.io.Codec
9 |
10 | /**
11 | * Constants used in the default configuration for the Ammonite REPL
12 | */
13 | object Defaults extends DefaultsScalaVersionSpecific {
14 |
15 | val welcomeBanner = {
16 | def ammoniteVersion = ammonite.Constants.version
17 | def javaVersion = System.getProperty("java.version")
18 | Util.normalizeNewlines(
19 | s"Welcome to the Ammonite Repl $ammoniteVersion (Scala %SCALA_VERSION% Java $javaVersion)"
20 | )
21 | }
22 |
23 | def ammoniteHome = os.Path(System.getProperty("user.home")) / ".ammonite"
24 |
25 | def alreadyLoadedDependencies(
26 | resourceName: String = "amm-dependencies.txt"
27 | ): Seq[Dependency] = {
28 |
29 | var is: InputStream = null
30 |
31 | try {
32 | is = Thread.currentThread().getContextClassLoader.getResourceAsStream(resourceName)
33 | if (is == null)
34 | throw new Exception(s"Resource $resourceName not found")
35 | scala.io.Source.fromInputStream(is)(Codec.UTF8)
36 | .mkString
37 | .split('\n')
38 | .filter(_.nonEmpty)
39 | .map(l =>
40 | l.split(':') match {
41 | case Array(org, name, ver) =>
42 | Dependency.of(org, name, ver)
43 | case other =>
44 | throw new Exception(s"Cannot parse line '$other' from resource $resourceName")
45 | }
46 | )
47 | } finally {
48 | if (is != null)
49 | is.close()
50 | }
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/amm/repl/src/main/scala/ammonite/repl/FrontEndUtils.scala:
--------------------------------------------------------------------------------
1 | package ammonite.repl
2 | import scala.annotation.tailrec
3 |
4 | import ammonite.util.Util.newLine
5 |
6 | /**
7 | * Created by haoyi on 8/29/15.
8 | */
9 | object FrontEndUtils {
10 | def width =
11 | if (scala.util.Properties.isWin) ammonite.repl.FrontEnds.width
12 | else ammonite.terminal.ConsoleDim.width()
13 | def height =
14 | if (scala.util.Properties.isWin) ammonite.repl.FrontEnds.height
15 | else ammonite.terminal.ConsoleDim.height()
16 | def tabulate(snippetsRaw: Seq[fansi.Str], width: Int): Iterator[String] = {
17 | val gap = 2
18 | val snippets = if (snippetsRaw.isEmpty) Seq(fansi.Str("")) else snippetsRaw
19 | val maxLength = snippets.maxBy(_.length).length + gap
20 | val columns = math.max(1, width / maxLength)
21 |
22 | val grouped =
23 | snippets.toList
24 | .grouped(math.ceil(snippets.length * 1.0 / columns).toInt)
25 | .toList
26 |
27 | ammonite.util.Util.transpose(grouped).iterator.flatMap {
28 | case first :+ last =>
29 | first.map(x => x ++ " " * (width / columns - x.length)) :+ last :+ fansi.Str(newLine)
30 | }.map(_.render)
31 | }
32 |
33 | @tailrec def findPrefix(strings: Seq[String], i: Int = 0): String = {
34 | if (strings.count(_.length > i) == 0) strings(0).take(i)
35 | else if (strings.collect { case x if x.length > i => x(i) }.distinct.length > 1)
36 | strings(0).take(i)
37 | else findPrefix(strings, i + 1)
38 | }
39 |
40 | def printCompletions(completions: Seq[String], details: Seq[String]): List[String] = {
41 |
42 | val prelude =
43 | if (details.length != 0 || completions.length != 0) List(newLine)
44 | else Nil
45 |
46 | val detailsText =
47 | if (details.length == 0) Nil
48 | else FrontEndUtils.tabulate(details.map(fansi.Str(_)), FrontEndUtils.width)
49 |
50 | val completionText =
51 | if (completions.length == 0) Nil
52 | else FrontEndUtils.tabulate(completions.map(fansi.Str(_)), FrontEndUtils.width)
53 |
54 | prelude ++ detailsText ++ completionText
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/amm/repl/src/main/scala/ammonite/repl/PPrints.scala:
--------------------------------------------------------------------------------
1 | package ammonite.repl
2 |
3 | import ammonite.repl.api.History
4 | import ammonite.runtime.tools.GrepResult
5 | import ammonite.util.Util
6 | import pprint.Renderer
7 |
8 | object PPrints {
9 | def replPPrintHandlers(width: => Int): PartialFunction[Any, pprint.Tree] = {
10 | // case x: os.Path => PPrints.pathRepr(x)
11 | // case x: os.RelPath => PPrints.relPathRepr(x)
12 | case t: History => pprint.Tree.Lazy(ctx => Iterator(t.mkString(Util.newLine)))
13 | case t: GrepResult => pprint.Tree.Lazy(ctx => Iterator(GrepResult.grepResultRepr(t, ctx)))
14 | case t: scala.xml.Elem => pprint.Tree.Lazy(_ => Iterator(t.toString))
15 | }
16 |
17 | def reprSection(s: String, cfg: pprint.Tree.Ctx): fansi.Str = {
18 | val validIdentifier = "([a-zA-Z_][a-zA-Z_0-9]+)".r
19 |
20 | if (validIdentifier.findFirstIn(s) == Some(s)) {
21 | cfg.literalColor('\'' + s)
22 | } else {
23 | cfg.literalColor(pprint.Util.literalize(s))
24 | }
25 | }
26 |
27 | def relPathRepr(p: os.RelPath) = pprint.Tree.Lazy(ctx =>
28 | Iterator(
29 | (Seq.fill(p.ups)("up") ++ p.segments.map(reprSection(_, ctx))).mkString("/")
30 | )
31 | )
32 |
33 | def pathRepr(p: os.Path) = pprint.Tree.Lazy(ctx =>
34 | Iterator("root") ++ p.segments.map("/" + reprSection(_, ctx))
35 | )
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/amm/repl/src/main/scala/ammonite/repl/Signaller.scala:
--------------------------------------------------------------------------------
1 | package ammonite.repl
2 |
3 | import sun.misc.{Signal, SignalHandler}
4 |
5 | object Signaller {
6 | val handlers = scala.collection.mutable.Map[Signal, List[SignalHandler]]()
7 | }
8 |
9 | /**
10 | * Lets you turn on signal handling within a certain block,
11 | * attaching a callback to the handler and then turning it
12 | * properly off again when the block exits. Does sketchy
13 | * `unsafe` stuff because that's the only way you can make
14 | * it properly reset when you're finished.
15 | */
16 | case class Signaller(sigStr: String)(f: => Unit) extends Scoped {
17 | import Signaller._
18 |
19 | def apply[T](t: => T): T = {
20 | val handler = new SignalHandler() {
21 | def handle(sig: Signal) = f
22 | }
23 |
24 | val sig = new Signal(sigStr)
25 |
26 | handlers(sig) = sun.misc.Signal.handle(sig, handler) :: handlers.getOrElse(sig, List())
27 |
28 | try t
29 | finally {
30 | val head :: tail = handlers(sig)
31 | handlers(sig) = tail
32 | val handlerToRegister = tail.headOption.getOrElse(sun.misc.SignalHandler.SIG_DFL)
33 | sun.misc.Signal.handle(sig, handlerToRegister)
34 | }
35 | }
36 | }
37 |
38 | /**
39 | * Converts something with a scoped `apply` method into
40 | * something which can be similarly used in a for-comprehension
41 | */
42 | trait Scoped {
43 | def apply[T](t: => T): T
44 | def foreach[T](t: Unit => T): T = apply(t(()))
45 | def flatMap[T](t: Unit => T): T = apply(t(()))
46 | def map[T](t: Unit => T): T = apply(t(()))
47 | }
48 |
--------------------------------------------------------------------------------
/amm/repl/src/main/scala/ammonite/repl/package.scala:
--------------------------------------------------------------------------------
1 | package ammonite
2 |
3 | /**
4 | * Everything to do with the interaction of the Ammonite REPL with the user
5 | * and the terminal. Interfacing with ammonite-terminal (or with JLine)
6 | */
7 | package object repl
8 |
--------------------------------------------------------------------------------
/amm/repl/src/test/scala/ammonite/DualTestRepl.scala:
--------------------------------------------------------------------------------
1 | package ammonite
2 |
3 | import ammonite.compiler.CodeClassWrapper
4 | import ammonite.util.{Evaluated, Res}
5 |
6 | /**
7 | * Wraps several [[TestRepl]], and runs its tests against all of them.
8 | */
9 | class DualTestRepl { dual =>
10 |
11 | def predef: (String, Option[os.Path]) = ("", None)
12 | def wrapperNamePrefix = Option.empty[String]
13 |
14 | def warnings = true
15 |
16 | def compilerBuilder = ammonite.compiler.CompilerBuilder()
17 | val repls = Seq(
18 | new TestRepl(compilerBuilder) {
19 | override def predef = dual.predef
20 | override def wrapperNamePrefix = dual.wrapperNamePrefix
21 | override def warnings = dual.warnings
22 | },
23 | new TestRepl(compilerBuilder) {
24 | override def predef = dual.predef
25 | override def codeWrapper = CodeClassWrapper
26 | override def wrapperNamePrefix = dual.wrapperNamePrefix
27 | override def warnings = dual.warnings
28 | }
29 | )
30 |
31 | def scalaVersion = compilerBuilder.scalaVersion
32 | lazy val scalaBinaryVersion =
33 | if (scalaVersion.startsWith("2.")) scalaVersion.split('.').take(2).mkString(".")
34 | else scalaVersion.takeWhile(_ != '.')
35 | def scala2 = scalaVersion.startsWith("2.")
36 | def scala2_12 = scalaVersion.startsWith("2.12.")
37 | def scala3_5_1OrHigher =
38 | (scalaVersion.startsWith("3.5.") && scalaVersion.split("\\.")(2).toInt >= 1) ||
39 | scalaVersion.split("\\.")(1).toInt >= 6
40 |
41 | def interps = repls.map(_.interp)
42 |
43 | def session(sess: String): Unit =
44 | repls.foreach(_.session(sess))
45 | def session(objWrapperSess: String, classWrapperSess: String): Unit =
46 | repls.foreach { repl =>
47 | val sess = if (repl.codeWrapper == CodeClassWrapper) classWrapperSess else objWrapperSess
48 | repl.session(sess)
49 | }
50 | def result(input: String, expected: Res[Evaluated]): Unit =
51 | repls.foreach(_.result(input, expected))
52 | def fail(input: String, failureCheck: String => Boolean = _ => true): Unit =
53 | repls.foreach(_.fail(input, failureCheck))
54 |
55 | def notFound(name: String): String =
56 | repls.headOption.fold("")(_.notFound(name))
57 | }
58 |
--------------------------------------------------------------------------------
/amm/repl/src/test/scala/ammonite/SerializationUtil.scala:
--------------------------------------------------------------------------------
1 | package ammonite
2 |
3 | object SerializationUtil {
4 |
5 | import java.io._
6 |
7 | def serialize(m: AnyRef): Array[Byte] = {
8 | val baos = new ByteArrayOutputStream()
9 | val oos = new ObjectOutputStream(baos)
10 | try {
11 | oos.writeObject(m)
12 | baos.toByteArray
13 | } finally oos.close()
14 | }
15 |
16 | def deserialize(b: Array[Byte], loader: ClassLoader): AnyRef = {
17 | val bais = new ByteArrayInputStream(b)
18 | val ois = new ClassLoaderObjectInputStream(loader, bais)
19 | try ois.readObject()
20 | finally ois.close()
21 | }
22 |
23 | // from akka.util
24 |
25 | /**
26 | * ClassLoaderObjectInputStream tries to utilize the provided ClassLoader
27 | * to load Classes and falls back to ObjectInputStreams resolver.
28 | *
29 | * @param classLoader - the ClassLoader which is to be used primarily
30 | * @param is - the InputStream that is wrapped
31 | */
32 | class ClassLoaderObjectInputStream(
33 | classLoader: ClassLoader,
34 | is: InputStream
35 | ) extends ObjectInputStream(is) {
36 | override protected def resolveClass(objectStreamClass: ObjectStreamClass): Class[_] =
37 | try Class.forName(objectStreamClass.getName, false, classLoader)
38 | catch {
39 | case cnfe: ClassNotFoundException ⇒ super.resolveClass(objectStreamClass)
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/amm/repl/src/test/scala/ammonite/TestReplBridge.scala:
--------------------------------------------------------------------------------
1 | package ammonite
2 |
3 | import ammonite.interp.api.APIHolder
4 |
5 | trait TestReplApi {
6 | def message: String
7 | }
8 |
9 | object TestReplBridge extends APIHolder[TestReplApi]
10 |
11 | case class Nope(n: Int)
12 |
--------------------------------------------------------------------------------
/amm/repl/src/test/scala/ammonite/interp/PrintTests.scala:
--------------------------------------------------------------------------------
1 | package ammonite.interp
2 |
3 | import ammonite.DualTestRepl
4 | import ammonite.util.Util.newLine
5 | import utest._
6 |
7 | object PrintTests extends TestSuite {
8 | val tests = Tests {
9 | println("PrintTests")
10 | val check = new DualTestRepl()
11 |
12 | test("simple") {
13 | for (repl <- check.repls) {
14 | val t @ (ev, out, res, warn, err, inf) = repl.run("val n = 2", 0)
15 | val expectedRes = "n: Int = 2"
16 |
17 | assert({ identity(t); ev.isSuccess })
18 | assert({ identity(t); out.isEmpty })
19 | assert({ identity(t); res == expectedRes })
20 | }
21 | }
22 |
23 | test("out") {
24 | for (repl <- check.repls) {
25 | val t @ (ev, out, res, warn, err, inf) = repl.run("show(List(1, 2, 3))", 0)
26 | val expectedOut = "List(1, 2, 3)" + newLine
27 |
28 | assert({ identity(t); ev.isSuccess })
29 | assert({ identity(t); out == expectedOut })
30 | assert({ identity(t); res.isEmpty })
31 | }
32 | }
33 |
34 | test("both") {
35 | for (repl <- check.repls) {
36 | val t @ (ev, out, res, warn, err, inf) = repl.run("show(List(1, 2, 3)); val n = 3", 0)
37 | val expectedOut = "List(1, 2, 3)" + newLine
38 | val expectedRes = "n: Int = 3"
39 |
40 | assert({ identity(t); ev.isSuccess })
41 | assert({ identity(t); out == expectedOut })
42 | assert({ identity(t); res == expectedRes })
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/amm/repl/src/test/scala/ammonite/testcode/PaulpImports.scala:
--------------------------------------------------------------------------------
1 | package ammonite.testcode
2 |
3 | package paulp1 {
4 | class Paulp {
5 | override def toString = "paulp1.Paulp1"
6 | }
7 | }
8 |
9 | package paulp2 {
10 | object Paulp {
11 | override def toString = "paulp2.Paulp2"
12 | }
13 | }
14 |
15 | package paulp3 {
16 | object Paulp {
17 | override def toString = "paulp3.Paulp-object"
18 | }
19 | class Paulp {
20 | override def toString = "paulp3.Paulp-class"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/amm/repl/src/test/scala/ammonite/unit/ClipboardTests.scala:
--------------------------------------------------------------------------------
1 | package ammonite.unit
2 |
3 | import ammonite.repl.api.Clipboard
4 | import ammonite.repl.ClipboardImpl
5 |
6 | import java.awt.Toolkit
7 | import java.awt.datatransfer.DataFlavor
8 |
9 | import utest._
10 |
11 | import scala.util.Try
12 |
13 | object ClipboardTests extends TestSuite {
14 |
15 | val clipboard: Clipboard = ClipboardImpl
16 |
17 | /**
18 | * This test suite requires an environment with access to a window
19 | * service (either under, Windows, MacOs, X11, ...) CI environment
20 | * doesn't satisfy that condition and that is detected in the following
21 | * check in order to skip [[Clipboard]] test when running on CI.
22 | */
23 | val canTest = Try(
24 | Toolkit.getDefaultToolkit.getSystemClipboard.isDataFlavorAvailable(
25 | DataFlavor.stringFlavor
26 | )
27 | ).getOrElse(false)
28 |
29 | override def tests = Tests {
30 | println("ClipboardTests")
31 | test("clipboard") {
32 | val newClipboardContents = "hello Ammonite"
33 | test("copyandpaste") {
34 | if (canTest) {
35 | clipboard.write(newClipboardContents)
36 | assert(clipboard.read == newClipboardContents)
37 | } else {
38 | println(
39 | "The environment doesn't allow testing clipboard - skipping"
40 | )
41 | }
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/amm/runtime/src/main/scala/ammonite/runtime/package.scala:
--------------------------------------------------------------------------------
1 | package ammonite
2 |
3 | /**
4 | * What actually lets us compile and execute code in the Ammonite REPL; deals
5 | * with the Scala compiler, preprocessing the strings, JVM classloaders, etc.
6 | */
7 | package object runtime
8 |
--------------------------------------------------------------------------------
/amm/src/main/scala/ammonite/main/ProxyFromEnv.scala:
--------------------------------------------------------------------------------
1 | package ammonite.main
2 |
3 | /**
4 | * Give Ammonite the ability to read (linux) system proxy environment variables
5 | * and convert them into java proxy properties. Which allows Ammonite to work
6 | * through proxy automatically, instead of setting `System.properties` manually.
7 | *
8 | * See issue 460.
9 | *
10 | * Parameter pattern:
11 | * https://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html
12 | *
13 | * Created by cuz on 17-5-21.
14 | */
15 | private[ammonite] object ProxyFromEnv {
16 | private lazy val KeyPattern = """([\w\d]+)_proxy""".r
17 | private lazy val UrlPattern = """([\w\d]+://)?(.+@)?([\w\d\.\-]+):(\d+)/?""".r
18 |
19 | /**
20 | * Get current proxy environment variables.
21 | */
22 | private def getEnvs =
23 | sys.env.map { case (k, v) => (k.toLowerCase, v.toLowerCase) }
24 | .filterKeys(_.endsWith("proxy"))
25 | .toMap
26 |
27 | /**
28 | * Convert single proxy environment variable to corresponding system proxy properties.
29 | */
30 | private def envToProps(env: (String, String)): Map[String, String] = env match {
31 | case ("no_proxy", noProxySeq) =>
32 | val converted = noProxySeq.split(""",""").mkString("|")
33 | // https uses the same as http's. Ftp need not to be set here.
34 | Map("http.nonProxyHosts" -> converted)
35 |
36 | case (KeyPattern(proto), UrlPattern(_, cred, host, port)) =>
37 | val propHost = s"$proto.proxyHost" -> host
38 | val propPort = s"$proto.proxyPort" -> port
39 | val propCred = if (cred.isDefined) {
40 | val credPair = cred.dropRight(1).split(":")
41 | val propUser = s"$proto.proxyUser" -> credPair.head
42 | val propPassword = credPair.drop(1).map(s"$proto.proxyPassword" -> _)
43 | Seq(propUser) ++ propPassword
44 | } else Nil
45 | (Seq(propHost, propPort) ++ propCred).toMap
46 | case bad => Map.empty
47 | }
48 |
49 | /**
50 | * Set system proxy properties from environment variables.
51 | * Existing properties will not be overwritten.
52 | */
53 | def setPropProxyFromEnv(envs: Map[String, String] = this.getEnvs): Unit = {
54 | val sysProps = sys.props
55 | val proxyProps = envs.flatMap { env =>
56 | val props = envToProps(env)
57 | props
58 | }.filter(p => !sysProps.exists(sp => sp._1 == p._1))
59 | sysProps ++= proxyProps
60 | }
61 |
62 | /**
63 | * helper implicit conversion: add isDefined method to String.
64 | */
65 | implicit private class StringIsDefined(s: String) {
66 | def isDefined: Boolean = s != null && s.length > 0
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/amm/src/main/scala/ammonite/main/TrapExitSecurityManager.scala:
--------------------------------------------------------------------------------
1 | package ammonite.main
2 | import java.security.Permission
3 |
4 | /**
5 | * This security manager is assigned as default one when we run user scripts with the --watch option
6 | * This allows to trap sys.exit by throwing a special TrapExitException
7 | */
8 | object TrapExitSecurityManager extends SecurityManager {
9 |
10 | override def checkExit(status: Int): Unit = throw new TrapExitException(status)
11 |
12 | override def checkPermission(perm: Permission): Unit = {}
13 |
14 | private class TrapExitException(status: Int) extends RuntimeException {
15 | override def toString: String = s"script exited with status $status"
16 | override def getStackTrace: Array[StackTraceElement] = Array.empty
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/amm/src/main/scala/ammonite/main/package.scala:
--------------------------------------------------------------------------------
1 | package ammonite
2 |
3 | /**
4 | * Code related to invoking Ammonite from the outside world: default
5 | * configuration, running scripts, printing error messages, etc.
6 | */
7 | package object main
8 |
--------------------------------------------------------------------------------
/amm/src/test/resources/bsp/comment/script.sc:
--------------------------------------------------------------------------------
1 | // foo
--------------------------------------------------------------------------------
/amm/src/test/resources/bsp/dash-1/main-1.sc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/amm/src/test/resources/bsp/dash-1/main-1.sc
--------------------------------------------------------------------------------
/amm/src/test/resources/bsp/error/error-and-invalid-import-file.sc:
--------------------------------------------------------------------------------
1 | import $file.nope.nope.nope
2 |
3 | zz
4 |
--------------------------------------------------------------------------------
/amm/src/test/resources/bsp/error/foo.sc:
--------------------------------------------------------------------------------
1 | aa
2 | val n = 2
3 |
4 | zz
5 |
6 | val p = n + 1
--------------------------------------------------------------------------------
/amm/src/test/resources/bsp/error/invalid-import-file.sc:
--------------------------------------------------------------------------------
1 | import scala.collection.mutable._
2 | import $file.nope.nope.nope
3 |
4 | val n = 2
5 |
--------------------------------------------------------------------------------
/amm/src/test/resources/bsp/import-file/lib.sc:
--------------------------------------------------------------------------------
1 |
2 | val value = 2
3 |
--------------------------------------------------------------------------------
/amm/src/test/resources/bsp/import-file/script.sc:
--------------------------------------------------------------------------------
1 |
2 | import $file.lib, lib.value
3 |
4 | println(value + 1)
5 |
--------------------------------------------------------------------------------
/amm/src/test/resources/bsp/multi/lib1.sc:
--------------------------------------------------------------------------------
1 | trait HasFoo {
2 | def foo: String = "foo"
3 | }
--------------------------------------------------------------------------------
/amm/src/test/resources/bsp/multi/lib2.sc:
--------------------------------------------------------------------------------
1 | import $ivy.`io.circe::circe-core:0.12.3 compat`
2 | import $ivy.`io.circe::circe-generic:0.12.3 compat`
3 | import $ivy.`io.circe::circe-parser:0.12.3 compat`
4 |
5 | import $file.lib1, lib1.HasFoo
6 |
7 | trait HasReallyFoo extends HasFoo
8 |
--------------------------------------------------------------------------------
/amm/src/test/resources/bsp/multi/lib3.sc:
--------------------------------------------------------------------------------
1 | // See https://github.com/Baccata/gradle-simple/blob/master/src/main/java/Hello.java
2 | import $repo.`https://jitpack.io`
3 | import $ivy.`com.github.jupyter:jvm-repr:0.4.0`
4 |
5 | import jupyter.Displayers
6 |
--------------------------------------------------------------------------------
/amm/src/test/resources/bsp/multi/script.sc:
--------------------------------------------------------------------------------
1 | import $file.lib2, lib2.HasReallyFoo
2 | import $file.lib3
3 | import io.circe._, io.circe.generic.auto._, io.circe.parser._, io.circe.syntax._
4 |
5 | sealed trait Foo extends HasReallyFoo
6 | case class Bar(xs: Vector[String]) extends Foo
7 | case class Qux(i: Int, d: Option[Double]) extends Foo
8 |
9 | val foo: Foo = Qux(13, Some(14.0))
10 |
11 | val json = foo.asJson.noSpaces
12 |
13 | val decodedFoo = decode[Foo](json)
14 |
15 | val helloFromJupyter = jupyter.Displayers.registration
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/amm/src/test/resources/bsp/semdb/other.sc:
--------------------------------------------------------------------------------
1 | val list = List(1, 2)
2 |
--------------------------------------------------------------------------------
/amm/src/test/resources/bsp/semdb/script.sc:
--------------------------------------------------------------------------------
1 |
2 | import $ivy.`com.softwaremill.sttp.client::core:2.0.6 compat`
3 | import sttp.client.quick._
4 | quickRequest.get(uri"http://httpbin.org/ip").send()
5 |
--------------------------------------------------------------------------------
/amm/src/test/resources/bsp/simple/script.sc:
--------------------------------------------------------------------------------
1 |
2 | import $ivy.`com.softwaremill.sttp.client::core:2.0.6 compat`
3 | import sttp.client.quick._
4 | quickRequest.get(uri"http://httpbin.org/ip").send()
5 |
--------------------------------------------------------------------------------
/amm/src/test/resources/importHooks/Basic.sc:
--------------------------------------------------------------------------------
1 | // Basic.sc
2 | val basicValue = 31337
3 |
4 |
--------------------------------------------------------------------------------
/amm/src/test/resources/importHooks/BasicTwo.sc:
--------------------------------------------------------------------------------
1 | val basicValueTwo = 1337
2 |
3 |
--------------------------------------------------------------------------------
/amm/src/test/resources/importHooks/Deep.sc:
--------------------------------------------------------------------------------
1 | object DeepObject{
2 | object DeepInner {
3 | val deepValue = "deeeep"
4 | }
5 | }
6 |
7 |
8 |
--------------------------------------------------------------------------------
/amm/src/test/resources/importHooks/DeepImport.sc:
--------------------------------------------------------------------------------
1 | import $file.Deep, Deep.DeepObject.DeepInner.deepValue
2 |
3 | val deepValueImported = deepValue
--------------------------------------------------------------------------------
/amm/src/test/resources/importHooks/FileImport.sc:
--------------------------------------------------------------------------------
1 | // FileImport.sc
2 | import $file.Basic
3 |
4 | val fileImportVal = Basic.basicValue + 1
--------------------------------------------------------------------------------
/amm/src/test/resources/importHooks/IndirectFileImport.sc:
--------------------------------------------------------------------------------
1 | // IndirectFileImport.sc
2 | import $file.FileImport
3 |
4 | val indirectFileImportVal = FileImport.fileImportVal + 1
--------------------------------------------------------------------------------
/amm/src/test/resources/importHooks/IvyImport.sc:
--------------------------------------------------------------------------------
1 | import $ivy.`com.lihaoyi::scalatags:0.7.0 compat`, scalatags.Text.all._
2 |
3 | val rendered = div("Moo").render
--------------------------------------------------------------------------------
/amm/src/test/resources/importHooks/UrlImport.sc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/amm/src/test/resources/importHooks/UrlImport.sc
--------------------------------------------------------------------------------
/amm/src/test/resources/lineNumbers/CompilationErrorLineNumberTest.sc:
--------------------------------------------------------------------------------
1 | // Test Code
2 |
3 | object test{
4 |
5 |
6 |
7 | val x = noSuchObject.badFunction
8 |
9 | }
10 |
11 |
12 |
--------------------------------------------------------------------------------
/amm/src/test/resources/lineNumbers/ErrorLineNumberTest.sc:
--------------------------------------------------------------------------------
1 | object Qs{
2 | def main(a: Int) = {
3 | println("OK")
4 | var unsorted: List[Int] = List(5,4,2,3,1)
5 | printlnqs(unsorted))
6 | }
7 |
8 | def qs(unsorted: List[Int]): List[Int] = {
9 | if(unsorted.length <= 1) unsorted
10 | else{
11 | val pivot = unsorted.head
12 | return qs(unsorted.filter(_ < pivot)) ::: List(pivot) ::: qs(unsorted.filter(_ > pivot))
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/amm/src/test/resources/lineNumbers/MultipleCompilationUnitErrorMsgTest1.sc:
--------------------------------------------------------------------------------
1 | 1 + 1
2 | @
3 | object Thing{
4 | foo}
5 | }
--------------------------------------------------------------------------------
/amm/src/test/resources/lineNumbers/MultipleCompilationUnitErrorMsgTest2.sc:
--------------------------------------------------------------------------------
1 | object Thing{
2 | foo}
3 | }
4 | @
5 | 1 + 1
--------------------------------------------------------------------------------
/amm/src/test/resources/lineNumbers/RuntimeCompilationErrorLineNumberTest.sc:
--------------------------------------------------------------------------------
1 |
2 | //Code to check runtime error ilne numbers
3 |
4 | object foo{
5 |
6 | def f(i: Int): Double = 5/i
7 |
8 | }
9 |
10 | @
11 |
12 | println(foo.f(0))
13 |
--------------------------------------------------------------------------------
/amm/src/test/resources/lineNumbers/compilationErrorInClass.sc:
--------------------------------------------------------------------------------
1 |
2 | //adsfasdfasd
3 | println("Hello")
4 |
5 | //Comment before an empty line
6 |
7 | @
8 |
9 | class numPair(a: Int, b: Int){
10 |
11 | val num1 = a
12 | val num2 = b
13 | }
14 |
15 | def functionSwap(nums: numPair) = {
16 |
17 | val temp = nums.a ^ nums.b
18 | nums.a = nums.a ^ nums.b
19 | nums.b = nums.a ^ nums.b
20 | nums.a = nums.a ^ nums.b
21 |
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/amm/src/test/resources/lineNumbers/compilationErrorInFourthBlock.sc:
--------------------------------------------------------------------------------
1 |
2 |
3 | //Comment after empty lines
4 | @
5 | //Another Comment
6 |
7 | def quicksort(unsorted : List[Int]) : List[Int] = {
8 | if(unsorted.length <= 1) unsorted
9 | else{
10 | val pivot = unsorted.head
11 | quicksort(unsorted.filter(_ < pivot)):::List(pivot):::quicksort(unsorted.filter(_ > pivot))
12 | }
13 | }
14 |
15 | @
16 |
17 | println("OK")
18 |
19 | //One more comment
20 | //This one is long one!
21 | //check empty lines
22 |
23 | val x = 1
24 | println(x)
25 | //print the value of x
26 | @
27 |
28 | //lots of comments!!
29 |
30 | prinntl("Ammonite")
31 |
--------------------------------------------------------------------------------
/amm/src/test/resources/lineNumbers/compilationErrorInSecondBlock.sc:
--------------------------------------------------------------------------------
1 |
2 | //Another Comment
3 |
4 | def quicksort(unsorted : List[Int]) : List[Int] = {
5 | if(unsorted.length <= 1) unsorted
6 | else{
7 | val pivot = unsorted.head
8 | quicksort(unsorted.filter(_ < pivot)):::List(pivot):::quicksort(unsorted.filter(_ > pivot))
9 | }
10 | }
11 |
12 | @
13 |
14 | printnl("OK")
15 |
16 | //One more comment
17 | //This one is long one!
18 | //check empty lines
19 |
20 | val x = 1
21 | println(x)
22 | //print the value of x
23 | @
24 |
25 | //lots of comments!!
26 |
27 | prinntl("Ammonite")
28 |
--------------------------------------------------------------------------------
/amm/src/test/resources/lineNumbers/compilationErrorWithCommentsAtTop.sc:
--------------------------------------------------------------------------------
1 |
2 |
3 | //Comment after empty lines
4 | @
5 | //Another Comment
6 |
7 | def quicksort(unsorted : List[Int]) : List[Int] = {
8 | if(unsorted.length <= 1) unsorted
9 | else{
10 | val pivot = unsorted.head
11 | quicort(unsorted.filter(_ < pivot)):::List(pivot):::quicksort(unsorted.filter(_ > pivot))
12 | }
13 | }
14 |
15 | @
16 |
17 | println("OK")
18 |
19 | //One more comment
20 | //This one is long one!
21 | //check empty lines
22 |
23 | val x = 1
24 | println(x)
25 | //print the value of x
26 | @
27 |
28 | //lots of comments!!
29 |
30 | prinntl("Ammonite")
31 |
--------------------------------------------------------------------------------
/amm/src/test/resources/lineNumbers/sourceCodeMetadata.sc:
--------------------------------------------------------------------------------
1 | Console.err.println(sourcecode.FileName())
2 | Console.err.println(sourcecode.File())
3 | //Console.err.println(sourcecode.Line()) doesn't work in scala 3
--------------------------------------------------------------------------------
/amm/src/test/resources/loadable/hello/Hello.java:
--------------------------------------------------------------------------------
1 | package hello;
2 | public class Hello{
3 | public static String hello(){
4 | return "Hello!";
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/amm/src/test/resources/mains/ArgList.sc:
--------------------------------------------------------------------------------
1 | @main
2 | def main(args: String*): Unit = {
3 | args.foreach(arg => println(s"Argument: $arg"))
4 | }
--------------------------------------------------------------------------------
/amm/src/test/resources/mains/Args.sc:
--------------------------------------------------------------------------------
1 | // Args.sc
2 | val x = 1
3 |
4 | @main
5 | def main(i: Int, s: String, path: os.Path = os.pwd) = {
6 | s"Hello! ${s * i} ${path.last}."
7 | }
--------------------------------------------------------------------------------
/amm/src/test/resources/mains/Args2.sc:
--------------------------------------------------------------------------------
1 | // Args.sc
2 | val x = 1
3 |
4 | @main
5 | def main(i: Int, s: String, path: os.Path = os.pwd): Unit = {
6 | println(s"Hello! ${s * i} ${path.last}.")
7 | }
--------------------------------------------------------------------------------
/amm/src/test/resources/mains/CompilerCrash.sc:
--------------------------------------------------------------------------------
1 | trait Bar { super[Object].hashCode }
--------------------------------------------------------------------------------
/amm/src/test/resources/mains/Hello.sc:
--------------------------------------------------------------------------------
1 | println("Hello World")
--------------------------------------------------------------------------------
/amm/src/test/resources/mains/Main.sc:
--------------------------------------------------------------------------------
1 | val x = 1
2 |
3 | @main
4 | def main() = {
5 | println("Hello! " + x)
6 | }
--------------------------------------------------------------------------------
/amm/src/test/resources/mains/MultiMain.sc:
--------------------------------------------------------------------------------
1 | // MultiMain.sc
2 |
3 | val x = 1
4 |
5 | @main
6 | def mainA() = {
7 | println("Hello! " + x)
8 | }
9 |
10 | @main
11 | def functionB(i: Int, s: String, path: os.Path = os.pwd) = {
12 | println(s"Hello! ${s * i} ${path.relativeTo(os.pwd)}.")
13 | }
--------------------------------------------------------------------------------
/amm/src/test/resources/mains/MultiMainDoc.sc:
--------------------------------------------------------------------------------
1 | // MultiMainDoc.sc
2 |
3 | val x = 1
4 |
5 | @main
6 | def mainA() = {
7 | println("Hello! " + x)
8 | }
9 |
10 | @arg(doc = "This explains what the function does")
11 | @main
12 | def functionB(@arg(doc =
13 | "how many times to repeat the string to make " +
14 | "it very very long, more than it originally was")
15 | i: Int ,
16 | @arg(doc = "the string to repeat")
17 | s: String ,
18 | path: os.Path = os.pwd) = {
19 | println(s"Hello! ${s * i} ${path.relativeTo(os.pwd)}.")
20 | }
--------------------------------------------------------------------------------
/amm/src/test/resources/mains/Varargs.sc:
--------------------------------------------------------------------------------
1 | // Varargs.sc
2 | @main
3 | def main(i: Int, s: String, things: mainargs.Leftover[String]): Unit = {
4 | println(i)
5 | println(s)
6 | println(things.value.toList)
7 | }
--------------------------------------------------------------------------------
/amm/src/test/resources/scriptCompilerSettings/configureCompiler.sc:
--------------------------------------------------------------------------------
1 | val scalacOptions = List(
2 | "-Yrangepos:true"
3 | )
4 | interp.configureCompiler(_.settings.processArguments(scalacOptions, true))
5 |
6 | // Forcing the re-initialisation of the compiler.
7 | // compiler.useOffsetPosition should remain true because it's initialised
8 | // eagerly
9 | @
10 |
11 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scriptCompilerSettings/preConfigureCompiler.sc:
--------------------------------------------------------------------------------
1 | val scalacOptions = List(
2 | "-Yrangepos:true"
3 | )
4 | interp.preConfigureCompiler(_.processArguments(scalacOptions, true))
5 |
6 | // Forcing the re-initialisation of the compiler.
7 | // compiler.useOffsetPosition should now be false because the configuration of
8 | // the settings will have occurred before the new compiler become instantiated
9 | @
10 |
11 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scriptCompilerSettings/yRangepos.sc:
--------------------------------------------------------------------------------
1 | val scalacOptions = List(
2 | "-Yrangepos:true"
3 | )
4 | interp.preConfigureCompiler(_.processArguments(scalacOptions, true))
5 |
6 | @
7 |
8 | case class ABC(a : Int, b : String)
9 | println(ABC(1, "2"))
10 |
11 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scriptCompilerSettings/yRangeposError.sc:
--------------------------------------------------------------------------------
1 | val scalacOptions = List(
2 | "-Yrangepos:true"
3 | )
4 | interp.preConfigureCompiler(_.processArguments(scalacOptions, true))
5 |
6 | @
7 |
8 | case class ABC(a : Int, b : String)
9 | val a = ABC(1, 1) // compiler error, the test checks the line at which it throws
10 |
11 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scriptLevelCaching/QuickSort.sc:
--------------------------------------------------------------------------------
1 | def fib(n : Int): Int = {
2 | if (n == 0) 0
3 | else if (n == 1) 1
4 | else fib(n-1) + fib(n-2)
5 | }
6 |
7 | def quicksort(unsorted : List[Int]): List[Int] = {
8 | if(unsorted.length <= 1) unsorted
9 | else{
10 | val pivot = unsorted.head
11 | quicksort(unsorted.filter(_ < pivot)):::List(pivot):::quicksort(unsorted.filter(_ > pivot))
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scriptLevelCaching/fileToBeImported.sc:
--------------------------------------------------------------------------------
1 | def listScalaFiles = os.list(os.pwd).filter(_.last.endsWith(".sc"))
--------------------------------------------------------------------------------
/amm/src/test/resources/scriptLevelCaching/ivyCacheTest.sc:
--------------------------------------------------------------------------------
1 | import $ivy.`com.lihaoyi::scalatags:0.7.0 compat`, scalatags.Text.all._
2 |
3 | val rendered = div("Moo").render
4 |
5 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scriptLevelCaching/ivyCachedResourceTest.sc:
--------------------------------------------------------------------------------
1 | import $ivy.`io.kamon::kamon-core:2.1.0 compat`
2 | os.read(os.resource/"reference.conf")
3 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scriptLevelCaching/runTimeExceptions.sc:
--------------------------------------------------------------------------------
1 | println(5/os.read(os.pwd/"amm"/"target"/"test"/"resources"/"scriptLevelCaching"/"num.value").trim.toInt)
2 | os.remove.all(os.pwd/"amm"/"target"/"test"/"resources"/"scriptLevelCaching"/"num.value")
3 | os.write(os.pwd/"amm"/"target"/"test"/"resources"/"scriptLevelCaching"/"num.value", "0")
4 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scriptLevelCaching/scriptOne.sc:
--------------------------------------------------------------------------------
1 | // Test Code
2 | object test{
3 |
4 | val x = interp
5 | }
6 | println(test.x)
7 |
8 | @
9 |
10 | def f = "Hello"
11 | println(System.lineSeparator*2 + "It has executed")
12 |
13 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scriptLevelCaching/scriptToBeLoaded.sc:
--------------------------------------------------------------------------------
1 |
2 | println(interp)
3 | println("First Block")
4 |
5 | @
6 |
7 | println(interp)
8 | println("Second Block")
9 |
10 | @
11 |
12 | println(interp)
13 | println("Third Block")
14 |
15 | @
16 |
17 | println(interp)
18 | println("Fourth Block")
19 |
20 | val x = interp
21 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scriptLevelCaching/scriptTwo.sc:
--------------------------------------------------------------------------------
1 |
2 | println("Test Script")
3 | println(interp)
4 |
5 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scriptLevelCaching/testFileImport.sc:
--------------------------------------------------------------------------------
1 | import $file.fileToBeImported
2 |
3 | @
4 |
5 | println("Hope It works!!")
6 |
7 | @
8 | println(fileToBeImported.listScalaFiles)
9 | println("Yup!! It worked :) ")
10 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scriptLevelCaching/testLoadModule.sc:
--------------------------------------------------------------------------------
1 | // Test case to check whether it can load modules from cache and use the imports successfully
2 |
3 | println("Script starts!!")
4 | val scriptDir = os.pwd/"amm"/"src"/"test"/"resources"/"scriptLevelCaching"
5 | interp.load.module(scriptDir/"scriptToBeLoaded.sc")
6 |
7 | @
8 |
9 | println(x)
10 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/Annotation.sc:
--------------------------------------------------------------------------------
1 | import annotation.tailrec
2 | val list= List(1,2,3,4)
3 | @tailrec def product(acc: Int, l: List[Int]): Int = {
4 | if(l.isEmpty) acc
5 | else product(acc*l.head,l.tail)
6 | }
7 | val res = product(1,list)
8 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/BlockSepSyntax.sc:
--------------------------------------------------------------------------------
1 | "block1"
2 | @
3 | "block2"
4 | @
5 | "block3"
6 | @ "block4"
7 | @ "block5"
8 | val res = 24
9 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/CompilationError.sc:
--------------------------------------------------------------------------------
1 | nonexistentSymbol
2 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/Encapsulation.sc:
--------------------------------------------------------------------------------
1 | asd
2 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/LimitImports.sc:
--------------------------------------------------------------------------------
1 | val res = 1
2 | @
3 | val asd = 1
4 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/LoadIvy.sc:
--------------------------------------------------------------------------------
1 | interp.load.ivy("com.lihaoyi" %% "scalatags" % "0.12.0")
2 | @
3 | import scalatags.Text.all._
4 | val res = a("omg", href:="www.google.com").render
5 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/MultiBlockError.sc:
--------------------------------------------------------------------------------
1 | val res1 = 1
2 | @
3 | thisWillFail
4 | @
5 | val res2 = 1
6 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/MultilineSheBang.sc:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | exec /usr/bin/amm "$0" "$@"
3 | !#
4 |
5 | val res = 42
6 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/NestedScripts.sc:
--------------------------------------------------------------------------------
1 | println("script start")
2 | interp.load.module(os.pwd/"amm"/"src"/"test"/"resources"/"scripts"/"LimitImports.sc")
3 | @
4 | println("module should be loaded")
5 | @
6 | val asd2 = asd
7 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/OneBlock.sc:
--------------------------------------------------------------------------------
1 | 1
2 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/PreserveImports.sc:
--------------------------------------------------------------------------------
1 | import scala.util.{Either, Left}
2 | @
3 | val res = Left("asd")
4 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/Resolvers.sc:
--------------------------------------------------------------------------------
1 | interp.repositories() ++= Seq(coursierapi.IvyRepository.of(
2 | "https://ambiata-oss.s3-ap-southeast-2.amazonaws.com/[defaultPattern]"
3 | ))
4 |
5 | @
6 |
7 | import $ivy.`com.ambiata::mundane:1.2.1-20141230225616-50fc792`
8 | import com.ambiata.mundane._
9 |
10 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/ResolversFail.sc:
--------------------------------------------------------------------------------
1 | interp.repositories() ++= Seq(coursierapi.IvyRepository.of(
2 | "https://ambiata-oss.s3-ap-southeast-2.amazonaws.com/[defaultPattern]"
3 | ))
4 |
5 | import $ivy.`com.ambiata::mundane:1.2.1-20141230225616-50fc792`
6 | import com.ambiata.mundane._
7 |
8 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/ResolversStatic.sc:
--------------------------------------------------------------------------------
1 | import $repo.`https://jitpack.io`
2 | import $ivy.`com.github.jupyter:jvm-repr:0.4.0`
3 | import jupyter._
4 |
5 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/ScriptDontUnwrap.sc:
--------------------------------------------------------------------------------
1 | {{
2 | val wrappedValue = 1
3 | val y = 2
4 | }}
5 | def foo = "foo def"
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/SheBang.sc:
--------------------------------------------------------------------------------
1 | #!/usr/bin/amm
2 | val res = 42
3 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/SyntaxError.sc:
--------------------------------------------------------------------------------
1 | #syntaxError
2 | val res = 1
3 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/TagBase.sc:
--------------------------------------------------------------------------------
1 | def tagBase = "asd"
2 | @
3 | tagBase
4 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/TagPrevCommand.sc:
--------------------------------------------------------------------------------
1 | def tagBase = "a"
2 | @
3 | tagBase
4 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/ThreeBlocks.sc:
--------------------------------------------------------------------------------
1 | 1
2 | @
3 | 2
4 | @
5 | 3
6 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/TwoBlocks.sc:
--------------------------------------------------------------------------------
1 | 1
2 | @
3 | 2
4 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/cachedCompilerInit.sc:
--------------------------------------------------------------------------------
1 | // Show compiler warnings
2 | interp.configureCompiler(c => println(c))
3 |
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/caching/scalatagsPredef.sc:
--------------------------------------------------------------------------------
1 | import $ivy.`com.lihaoyi::scalatags:0.7.0`, scalatags.Text.all._
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/caching/scalatagsScript.sc:
--------------------------------------------------------------------------------
1 | println(div("<('.'<)").render)
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/loadIvyAdvanced.sc:
--------------------------------------------------------------------------------
1 | import coursierapi.Dependency
2 |
3 | interp.load.ivy(
4 | // Using SBT-style syntax
5 | "xom" % "xom" % "1.1",
6 | // Directly using coursier API. Can pass in exclusions,
7 | // attributes, configurations, classifiers, etc.
8 | Dependency.of("net.sf.json-lib", "json-lib", "2.4")
9 | .withClassifier("jdk15")
10 | )
11 |
12 | @
13 |
14 | // Code using the dependencies
15 | val serializer = new net.sf.json.xml.XMLSerializer
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/predefWithLoad/Loaded.sc:
--------------------------------------------------------------------------------
1 | val loadedDefinedValue = 1337
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/predefWithLoad/PredefLoadExec.sc:
--------------------------------------------------------------------------------
1 | repl.load.exec(
2 | os.pwd/"amm"/"src"/"test"/"resources"/"scripts"/"predefWithLoad"/"Loaded.sc"
3 | )
4 |
5 | @
6 |
7 | val predefDefinedValue = loadedDefinedValue
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/predefWithLoad/PredefLoadModule.sc:
--------------------------------------------------------------------------------
1 | interp.load.module(
2 | os.pwd/"amm"/"src"/"test"/"resources"/"scripts"/"predefWithLoad"/"Loaded.sc"
3 | )
4 |
5 | @
6 | val predefDefinedValue = loadedDefinedValue
--------------------------------------------------------------------------------
/amm/src/test/resources/scripts/predefWithLoad/PredefMagicImport.sc:
--------------------------------------------------------------------------------
1 | import $file.Loaded
2 |
3 | val predefDefinedValue = Loaded.loadedDefinedValue
--------------------------------------------------------------------------------
/amm/src/test/resources/testdata/Resume.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/amm/src/test/resources/testdata/Resume.docx
--------------------------------------------------------------------------------
/amm/src/test/resources/testdata/images/GettingStarted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/amm/src/test/resources/testdata/images/GettingStarted.png
--------------------------------------------------------------------------------
/amm/src/test/resources/testdata/images/Highlighting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/amm/src/test/resources/testdata/images/Highlighting.png
--------------------------------------------------------------------------------
/amm/src/test/resources/testdata/images/SystemShell.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/amm/src/test/resources/testdata/images/SystemShell.png
--------------------------------------------------------------------------------
/amm/src/test/scala/ammonite/interp/CompilerSettingsTests.scala:
--------------------------------------------------------------------------------
1 | package ammonite.interp
2 |
3 | import ammonite.TestUtils._
4 |
5 | import ammonite.compiler.test.CompilerTestExtensions._
6 | import ammonite.runtime.Storage
7 | import ammonite.main.Scripts
8 | import utest._
9 |
10 | object CompilerSettingsTests extends TestSuite {
11 | val tests = Tests {
12 | println("CompilerSettingsTests")
13 |
14 | val scriptPath = os.pwd / "amm" / "src" / "test" / "resources" / "scriptCompilerSettings"
15 |
16 | test("configureYrangepos") {
17 |
18 | // In this test, the script sets -Yrangepos to true using "configureCompiler",
19 | // which is called AFTER the compiler instantiates. As useOffsetPositions
20 | // is set eagerly during the compiler instantiation as !Yrangepos, its
21 | // value remains "true".
22 | if (scala2_12) {
23 | val storage = Storage.InMemory()
24 | val interp = createTestInterp(storage)
25 | Scripts.runScript(os.pwd, scriptPath / "configureCompiler.sc", interp)
26 |
27 | assert(
28 | interp
29 | .compilerManager
30 | .asInstanceOf[ammonite.compiler.CompilerLifecycleManager]
31 | .compiler
32 | .compiler
33 | .useOffsetPositions
34 | )
35 | } else "Disabled"
36 | }
37 |
38 | test("preConfigureYrangepos") {
39 | // In this test, the script sets -Yrangepos using "preConfigureCompiler",
40 | // which is called BEFORE the compiler instantiates, resulting in
41 | // useOffsetPositions initializing as false, as expected
42 | if (scala2) {
43 | val storage = Storage.InMemory()
44 | val interp = createTestInterp(
45 | storage,
46 | predefImports = Interpreter.predefImports
47 | )
48 | Scripts.runScript(os.pwd, scriptPath / "preConfigureCompiler.sc", interp)
49 |
50 | assert(
51 | !interp
52 | .compilerManager
53 | .asInstanceOf[ammonite.compiler.CompilerLifecycleManager]
54 | .compiler
55 | .compiler
56 | .useOffsetPositions
57 | )
58 | } else "Disabled in Scala 3"
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/amm/src/test/scala/ammonite/interp/YRangeposTests.scala:
--------------------------------------------------------------------------------
1 | package ammonite.interp
2 |
3 | import ammonite.TestUtils._
4 |
5 | import ammonite.runtime.Storage
6 | import ammonite.main._
7 | import utest._
8 |
9 | object YRangeposTests extends TestSuite {
10 | val tests = Tests {
11 | println("YRangeposTests")
12 |
13 | def checkErrorMessage(file: os.Path, expected: String): Unit = {
14 | val e = new InProcessMainMethodRunner(file, Nil, Nil)
15 |
16 | assert(e.err.contains(expected))
17 | }
18 |
19 | val scriptFolderPath =
20 | os.pwd / "amm" / "src" / "test" / "resources" / "scriptCompilerSettings"
21 |
22 | def simpleTest() = {
23 | // This tests shows that enabling Yrangepos does not mess with ammonite's
24 | // behaviour. The compiler not crashing is the test itself.
25 | val storage = Storage.InMemory()
26 | val interp = createTestInterp(
27 | storage,
28 | predefImports = Interpreter.predefImports
29 | )
30 | val res = Scripts.runScript(os.pwd, scriptFolderPath / "yRangepos.sc", interp)
31 | assert(res.isSuccess)
32 | }
33 | test("Yrangepos") {
34 | if (scala2) simpleTest()
35 | else "Disabled in Scala 3"
36 | }
37 |
38 | def errorTest() = {
39 | // This tests shows that enabling Yrangepos does not mess with ammonite's
40 | // behaviour, by checking that the line at which the error is found matches
41 | // the expected one in the file
42 | val expectedErrorMessage = "yRangeposError.sc:9: type mismatch;"
43 | checkErrorMessage(
44 | InProcessMainMethodRunner.base / "scriptCompilerSettings" / "yRangeposError.sc",
45 | expectedErrorMessage
46 | )
47 | }
48 | test("YrangeposError") {
49 | if (scala2) errorTest()
50 | else "Disabled in Scala 3"
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/amm/src/test/scala/ammonite/interp/script/TestBuildClient.scala:
--------------------------------------------------------------------------------
1 | package ammonite.interp.script
2 |
3 | import java.util.concurrent.{ConcurrentHashMap, ConcurrentLinkedQueue}
4 |
5 | import ch.epfl.scala.bsp4j.{Diagnostic => BDiagnostic, _}
6 |
7 | import scala.collection.JavaConverters._
8 |
9 | class TestBuildClient extends BuildClient {
10 |
11 | import TestBuildClient._
12 |
13 | private val diagnostics0 =
14 | new ConcurrentHashMap[
15 | (BuildTargetIdentifier, TextDocumentIdentifier),
16 | Seq[BDiagnostic]
17 | ]
18 |
19 | private val taskEvents0 = new ConcurrentLinkedQueue[TaskEvent]
20 | private val didChangeNotifications0 = new ConcurrentLinkedQueue[BuildTargetEvent]
21 |
22 | def diagnostics(
23 | targetId: BuildTargetIdentifier,
24 | document: TextDocumentIdentifier
25 | ): Option[Seq[BDiagnostic]] =
26 | Option(diagnostics0.get((targetId, document)))
27 |
28 | def taskEvents(): Seq[TaskEvent] =
29 | taskEvents0.iterator().asScala.toVector
30 | def didChangeNotifications(): Seq[BuildTargetEvent] =
31 | didChangeNotifications0.iterator().asScala.toVector
32 | def clearDidChangeNotifications(): Unit =
33 | didChangeNotifications0.clear()
34 |
35 | def onBuildPublishDiagnostics(params: PublishDiagnosticsParams): Unit =
36 | diagnostics0.put(
37 | (params.getBuildTarget, params.getTextDocument),
38 | params.getDiagnostics.asScala.toVector
39 | )
40 |
41 | def onBuildTaskStart(params: TaskStartParams): Unit =
42 | taskEvents0.add(TaskEvent.Start(params))
43 | def onBuildTaskProgress(params: TaskProgressParams): Unit =
44 | taskEvents0.add(TaskEvent.Progress(params))
45 | def onBuildTaskFinish(params: TaskFinishParams): Unit =
46 | taskEvents0.add(TaskEvent.Finish(params))
47 |
48 | def onBuildTargetDidChange(params: DidChangeBuildTarget): Unit =
49 | didChangeNotifications0.addAll(params.getChanges)
50 |
51 | def onBuildLogMessage(params: LogMessageParams): Unit = ()
52 | def onBuildShowMessage(params: ShowMessageParams): Unit = ()
53 | }
54 |
55 | object TestBuildClient {
56 |
57 | sealed abstract class TaskEvent extends Product with Serializable
58 | object TaskEvent {
59 | final case class Start(params: TaskStartParams) extends TaskEvent
60 | final case class Progress(params: TaskProgressParams) extends TaskEvent
61 | final case class Finish(params: TaskFinishParams) extends TaskEvent
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/amm/src/test/scala/ammonite/main/InProcessMainMethodRunner.scala:
--------------------------------------------------------------------------------
1 | package ammonite.main
2 |
3 | import java.io.{ByteArrayInputStream, ByteArrayOutputStream}
4 |
5 | object InProcessMainMethodRunner {
6 | val base = os.pwd / "amm" / "src" / "test" / "resources"
7 | }
8 |
9 | /**
10 | * An in-memory mock subprocess; exposes the same API as a subprocess call:
11 | * stdin, stdout, stderr, and command-line arguments as a Array[String]. But
12 | * runs the computation in memory, which is often a lot faster.
13 | *
14 | * Attempts to capture stdout and stderr from the current thread via
15 | * the `Console.with*` methods. This doesn't always work, e.g. it doesn't
16 | * capture Java `System.*.println` methods, and overall this doesn't guarantee
17 | * JVM-level isolation between tests. But it works well enough for
18 | * our unit tests.
19 | */
20 | class InProcessMainMethodRunner(p: os.Path, preArgs: List[String], args: Seq[String]) {
21 |
22 | val in = new ByteArrayInputStream(Array.empty[Byte])
23 | val err0 = new ByteArrayOutputStream()
24 | val out0 = new ByteArrayOutputStream()
25 | val path = p
26 |
27 | val success = Console.withIn(in) {
28 | Console.withErr(err0) {
29 | Console.withOut(out0) {
30 | ammonite.AmmoniteMain.main0(
31 | List("--home", os.temp.dir().toString) ++
32 | preArgs ++
33 | Seq(path.toString) ++
34 | args.toList,
35 | in,
36 | out0,
37 | err0
38 | )
39 | }
40 | }
41 | }
42 |
43 | val out = new String(out0.toByteArray)
44 | val err = new String(err0.toByteArray)
45 | override def toString = {
46 | s"Executor($out, $err)"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/amm/src/test/scala/ammonite/main/InProcessMainMethodRunnerRawArgs.scala:
--------------------------------------------------------------------------------
1 | package ammonite.main
2 |
3 | import java.io.{ByteArrayInputStream, ByteArrayOutputStream}
4 |
5 | /**
6 | * Same purpose as [[InProcessMainMethodRunner]] but it accepts the arguments
7 | * as they are. This is somewhat analogous to [[ammonite.Main.main0]] but it
8 | * attempts to capture the output and error streams like
9 | * [[InProcessMainMethodRunner]] without having to append any prefix arguments
10 | * such as the current path.
11 | *
12 | * @see [[InProcessMainMethodRunner]].
13 | */
14 | class InProcessMainMethodRunnerRawArgs(args: Seq[String]) {
15 |
16 | val in = new ByteArrayInputStream(Array.empty[Byte])
17 | val err0 = new ByteArrayOutputStream()
18 | val out0 = new ByteArrayOutputStream()
19 |
20 | val success = Console.withIn(in) {
21 | Console.withErr(err0) {
22 | Console.withOut(out0) {
23 | ammonite.AmmoniteMain.main0(args.toList, in, out0, err0)
24 | }
25 | }
26 | }
27 |
28 | val out = new String(out0.toByteArray)
29 | val err = new String(err0.toByteArray)
30 |
31 | override def toString =
32 | s"Executor($out, $err)"
33 | }
34 |
--------------------------------------------------------------------------------
/amm/src/test/scala/ammonite/readme.md:
--------------------------------------------------------------------------------
1 | The tests in this folder are roughly broken down into:
2 |
3 | - `unit` tests: small, self-contained functions or utilities
4 |
5 | - `interp` tests: instantiating an `Interpreter` object, then poking at its
6 | internals and running its functionality
7 |
8 | - `session` tests: simulating a REPL session, running multiple commands one
9 | after another and checking that the output matches what you'd expect
10 |
11 | - `main` tests: tests running Ammonite's `main0` method, which is basically
12 | equivalent to spawning a new Ammonite process, except the logic is run
13 | in-process with mock `stdin`/`stdout`/`stderr` streams.
14 |
15 | These are listed in increasing levels of "integration"-ness; anything more
16 | integrated than this would be in the separate integration/ test subproject,
17 | which literally spins up a separate Ammonite process from the jar file and
18 | makes sure everything works end-to-end
--------------------------------------------------------------------------------
/amm/util/src/main/scala/ammonite/util/Frame.scala:
--------------------------------------------------------------------------------
1 | package ammonite.util
2 |
3 | import java.net.URL
4 |
5 | trait Frame {
6 | def classloader: ReplClassLoader
7 | def pluginClassloader: ReplClassLoader
8 |
9 | def classpath: Seq[URL]
10 | def version: Int
11 |
12 | /** Adds a [[Frame.Hook]] to be called every time JARs are added to the class path */
13 | def addHook(hook: Frame.Hook): Unit
14 | }
15 |
16 | object Frame {
17 |
18 | /** A hook that can be called every time JARs are added to the class path */
19 | trait Hook {
20 |
21 | /** Called when new JARs are added to the class path */
22 | def addClasspath(additional: Seq[java.net.URL]): Unit
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/amm/util/src/main/scala/ammonite/util/Position.scala:
--------------------------------------------------------------------------------
1 | package ammonite.util
2 |
3 | final case class Position(line: Int, char: Int)
4 |
--------------------------------------------------------------------------------
/amm/util/src/main/scala/ammonite/util/ReplClassLoader.scala:
--------------------------------------------------------------------------------
1 | package ammonite.util
2 |
3 | import java.net.{URL, URLClassLoader}
4 |
5 | abstract class ReplClassLoader(urls: Array[URL], parent: ClassLoader)
6 | extends URLClassLoader(urls, parent) {
7 | def inMemoryClasses: Map[String, Array[Byte]]
8 | }
9 |
--------------------------------------------------------------------------------
/amm/util/src/main/scala/ammonite/util/WhiteListClassLoader.scala:
--------------------------------------------------------------------------------
1 | package ammonite.util
2 |
3 | import java.net.URLClassLoader
4 |
5 | class WhiteListClassLoader(whitelist: Set[Seq[String]], parent: ClassLoader)
6 | extends URLClassLoader(Array(), parent) {
7 | override def loadClass(name: String, resolve: Boolean) = {
8 | val tokens = name.split('.')
9 | if (Util.lookupWhiteList(whitelist, tokens.init ++ Seq(tokens.last + ".class"))) {
10 | super.loadClass(name, resolve)
11 | } else {
12 | throw new ClassNotFoundException(name)
13 | }
14 |
15 | }
16 | override def getResource(name: String) = {
17 | if (Util.lookupWhiteList(whitelist, name.split('/'))) super.getResource(name)
18 | else null
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/build.sbt:
--------------------------------------------------------------------------------
1 | import scalatex.ScalatexReadme
2 |
3 | lazy val readme = ScalatexReadme(
4 | projectId = "readme",
5 | wd = file(""),
6 | url = "https://github.com/com-lihaoyi/Ammonite/tree/main",
7 | source = "Index"
8 | ).settings(
9 | scalaVersion := "2.12.18",
10 | libraryDependencies += "com.lihaoyi" %% "fansi" % "0.2.14",
11 | libraryDependencies += "com.lihaoyi" %% "os-lib" % "0.7.8",
12 | Test / envVars := Map(
13 | "AMMONITE_ASSEMBLY" -> sys.env("AMMONITE_ASSEMBLY"),
14 | "AMMONITE_SHELL" -> sys.env("AMMONITE_SHELL")
15 | ),
16 | fork := true,
17 | Compile / run / baseDirectory := (Compile / run / baseDirectory).value / "..",
18 | (Compile / unmanagedSources) += file(sys.env("CONSTANTS_FILE"))
19 | )
20 |
--------------------------------------------------------------------------------
/ci/deploy_master_docs.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -euxv
3 |
4 | # Mangle ssh-key stuff to work with the deploy_key written by python
5 | eval "$(ssh-agent -s)"
6 | chmod 600 deploy_key
7 | ssh-add deploy_key
8 | rm deploy_key
9 |
10 | # Set up git so we can actually do things with it
11 | git config --global user.email "haoyi.sg+travis@gmail.com"
12 | git config --global user.name "Ammonite Travis Bot"
13 | git fetch origin gh-pages:gh-pages
14 |
15 | # Do all the git-foo to push the readme to the relevant gh-pages folder
16 | git checkout -f gh-pages
17 | cp -r readme/target/scalatex/* .
18 | git add -A
19 | git commit -am $(git rev-parse HEAD)
20 | git push git@github.com:$GITHUB_REPOSITORY.git gh-pages:gh-pages
21 |
--------------------------------------------------------------------------------
/ci/package.mill:
--------------------------------------------------------------------------------
1 | package build.ci
2 |
--------------------------------------------------------------------------------
/ci/upload.mill:
--------------------------------------------------------------------------------
1 | package build.ci
2 |
3 | def apply(
4 | uploadedFile: os.Path,
5 | tagName: String,
6 | uploadName: String,
7 | authKey: String,
8 | ghOrg: String,
9 | ghRepo: String
10 | ): String = {
11 | println("upload.apply")
12 | println(uploadedFile)
13 | println(tagName)
14 | println(uploadName)
15 | println(authKey)
16 | println(ghOrg)
17 | println(ghRepo)
18 | val body = requests.get(
19 | s"https://api.github.com/repos/${ghOrg}/${ghRepo}/releases/tags/" + tagName,
20 | headers = Seq("Authorization" -> s"token $authKey")
21 | )
22 |
23 | val parsed = ujson.read(body.text)
24 |
25 | println(body)
26 |
27 | val snapshotReleaseId = parsed("id").num.toInt
28 |
29 | val uploadUrl =
30 | s"https://uploads.github.com/repos/${ghOrg}/${ghRepo}/releases/" +
31 | s"$snapshotReleaseId/assets?name=$uploadName"
32 |
33 | val res = requests.post(
34 | uploadUrl,
35 | headers = Seq(
36 | "Content-Type" -> "application/octet-stream",
37 | "Authorization" -> s"token $authKey"
38 | ),
39 | connectTimeout = 5000,
40 | readTimeout = 60000,
41 | data = os.read.bytes(uploadedFile)
42 | ).text
43 |
44 | println(res)
45 |
46 | val longUrl = ujson.read(res)("browser_download_url").str
47 |
48 | longUrl
49 | }
50 |
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/Complex.sc:
--------------------------------------------------------------------------------
1 | import $ivy.`org.spire-math::spire:0.13.0`
2 |
3 | import spire.implicits._
4 | import spire.math._
5 |
6 | println("Spire Interval " + Interval(0, 10))
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/Failure.sc:
--------------------------------------------------------------------------------
1 | println(x)
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/Hello.sc:
--------------------------------------------------------------------------------
1 | println("Hello World")
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/HttpApi.sc:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env amm
2 | // HttpApi.sc
3 |
4 | import $ivy.{
5 | `com.lihaoyi::requests:0.2.0 compat`,
6 | `com.lihaoyi::ujson:0.7.5 compat`
7 | }
8 |
9 | lazy val jsonPlaceHolderBase =
10 | Option(System.getenv("JSONPLACEHOLDER")).getOrElse {
11 | "http://jsonplaceholder.typicode.com"
12 | }
13 |
14 | @main
15 | def addPost(title: String, body: String) = {
16 | ujson.read(
17 | requests.post(
18 | s"$jsonPlaceHolderBase/posts",
19 | data = Seq(
20 | "title" -> title,
21 | "body" -> body,
22 | "userId" -> "1"
23 | )
24 | ).text()
25 | ).obj.get("id").map(_.num.toInt).getOrElse(0)
26 |
27 |
28 | }
29 |
30 | @main
31 | def comments(postId: Int) = {
32 | val json = ujson.read(
33 | requests
34 | .get(s"$jsonPlaceHolderBase/comments?postId=$postId")
35 | .text()
36 | )
37 | val names = for{
38 | item <- json.arr
39 | name <- item.obj.get("name")
40 | } yield name.str
41 | names.mkString(",")
42 | }
43 |
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/MultiMain.sc:
--------------------------------------------------------------------------------
1 | // MultiMain.sc
2 |
3 | val x = 1
4 |
5 | @main
6 | def mainA() = {
7 | println("Hello! " + x)
8 | }
9 |
10 | @main
11 | def functionB(i: Int, s: String, path: os.Path = os.pwd) = {
12 | println(s"Hello! ${s * i} ${path.relativeTo(os.pwd)}.")
13 | }
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/PlayFramework.sc:
--------------------------------------------------------------------------------
1 | /**
2 | * Single-file play framework application!
3 | */
4 | import $ivy.{
5 | `com.typesafe.play::play:2.5.0`,
6 | `com.typesafe.play::play-netty-server:2.5.0`,
7 | `com.lihaoyi::requests:0.2.0`
8 | }
9 |
10 | import play.core.server._, play.api.routing.sird._, play.api.mvc._
11 | val server = NettyServer.fromRouter(new ServerConfig(
12 | rootDir = new java.io.File("."),
13 | port = Some(19000), sslPort = None,
14 | address = "0.0.0.0", mode = play.api.Mode.Dev,
15 | properties = System.getProperties,
16 | configuration = play.api.Configuration(
17 | "play.server.netty" -> Map(
18 | "maxInitialLineLength" -> 4096,
19 | "maxHeaderSize" -> 8192,
20 | "maxChunkSize" -> 8192,
21 | "log.wire" -> false,
22 | "eventLoopThreads" -> 0,
23 | "transport" -> "jdk",
24 | "option.child" -> Map()
25 | )
26 | )
27 | )) {
28 | case GET(p"/hello/$to") => Action { Results.Ok(s"Hello $to") }
29 | }
30 | try {
31 | println(requests.get("http://localhost:19000/hello/bar").text())
32 | } finally{
33 | server.stop()
34 | }
35 |
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/Print.sc:
--------------------------------------------------------------------------------
1 | println(os.list(os.pwd/"out"))
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/QuickSort.sc:
--------------------------------------------------------------------------------
1 | def fib(n : Int) : Int = {
2 | if (n == 0) 0
3 | else if (n == 1) 1
4 | else fib(n-1) + fib(n-2)
5 | }
6 |
7 | def quicksort(unsorted : List[Int]) : List[Int] = {
8 | if(unsorted.length <= 1) unsorted
9 | else{
10 | val pivot = unsorted.head
11 | quicksort(unsorted.filter(_ < pivot)):::List(pivot):::quicksort(unsorted.filter(_ > pivot))
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/Resources.sc:
--------------------------------------------------------------------------------
1 | interp.load.ivy("org.apache.jackrabbit" % "oak-core" % "1.3.16")
2 | @
3 | val path = os.resource/"org"/"apache"/"jackrabbit"/"oak"/"plugins"/"blob"/"blobstore.properties"
4 | println(os.read(path).length) // Should work
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/SourceDownload.sc:
--------------------------------------------------------------------------------
1 | import $ivy.`com.lihaoyi::scalatags:0.7.0 compat`
2 |
3 | val loc = source.load(scalatags.Text)
4 | val snip = Predef.augmentString(loc.fileContent)
5 | .lines
6 | .slice(loc.lineNum-15, loc.lineNum+15)
7 | .mkString("\n")
8 |
9 | assert(snip.contains("object Text"))
10 | assert(snip.contains("extends generic.Bundle"))
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/Spark.sc:
--------------------------------------------------------------------------------
1 |
2 | import $ivy.{
3 | `org.apache.hadoop:hadoop-common:2.5.1`,
4 | `org.apache.hadoop:hadoop-auth:2.5.1`,
5 | `commons-configuration:commons-configuration:1.9`,
6 | `commons-collections:commons-collections:3.2.1`,
7 | `commons-lang:commons-lang:2.6`,
8 | `org.apache.spark::spark-core:2.1.1`,
9 | `org.apache.spark::spark-repl:2.1.1`,
10 | `org.apache.spark::spark-network-common:2.1.1`,
11 | `org.apache.spark::spark-network-shuffle:2.1.1`,
12 | `org.eclipse.jetty.aggregate:jetty-all-server:8.1.14.v20131031`
13 | }
14 |
15 | import java.net.InetAddress
16 | import org.eclipse.jetty.server.Server
17 | import org.eclipse.jetty.server.bio.SocketConnector
18 | import org.eclipse.jetty.server.handler.{DefaultHandler, HandlerList, ResourceHandler}
19 | import org.eclipse.jetty.util.thread.QueuedThreadPool
20 | import org.eclipse.jetty.util.resource.Resource
21 | import org.apache.spark.{SparkConf, SparkContext}
22 |
23 |
24 | val server = {
25 | val server = new Server()
26 |
27 | val connector = new SocketConnector
28 | connector.setMaxIdleTime(60 * 1000)
29 | connector.setSoLingerTime(-1)
30 | connector.setPort(0)
31 | server.addConnector(connector)
32 |
33 | val threadPool = new QueuedThreadPool
34 | threadPool.setDaemon(true)
35 | server.setThreadPool(threadPool)
36 |
37 | val resHandler = new ResourceHandler
38 | resHandler.setBaseResource(Resource.newClassPathResource("/"))
39 |
40 | val handlerList = new HandlerList
41 | handlerList.setHandlers(Array(resHandler, new DefaultHandler))
42 |
43 | server.setHandler(handlerList)
44 |
45 | server.start()
46 |
47 | server
48 | }
49 |
50 | val port = server.getConnectors()(0).getLocalPort
51 |
52 | println("Starting spark test")
53 |
54 | val conf = new SparkConf()
55 | .setAppName("test")
56 | .setMaster("local[*]")
57 | .set(
58 | "spark.repl.class.uri",
59 | s"http://${InetAddress.getLocalHost().getHostName()}:$port"
60 | )
61 | // To allow retries for this test.
62 | .set("spark.driver.allowMultipleContexts", "true")
63 | val sc = new SparkContext(conf)
64 | val result = sc.parallelize(1 to 5).map(_ * 10).collect
65 |
66 | server.stop()
67 | println(s"Spark result: ${result.toList}")
68 | assert(result.toList == List(10, 20, 30, 40, 50))
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/Spark2.json:
--------------------------------------------------------------------------------
1 | {"hello": 1},
2 | {"hello": 2},
3 |
4 | {"hello": 3}
5 |
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/Spark2.sc:
--------------------------------------------------------------------------------
1 | import $ivy.{
2 | `org.apache.spark::spark-core:2.1.0`,
3 | `org.apache.spark::spark-sql:2.1.0`
4 | }
5 | import org.apache.spark.sql.SparkSession
6 |
7 | val spark = SparkSession.builder.master("local[*]").appName("bxm").getOrCreate
8 |
9 | val df = spark.read.json(
10 | "integration/src/test/resources/ammonite/integration/basic/Spark2.json"
11 | )
12 |
13 | df.foreachPartition { records =>
14 | records.foreach {
15 | record => println("fake db write")
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/Varargs.sc:
--------------------------------------------------------------------------------
1 | // Varargs.sc
2 | @main
3 | def main(i: Int, s: String, things: String*): Unit = {
4 | println(i)
5 | println(s)
6 | println(things)
7 | }
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/http-api-data.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "body": "eum laborum quidem omnis facere harum ducimus dolores quaerat\ncorporis quidem aliquid\nquod aut aut at dolorum aspernatur reiciendis\nexercitationem quasi consectetur asperiores vero blanditiis dolor",
4 | "email": "Jenifer_Lowe@reuben.ca",
5 | "id": 196,
6 | "name": "totam vel saepe aut qui velit quis",
7 | "postId": 40
8 | },
9 | {
10 | "body": "fugit ut laborum provident\nquos provident voluptatibus quam non\nsed accusantium explicabo dolore quia distinctio voluptatibus et\nconsequatur eos qui iure minus eaque praesentium",
11 | "email": "Cecelia_Nitzsche@marty.com",
12 | "id": 197,
13 | "name": "non perspiciatis omnis facere rem",
14 | "postId": 40
15 | },
16 | {
17 | "body": "est veritatis mollitia atque quas et sint et dolor\net ut beatae aut\nmagni corporis dolores voluptatibus optio molestiae enim minus est\nreiciendis facere voluptate rem officia doloribus ut",
18 | "email": "Christop_Friesen@jordan.me",
19 | "id": 198,
20 | "name": "quod vel enim sit quia ipsa quo dolores",
21 | "postId": 40
22 | },
23 | {
24 | "body": "veniam eos ab voluptatem in fugiat ipsam quis\nofficiis non qui\nquia ut id voluptates et a molestiae commodi quam\ndolorem enim soluta impedit autem nulla",
25 | "email": "Cooper_Boehm@damian.biz",
26 | "id": 199,
27 | "name": "pariatur aspernatur nam atque quis",
28 | "postId": 40
29 | },
30 | {
31 | "body": "facere maxime alias aspernatur ab quibusdam necessitatibus\nratione similique error enim\nsed minus et\net provident minima voluptatibus",
32 | "email": "Amir@kaitlyn.org",
33 | "id": 200,
34 | "name": "aperiam et omnis totam",
35 | "postId": 40
36 | }
37 | ]
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/ivyResolveItv1.sc:
--------------------------------------------------------------------------------
1 | import $ivy.`com.lihaoyi::some-dummy-library:0.2+`
2 |
3 | import io.circe._
4 | val json = Json.obj("a" -> Json.True)
5 |
6 | println(dummy.Dummy.thing)
7 |
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/ivyResolveItv2.sc:
--------------------------------------------------------------------------------
1 | import $ivy.`com.lihaoyi::some-dummy-library:0.2+`
2 |
3 | import argonaut._
4 | val json = Json.obj("a" -> Json.jTrue, "c" -> Json.jString("b"))
5 |
6 | println(dummy.Dummy.thing)
7 |
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/ivyResolveSnapshot1.sc:
--------------------------------------------------------------------------------
1 | import $ivy.`com.lihaoyi::some-dummy-library:0.1-SNAPSHOT`
2 |
3 | import io.circe._
4 | val json = Json.obj("a" -> Json.True)
5 |
6 | println(dummy.Dummy.thing)
7 |
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/ivyResolveSnapshot2.sc:
--------------------------------------------------------------------------------
1 | import $ivy.`com.lihaoyi::some-dummy-library:0.1-SNAPSHOT`
2 |
3 | import argonaut._
4 | val json = Json.obj("a" -> Json.jTrue, "c" -> Json.jString("b"))
5 |
6 | println(dummy.Dummy.thing)
7 |
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/scalaTags.sc:
--------------------------------------------------------------------------------
1 | interp.load.ivy("com.lihaoyi" %% "scalatags" % "0.7.0")
2 | @
3 | import scalatags.Text.all._
4 | val res = a("omg", href:="www.google.com").render
5 |
6 | println(res)
7 |
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/basic/wrongIvyCordinates.sc:
--------------------------------------------------------------------------------
1 | import $ivy.`com.lihaoyi::somethingWhichDoesNotExist:0.4.5`
2 |
3 |
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/errorTruncation/compileError.sc:
--------------------------------------------------------------------------------
1 | doesntexist
2 |
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/errorTruncation/compileErrorMultiExpr.sc:
--------------------------------------------------------------------------------
1 | // Make sure the line numbers work properly in cases where we have statement
2 | // breaks, both implicitly due to newlines, explicitly due to semi-colons, or
3 | // both!
4 | 123;456
5 |
6 | ;implicitly{
7 | math.max(1 + 2 + 3, 4)
8 | }
9 |
10 | identity("Hello");
11 | doesntexist
12 |
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/errorTruncation/parseError.sc:
--------------------------------------------------------------------------------
1 | }
2 |
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/errorTruncation/runtimeError.sc:
--------------------------------------------------------------------------------
1 | 1/0
2 |
--------------------------------------------------------------------------------
/integration/src/test/resources/ammonite/integration/lineNumbers/compilationErrorInSecondBlock.sc:
--------------------------------------------------------------------------------
1 |
2 | //Another Comment
3 |
4 | def quicksort(unsorted : List[Int]) : List[Int] = {
5 | if(unsorted.length <= 1) unsorted
6 | else{
7 | val pivot = unsorted.head
8 | quicksort(unsorted.filter(_ < pivot)):::List(pivot):::quicksort(unsorted.filter(_ > pivot))
9 | }
10 | }
11 |
12 | @
13 |
14 | printnl("OK")
15 |
16 | //One more comment
17 | //This one is long one!
18 | //check empty lines
19 |
20 | val x = 1
21 | println(x)
22 | //print the value of x
23 | @
24 |
25 | //lots of comments!!
26 |
27 | prinntl("Ammonite")
28 |
--------------------------------------------------------------------------------
/integration/src/test/resources/some-dummy-library/build.sbt:
--------------------------------------------------------------------------------
1 | val scalaV = sys.env("SCALA_VERSION")
2 | val circeVersion = if(scalaV.startsWith("3.")) "0.14.6" else "0.12.0-M3"
3 |
4 | lazy val root = (project in file(".")).
5 | settings(
6 | name := "some-dummy-library",
7 | organization := "com.lihaoyi",
8 | version := sys.env("VERSION"),
9 | scalaVersion := sys.env("SCALA_VERSION"),
10 | libraryDependencies += {
11 | if (sys.env("FIRST_RUN").toBoolean)
12 | "io.circe" %% "circe-core" % circeVersion
13 | else
14 | "io.argonaut" %% "argonaut" % "6.2.6"
15 | }
16 | )
17 |
--------------------------------------------------------------------------------
/integration/src/test/resources/some-dummy-library/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.9.6
2 |
--------------------------------------------------------------------------------
/integration/src/test/scala-2.13/ammonite/integration/ProjectTests213.scala:
--------------------------------------------------------------------------------
1 | package ammonite.integration
2 |
3 | import ammonite.integration.TestUtils._
4 | import utest._
5 |
6 | object ProjectTests213 extends TestSuite {
7 |
8 | val tests = Tests {
9 | println("Running ProjectTest213")
10 |
11 | test("httpApi") {
12 | def addPostTest() = jsonplaceholder.withServer { url =>
13 | val res = execWithEnv(
14 | Seq("JSONPLACEHOLDER" -> url),
15 | os.rel / 'basic / "HttpApi.sc",
16 | "addPost",
17 | "title",
18 | "some text"
19 | )
20 | assert(res.out.trim.contains("101"))
21 | }
22 | def commentsTest() = jsonplaceholder.withServer { url =>
23 | val res = execWithEnv(
24 | Seq("JSONPLACEHOLDER" -> url),
25 | os.rel / 'basic / "HttpApi.sc",
26 | "comments",
27 | "40"
28 | )
29 | assert(res.out.trim.contains("totam vel saepe aut"))
30 | assert(res.out.trim.contains("aperiam et omnis totam"))
31 | }
32 | test("addPost") {
33 | if (isScala2) addPostTest()
34 | else "Disabled in Scala 3"
35 | }
36 | test("comments") {
37 | if (isScala2) commentsTest()
38 | else "Disabled in Scala 3"
39 | }
40 | }
41 | }
42 | }
43 |
44 | object jsonplaceholder extends cask.MainRoutes {
45 |
46 | private val comments = Map(
47 | 40 -> ujson.read(
48 | os.read(replStandaloneResources / 'basic / "http-api-data.json")
49 | )
50 | )
51 |
52 | @cask.postForm("/posts")
53 | def posts(title: String, body: String, userId: String) = {
54 | System.err.println(s"got request $title, $body, $userId")
55 | cask.Response(ujson.Obj("id" -> 101).render())
56 | }
57 |
58 | @cask.get("/comments")
59 | def commentsHandler(postId: String) = {
60 | val postId0 = scala.util.Try(postId.toInt).getOrElse(0)
61 | val resp = comments.getOrElse(postId0, ujson.Obj())
62 | cask.Response(resp)
63 | }
64 |
65 | initialize()
66 |
67 | def withServer[T](f: String => T): T = {
68 | import scala.collection.JavaConverters._
69 | var server: io.undertow.Undertow = null
70 | try {
71 | server = io.undertow.Undertow.builder
72 | .addHttpListener(0, "localhost")
73 | .setHandler(defaultHandler)
74 | .build()
75 | server.start()
76 | val addr = server
77 | .getListenerInfo
78 | .asScala
79 | .head
80 | .getAddress
81 | .asInstanceOf[java.net.InetSocketAddress]
82 | val url = s"http://${addr.getHostString}:${addr.getPort}"
83 | f(url)
84 | } finally {
85 | if (server != null)
86 | server.stop()
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/integration/src/test/scala/ammonite/integration/AmmoniteBridge.scala:
--------------------------------------------------------------------------------
1 | package ammonite.integration
2 | object AmmoniteBridge {
3 | def main(args: Array[String]): Unit = {
4 | ammonite.AmmoniteMain.main(args)
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/integration/src/test/scala/ammonite/integration/LineNumberTests.scala:
--------------------------------------------------------------------------------
1 | package ammonite.integration
2 | import ammonite.util.Util
3 | import utest._
4 | import TestUtils._
5 |
6 | /**
7 | * Mostly already tested in the `ammonite.main` unit tests; one test case is
8 | * left here just to verify end-to-end correctness
9 | */
10 | object LineNumberTests extends TestSuite {
11 | val tests = this {
12 |
13 | def checkErrorMessage(file: os.RelPath, expected: String): Unit = {
14 | val e = intercept[os.SubprocessException] {
15 | exec(file)
16 | }.result.err.text()
17 | assert(TestUtils.containsLines(e, expected))
18 | }
19 |
20 | test("compilationErrorInSecondBlock") {
21 | val path = os.rel / "lineNumbers" / "compilationErrorInSecondBlock.sc"
22 | val sp = " "
23 | checkErrorMessage(
24 | file = path,
25 | expected = Util.normalizeNewlines(
26 | if (isScala2)
27 | """compilationErrorInSecondBlock.sc:14: not found: value printnl
28 | |val res_0 = printnl("OK")
29 | | ^""".stripMargin
30 | else if (scalaVersion < "3.3.4")
31 | s"""-- [E006] Not Found Error: ${replStandaloneResources / path}:1:12$sp
32 | |1 |val res_0 = printnl("OK")
33 | | | ^^^^^^^
34 | | | Not found: printnl
35 | |Compilation Failed""".stripMargin
36 | else
37 | s"""-- [E006] Not Found Error: ${replStandaloneResources / path}:1:12$sp
38 | |1 |val res_0 = printnl("OK")
39 | | | ^^^^^^^
40 | | | Not found: printnl - did you mean print? or perhaps printf or println?
41 | | |
42 | | | longer explanation available when compiling with `-explain`
43 | |Compilation Failed""".stripMargin
44 | )
45 | )
46 | }
47 |
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/integration/src/test/scala/ammonite/integration/ProjectTests.scala:
--------------------------------------------------------------------------------
1 | package ammonite.integration
2 |
3 | import ammonite.integration.TestUtils._
4 | import ammonite.util.Util
5 | import utest._
6 |
7 | /**
8 | * Run a small number of scripts using the Ammonite standalone executable,
9 | * to make sure that this works. Otherwise it tends to break since the
10 | * standalone executable has a pretty different classloading environment
11 | * from the "run in SBT on raw class files" that the rest of the tests use.
12 | *
13 | * These are also the only tests that cover all the argument-parsing
14 | * and configuration logic inside, which the unit tests don't cover since
15 | * they call the REPL programmatically
16 | */
17 | object ProjectTests extends TestSuite {
18 |
19 | val tests = Tests {
20 | println("Running ProjectTest")
21 |
22 | test("playframework") {
23 | if (!Util.windowsPlatform) {
24 | if (scalaVersion.startsWith("2.11.") && javaVersion.startsWith("1.8.")) {
25 | val evaled = exec(os.rel / "basic" / "PlayFramework.sc")
26 | assert(evaled.out.text().contains("Hello bar"))
27 | }
28 | }
29 | }
30 | // Disabled due to travis instability
31 | // test("spark"){
32 | // // Note that this script screws up if you try to run it within SBT! It has to
33 | // // be run as an integration test, or via `sbt amm/test:assembly && amm/target/amm`
34 | // if (!Util.windowsPlatform) {
35 | // if (scalaVersion.startsWith("2.11.") && javaVersion.startsWith("1.8.")){
36 | // val evaled = exec('basic/"Spark.sc")
37 | // assert(evaled.out.string.contains("List(10, 20, 30, 40, 50)"))
38 | // }
39 | // }
40 | // }
41 |
42 | test("spark2") {
43 | // Note that this script screws up if you try to run it within SBT! It has to
44 | // be run as an integration test, or via `sbt amm/test:assembly && amm/target/amm`
45 | if (!Util.windowsPlatform) {
46 | if (scalaVersion.startsWith("2.11.") && javaVersion.startsWith("1.8.")) {
47 | val evaled = exec(os.rel / "basic" / "Spark2.sc")
48 | assert(evaled.out.text().contains("fake db write"))
49 | }
50 | }
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/integration/src/test/scala/ammonite/integration/TestMain.scala:
--------------------------------------------------------------------------------
1 | package ammonite.integration
2 | object TestMain {
3 | def main(args: Array[String]): Unit = {
4 | val hello = "Hello"
5 | // Break into debug REPL with
6 | ammonite.Main(
7 | predefCode = "println(\"Starting Debugging!\")"
8 | ).run(
9 | "hello" -> hello,
10 | "fooValue" -> foo()
11 | )
12 | }
13 | def foo() = 1
14 | }
15 |
--------------------------------------------------------------------------------
/integration/src/test/scala/ammonite/integration/TestUtils.scala:
--------------------------------------------------------------------------------
1 | package ammonite.integration
2 |
3 | import ammonite.util.Util
4 |
5 | /**
6 | * Created by haoyi on 6/4/16.
7 | */
8 | object TestUtils {
9 | val scalaVersion = ammonite.compiler.CompilerBuilder.scalaVersion
10 | val isScala2 = scalaVersion.startsWith("2.")
11 | val javaVersion = scala.util.Properties.javaVersion
12 | val ammVersion = ammonite.Constants.version
13 | val ammAssembly = System.getenv("AMMONITE_ASSEMBLY")
14 | val executable =
15 | if (Util.windowsPlatform)
16 | Seq(ammAssembly)
17 | else
18 | Seq("bash", ammAssembly)
19 | val intTestResources = os.pwd / "integration" / "src" / "test" / "resources"
20 | val replStandaloneResources = intTestResources / "ammonite" / "integration"
21 | val shellAmmoniteResources =
22 | os.pwd / "shell" / "src" / "main" / "resources" / "ammonite" / "shell"
23 |
24 | // we use an empty predef file here to isolate the tests from external forces.
25 | def execBase(
26 | name: os.RelPath,
27 | extraAmmArgs: Seq[String],
28 | home: os.Path,
29 | args: Seq[String],
30 | thin: Boolean,
31 | extraEnv: Iterable[(String, String)]
32 | ) = {
33 | os.proc(
34 | executable,
35 | extraAmmArgs,
36 | if (thin) Seq("--thin") else Nil,
37 | "--home",
38 | home,
39 | replStandaloneResources / name,
40 | args
41 | ).call(
42 | env = Map("JAVA_OPTS" -> null) ++ extraEnv,
43 | stderr = os.Pipe
44 | )
45 | }
46 | def exec(name: os.RelPath, args: String*) =
47 | execBase(name, Nil, os.temp.dir(), args, thin = true, Nil)
48 | def execWithEnv(env: Iterable[(String, String)], name: os.RelPath, args: String*) =
49 | execBase(name, Nil, os.temp.dir(), args, thin = true, env)
50 | def execNonThin(name: os.RelPath, args: String*) =
51 | execBase(name, Nil, os.temp.dir(), args, thin = false, Nil)
52 | def execWithHome(home: os.Path, name: os.RelPath, args: String*) =
53 | execBase(name, Nil, home, args, thin = true, Nil)
54 | def execSilent(name: os.RelPath, args: String*) =
55 | execBase(name, Seq("-s"), os.temp.dir(), args, thin = true, Nil)
56 |
57 | /**
58 | * Counts number of non-overlapping occurrences of `subs` in `s`
59 | */
60 | def substrCount(s: String, subs: String, count: Int = 0, ptr: Int = 0): Int = {
61 | s.indexOf(subs, ptr) match {
62 | case -1 => count
63 | case x => substrCount(s, subs, count + 1, x + subs.length)
64 | }
65 | }
66 |
67 | def containsLines(output: String, expected: String): Boolean =
68 | containsLines(output.linesIterator.toList, expected.linesIterator.toList)
69 |
70 | @annotation.tailrec
71 | def containsLines(output: List[String], expected: List[String]): Boolean =
72 | expected match {
73 | case Nil => true
74 | case h :: t =>
75 | output match {
76 | case Nil => false
77 | case h0 :: t0 =>
78 | val remaining = if (h0.contains(h)) t else expected
79 | containsLines(t0, remaining)
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/internals-docs/packages.md:
--------------------------------------------------------------------------------
1 | Packages
2 | ========
3 |
4 | Like most JVM programs, Ammonite is split into separate packages. Unlike
5 | most of them, it also contains some synthetic packages that house user code
6 | compiled and run within the Ammonite REPL.
7 |
8 | The main static packages containing Ammonite code are:
9 |
10 | - `ammonite.terminal`: a standalone replacement for JLine, with more features
11 | such as syntax-highlighting, GUI-style keybindings and good multiline editing
12 |
13 | - `ammonite`: the main Ammonite REPL
14 |
15 | - `ammonite.sshd`: spin up an Ammonite server in any existing process you can
16 | connect to via SSH
17 |
18 | Each of these has its own unit tests, along with the integration suite in
19 |
20 | - `ammonite.integration`: tests that package up the Ammonite jar, spawn
21 | Ammonite subprocess via the command-line interface and ensure the whole
22 | thing works end-to-end. This has no published artifact
23 |
24 | Lastly, there are the packages which aren't visible in the source code but
25 | contain code that is generated at runtime by Ammonite
26 |
27 | - `$sess`: contains the wrapper-objects that contains any code
28 | a user enters into the REPL. Any values, functions, classes, etc. you write
29 | into the REPL are wraNpped in a wrapper object and placed in this package
30 |
31 | - `$file`: contains the code that results from loading Ammonite
32 | script files into the REPL, or running them using Ammonite from the
33 | command-line. Any scripts are placed in `$file.foo.bar.baz`
34 | for a script in folder `foo/bar/baz/` relative to the current working
35 | directory; scripts outside the current working directory have the
36 | corresponding number of `..` packages e.g. `$file.`..`.foo.bar`
37 | to represent a script in the folder `../foo/bar/` relative to the working
38 | directory.
--------------------------------------------------------------------------------
/internals-docs/predef.md:
--------------------------------------------------------------------------------
1 | Predef
2 | ======
3 |
4 | Ammonite has the concept of a "Predef": Code you can run before entering the
5 | REPL, and provides all sorts of useful things:
6 |
7 | - Import the implicits necessary for the REPL to run at all (pretty-printing
8 | code and types)
9 |
10 | - Loading "common" modules that you want available: `ammonite-shell` to make the
11 | REPL behave like a systems shell,
12 |
13 | - Initialize common definitions *the end-user* of Ammonite desires every time
14 | the REPL is opened
15 |
16 | The Predef itself is made of several parts:
17 |
18 | - `hardcodedPredef`: imports the minimal implicits for the REPL to run.
19 | This is mostly just the implicits necessary for pretty-printing values and
20 | types.
21 |
22 | - `defaultPredefString`: brings in the default set of imports that
23 | Ammonite starts with. This brings in Ammonite Ops' various `|` `|?` `|>`
24 | pipes, `ammonite.tools` like `grep` `time` and `browse`, implicits to
25 | add SBT-style syntax for loading stuff from `load.ivy`, and importing
26 | everything from the `repl` object. This is loaded by default, but can
27 | be disabled by a `--no-default-predef` flag, or `defaultPredef = false` to
28 | `Main`
29 |
30 | - The assignment of any arguments to the `debug` entrypoint to local `val`s
31 |
32 | - Any `commandLinePredef` string you pass in via `predef = "..."` or `--predef "..."`
33 |
34 | - Any predef file, which defaults `~/.ammonite/predef.sc` for the REPL and
35 | `~/.ammonite/predefScript.sc` for scripts, but can be set manually via
36 | `--predef ...`. This split allows you to e.g. put REPL-specific setup
37 | code inside `predef.sc`, without it messing up scripts. Both the REPL and
38 | scripts also run `~/.ammonite/predefShared.sc` for setup code you want to
39 | apply to both
40 |
41 | Unlike script files, anything that is run in the predef is automatically made
42 | available to every executed script without needing to `load.module` or import
43 | it manually. This includes any files being loaded in the predef itself.
44 |
45 |
--------------------------------------------------------------------------------
/mill:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # This is a wrapper script, that automatically download mill from GitHub release pages
4 | # You can give the required mill version with MILL_VERSION env variable
5 | # If no version is given, it falls back to the value of DEFAULT_MILL_VERSION
6 |
7 | set -e
8 |
9 | if [ -z "${DEFAULT_MILL_VERSION}" ] ; then
10 | DEFAULT_MILL_VERSION=0.11.12
11 | fi
12 |
13 | if [ -z "$MILL_VERSION" ] ; then
14 | if [ -f ".mill-version" ] ; then
15 | MILL_VERSION="$(head -n 1 .mill-version 2> /dev/null)"
16 | elif [ -f ".config/mill-version" ] ; then
17 | MILL_VERSION="$(head -n 1 .config/mill-version 2> /dev/null)"
18 | elif [ -f "mill" ] && [ "$0" != "mill" ] ; then
19 | MILL_VERSION=$(grep -F "DEFAULT_MILL_VERSION=" "mill" | head -n 1 | cut -d= -f2)
20 | else
21 | MILL_VERSION=$DEFAULT_MILL_VERSION
22 | fi
23 | fi
24 |
25 | if [ "x${XDG_CACHE_HOME}" != "x" ] ; then
26 | MILL_DOWNLOAD_PATH="${XDG_CACHE_HOME}/mill/download"
27 | else
28 | MILL_DOWNLOAD_PATH="${HOME}/.cache/mill/download"
29 | fi
30 | MILL_EXEC_PATH="${MILL_DOWNLOAD_PATH}/${MILL_VERSION}"
31 |
32 | version_remainder="$MILL_VERSION"
33 | MILL_MAJOR_VERSION="${version_remainder%%.*}"; version_remainder="${version_remainder#*.}"
34 | MILL_MINOR_VERSION="${version_remainder%%.*}"; version_remainder="${version_remainder#*.}"
35 |
36 | if [ ! -s "$MILL_EXEC_PATH" ] ; then
37 | mkdir -p "$MILL_DOWNLOAD_PATH"
38 | if [ "$MILL_MAJOR_VERSION" -gt 0 ] || [ "$MILL_MINOR_VERSION" -ge 5 ] ; then
39 | ASSEMBLY="-assembly"
40 | fi
41 | DOWNLOAD_FILE=$MILL_EXEC_PATH-tmp-download
42 | MILL_VERSION_TAG=$(echo $MILL_VERSION | sed -E 's/([^-]+)(-M[0-9]+)?(-.*)?/\1\2/')
43 | MILL_DOWNLOAD_URL="https://repo1.maven.org/maven2/com/lihaoyi/mill-dist/$MILL_VERSION/mill-dist-$MILL_VERSION.jar"
44 | curl --fail -L -o "$DOWNLOAD_FILE" "$MILL_DOWNLOAD_URL"
45 | chmod +x "$DOWNLOAD_FILE"
46 | mv "$DOWNLOAD_FILE" "$MILL_EXEC_PATH"
47 | unset DOWNLOAD_FILE
48 | unset MILL_DOWNLOAD_URL
49 | fi
50 |
51 | if [ -z "$MILL_MAIN_CLI" ] ; then
52 | MILL_MAIN_CLI="${0}"
53 | fi
54 |
55 | MILL_FIRST_ARG=""
56 |
57 | # first arg is a long flag for "--interactive" or starts with "-i"
58 | if [ "$1" = "--bsp" ] || [ "${1#"-i"}" != "$1" ] || [ "$1" = "--interactive" ] || [ "$1" = "--no-server" ] || [ "$1" = "--repl" ] || [ "$1" = "--help" ] ; then
59 | # Need to preserve the first position of those listed options
60 | MILL_FIRST_ARG=$1
61 | shift
62 | fi
63 |
64 | unset MILL_DOWNLOAD_PATH
65 | unset MILL_VERSION
66 |
67 | exec $MILL_EXEC_PATH $MILL_FIRST_ARG -D "mill.main.cli=${MILL_MAIN_CLI}" "$@"
68 |
--------------------------------------------------------------------------------
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.10.7
2 |
--------------------------------------------------------------------------------
/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("com.lihaoyi" % "scalatex-sbt-plugin" % "0.3.11")
2 |
--------------------------------------------------------------------------------
/readme/ANSI.scala:
--------------------------------------------------------------------------------
1 | package readme
2 |
3 | import scala.collection.mutable
4 | import scalatags.Text.all._
5 |
6 | object ANSI {
7 |
8 | // http://flatuicolors.com/
9 | val red = "#c0392b"
10 | val green = "#27ae60"
11 | val yellow = "#f39c12"
12 | val blue = "#2980b9"
13 | val magenta = "#8e44ad"
14 | val cyan = "#16a085"
15 | val black = "#000"
16 | val white = "#fff"
17 |
18 | val foregrounds = Map[fansi.Attr, String](
19 | fansi.Color.Black -> black,
20 | fansi.Color.Red -> red,
21 | fansi.Color.Green-> green,
22 | fansi.Color.Yellow-> yellow,
23 | fansi.Color.Blue -> blue,
24 | fansi.Color.Magenta-> magenta,
25 | fansi.Color.Cyan -> cyan,
26 | fansi.Color.White -> white
27 | )
28 | val backgrounds = Map[fansi.Attr, String](
29 | fansi.Back.Black -> black,
30 | fansi.Back.Red -> red,
31 | fansi.Back.Green-> green,
32 | fansi.Back.Yellow-> yellow,
33 | fansi.Back.Blue -> blue,
34 | fansi.Back.Magenta-> magenta,
35 | fansi.Back.Cyan -> cyan,
36 | fansi.Back.White -> white
37 | )
38 | def ansiToHtml(ansiInput: String): Frag = {
39 | val wrapped = mutable.Buffer.empty[scalatags.Text.Frag]
40 | val parsed = fansi.Str(ansiInput, errorMode = fansi.ErrorMode.Strip)
41 | val chars = parsed.getChars
42 | val colors = parsed.getColors
43 |
44 | var i = 0
45 | var previousColor = 0L
46 | val snippetBuffer = new mutable.StringBuilder()
47 |
48 | def createSnippet() = {
49 | val foreground = fansi.Color.lookupAttr(previousColor & fansi.Color.mask)
50 | val background = fansi.Back.lookupAttr(previousColor & fansi.Back.mask)
51 | val snippet = snippetBuffer.toString
52 | snippetBuffer.clear()
53 | wrapped.append(span(
54 | foregrounds.get(foreground).map(color := _),
55 | backgrounds.get(background).map(backgroundColor := _),
56 | snippet
57 | ))
58 | }
59 |
60 | while(i < parsed.length){
61 | if (colors(i) != previousColor && snippetBuffer.nonEmpty) createSnippet()
62 | previousColor = colors(i)
63 | snippetBuffer += chars(i)
64 | i += 1
65 | }
66 | createSnippet()
67 | wrapped.toVector
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/readme/resources/Browse.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/Browse.gif
--------------------------------------------------------------------------------
/readme/resources/ColoredTraces.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/ColoredTraces.png
--------------------------------------------------------------------------------
/readme/resources/Debugging.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/Debugging.png
--------------------------------------------------------------------------------
/readme/resources/DebuggingViaSshd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/DebuggingViaSshd.png
--------------------------------------------------------------------------------
/readme/resources/Desugar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/Desugar.png
--------------------------------------------------------------------------------
/readme/resources/Editing.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/Editing.gif
--------------------------------------------------------------------------------
/readme/resources/GettingStarted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/GettingStarted.png
--------------------------------------------------------------------------------
/readme/resources/Highlighting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/Highlighting.png
--------------------------------------------------------------------------------
/readme/resources/HistorySearch.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/HistorySearch.gif
--------------------------------------------------------------------------------
/readme/resources/IvyComplete.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/IvyComplete.gif
--------------------------------------------------------------------------------
/readme/resources/ScriptFolderLayout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/ScriptFolderLayout.png
--------------------------------------------------------------------------------
/readme/resources/ScriptRepl.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/ScriptRepl.gif
--------------------------------------------------------------------------------
/readme/resources/Source.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/Source.gif
--------------------------------------------------------------------------------
/readme/resources/Swing1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/Swing1.png
--------------------------------------------------------------------------------
/readme/resources/Swing2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/Swing2.png
--------------------------------------------------------------------------------
/readme/resources/Swing3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/Swing3.png
--------------------------------------------------------------------------------
/readme/resources/SystemShell.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/SystemShell.png
--------------------------------------------------------------------------------
/readme/resources/UndoRedo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/UndoRedo.gif
--------------------------------------------------------------------------------
/readme/resources/Watch.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/Watch.gif
--------------------------------------------------------------------------------
/readme/resources/favicon-old.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/favicon-old.png
--------------------------------------------------------------------------------
/readme/resources/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/favicon.png
--------------------------------------------------------------------------------
/readme/resources/smaller-favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/smaller-favicon.png
--------------------------------------------------------------------------------
/readme/resources/square-favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/com-lihaoyi/Ammonite/2fdc440b23c9bc7eb782c496c05ec1d3c10ee3d6/readme/resources/square-favicon.png
--------------------------------------------------------------------------------
/sshd/src/main/scala/ammonite/sshd/ShellSession.scala:
--------------------------------------------------------------------------------
1 | package ammonite.sshd
2 |
3 | import java.io.{InputStream, OutputStream}
4 |
5 | import org.apache.sshd.server._
6 | import org.apache.sshd.server.session.ServerSession
7 |
8 | /**
9 | * Implementation of ssh server's remote shell session,
10 | * which will be serving remote user.
11 | * @param remoteShell actual shell implementation,
12 | * which will serve remote user's shell session.
13 | */
14 | private[sshd] class ShellSession(remoteShell: ShellSession.Server)
15 | extends Command {
16 | var in: InputStream = _
17 | var out: OutputStream = _
18 | var exit: ExitCallback = _
19 | lazy val thread = createShellServingThread()
20 |
21 | override def setInputStream(in: InputStream) = {
22 | this.in = in
23 | }
24 | override def setOutputStream(out: OutputStream) = {
25 | this.out = new SshOutputStream(out)
26 | }
27 | /* ammonite doesn't uses err stream so we don't need this */
28 | override def setErrorStream(err: OutputStream) = {}
29 |
30 | /**
31 | * called by ssh server to instrument this session
32 | * with a callback that it finished serving a user
33 | */
34 | override def setExitCallback(exit: ExitCallback) = {
35 | this.exit = exit
36 | }
37 |
38 | /**
39 | * called when ssh server is ready to start this session.
40 | * Starts the actual shell-serving task.
41 | */
42 | override def start(env: Environment) = {
43 | thread.start()
44 | }
45 |
46 | /**
47 | * called when ssh server wants to destroy shell session.
48 | * Whatever shell session serving a user was doing at this moment
49 | * we are free to stop it.
50 | */
51 | override def destroy() = {
52 | thread.interrupt()
53 | }
54 |
55 | private def createShellServingThread(): Thread = new Thread {
56 | override def run(): Unit = {
57 | remoteShell(in, out)
58 | exit.onExit(0, "repl finished")
59 | }
60 | }
61 |
62 | // proxy which fixes output to the remote side to be ssh compatible.
63 | private class SshOutputStream(out: OutputStream) extends OutputStream {
64 | override def close() = { out.close() }
65 | override def flush() = { out.flush() }
66 |
67 | override def write(byte: Int): Unit = {
68 | // ssh client's only accepts new lines with \r so we make \n to be \r\n.
69 | // Unneeded \r will not be seen anyway
70 | if (byte.toChar == '\n') out.write('\r')
71 | out.write(byte)
72 | }
73 |
74 | override def write(bytes: Array[Byte]): Unit = for {
75 | i ← bytes.indices
76 | } write(bytes(i))
77 |
78 | override def write(bytes: Array[Byte], offset: Int, length: Int): Unit = {
79 | write(bytes.slice(offset, offset + length))
80 | }
81 | }
82 |
83 | }
84 |
85 | object ShellSession {
86 | type Server = ((InputStream, OutputStream) => Unit)
87 | }
88 |
--------------------------------------------------------------------------------
/sshd/src/main/scala/ammonite/sshd/SshServerConfig.scala:
--------------------------------------------------------------------------------
1 | package ammonite.sshd
2 |
3 | import ammonite.main.Defaults
4 | import org.apache.sshd.server.auth.password.PasswordAuthenticator
5 | import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator
6 |
7 | /**
8 | * Ssh server parameters
9 | * @param port a port to be used by ssh server. Set it as `0` to let server choose some random port.
10 | * @param ammoniteHome path that ammonite repl sessions will be using as their home directory
11 | * @param hostKeyFile path to the place where to store server's identity key
12 | */
13 | case class SshServerConfig(
14 | address: String,
15 | port: Int,
16 | ammoniteHome: os.Path = Defaults.ammoniteHome,
17 | hostKeyFile: Option[os.Path] = None,
18 | passwordAuthenticator: Option[PasswordAuthenticator] = None,
19 | publicKeyAuthenticator: Option[PublickeyAuthenticator] = None
20 | ) {
21 | require(
22 | passwordAuthenticator.orElse(publicKeyAuthenticator).isDefined,
23 | "you must provide at least one authenticator"
24 | )
25 | override def toString =
26 | s"(port = $port," +
27 | s"home = '$ammoniteHome', hostKeyFile = $hostKeyFile," +
28 | s"passwordAuthenticator = $passwordAuthenticator," +
29 | s"publicKeyAuthenticator = $publicKeyAuthenticator)"
30 | }
31 |
--------------------------------------------------------------------------------
/sshd/src/main/scala/ammonite/sshd/util/Environment.scala:
--------------------------------------------------------------------------------
1 | package ammonite.sshd.util
2 |
3 | import java.io.{InputStream, OutputStream, PrintStream}
4 |
5 | /**
6 | * Container for staging environment important for Ammonite repl to run correctly.
7 | * @param thread a thread where execution takes place. Important for restoring contextClassLoader
8 | * @param contextClassLoader thread's context class loader. Ammonite repl uses that to load classes
9 | * @param systemIn
10 | * @param systemOut
11 | * @param systemErr
12 | */
13 | case class Environment(
14 | thread: Thread,
15 | contextClassLoader: ClassLoader,
16 | systemIn: InputStream,
17 | systemOut: PrintStream,
18 | systemErr: PrintStream
19 | )
20 |
21 | object Environment {
22 | def apply(classLoader: ClassLoader, in: InputStream, out: PrintStream): Environment =
23 | apply(Thread.currentThread(), classLoader, in, out, out)
24 |
25 | def apply(classLoader: ClassLoader, in: InputStream, out: OutputStream): Environment =
26 | apply(classLoader, in, new PrintStream(out))
27 |
28 | /**
29 | * Runs your code with supplied environment installed.
30 | * After execution of supplied code block will restore original environment
31 | */
32 | def withEnvironment(env: Environment)(code: ⇒ Any): Any = {
33 | val oldClassLoader = env.thread.getContextClassLoader
34 | try {
35 | env.thread.setContextClassLoader(env.contextClassLoader)
36 | Console.withIn(env.systemIn) {
37 | Console.withOut(env.systemOut) {
38 | Console.withErr(env.systemErr) {
39 | code
40 | }
41 | }
42 | }
43 | } finally {
44 | env.thread.setContextClassLoader(oldClassLoader)
45 | }
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/sshd/src/test/scala/ammonite/sshd/Main.scala:
--------------------------------------------------------------------------------
1 | package ammonite.sshd
2 |
3 | import java.security.PublicKey
4 | import org.apache.sshd.common.config.keys.{KeyUtils, PublicKeyEntryResolver}
5 | import org.apache.sshd.server.auth.password.PasswordAuthenticator
6 | import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator
7 | import org.apache.sshd.server.config.keys.AuthorizedKeysAuthenticator
8 | import org.apache.sshd.server.session.ServerSession
9 | import scala.annotation.tailrec
10 | import scala.collection.JavaConverters._
11 |
12 | object Main {
13 | def main(args: Array[String]): Unit = {
14 | val config = SshServerConfig(
15 | "localhost",
16 | 2222,
17 | passwordAuthenticator = None,
18 | publicKeyAuthenticator = Some(publicKeyChecker)
19 | )
20 | val ammoniteServer = new SshdRepl(config)
21 |
22 | ammoniteServer.start()
23 | println(s"Ammonite server started. $helpMessage." +
24 | s"To connect use ssh [${currentUserName}@] -p${config.port}")
25 | exitAwaitLoop()
26 | ammoniteServer.stop()
27 |
28 | println("Ammonite server finished")
29 | }
30 |
31 | object publicKeyChecker extends PublickeyAuthenticator {
32 | def authenticate(username: String, key: PublicKey, session: ServerSession): Boolean = {
33 | val keys = AuthorizedKeysAuthenticator.readDefaultAuthorizedKeys()
34 | username == currentUserName &&
35 | keys.asScala
36 | .exists { entry =>
37 | KeyUtils.compareKeys(entry.resolvePublicKey(PublicKeyEntryResolver.IGNORING), key)
38 | }
39 | }
40 | }
41 |
42 | object passwordChecker extends PasswordAuthenticator {
43 | def authenticate(username: String, password: String, session: ServerSession): Boolean = {
44 | username == currentUserName && password == getPassword
45 | }
46 | }
47 |
48 | def currentUserName = System.getProperty("user.name")
49 |
50 | private def getPassword = "password"
51 |
52 | private val helpMessage = "Print 'q' to quit."
53 |
54 | @tailrec private def exitAwaitLoop(): Unit = System.console().readLine() match {
55 | case "q" => println("exiting...")
56 | case cmd =>
57 | println(s"'$cmd' is illegal command! $helpMessage")
58 | exitAwaitLoop()
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/sshd/src/test/scala/ammonite/sshd/ScalaCheckSupport.scala:
--------------------------------------------------------------------------------
1 | package ammonite.sshd
2 |
3 | import org.scalacheck.Test.{PropException, Result, TestCallback}
4 | import org.scalacheck.{Prop, Test}
5 |
6 | trait ScalaCheckSupport {
7 | def check(prop: Prop): Unit = check(Test.Parameters.default.minSuccessfulTests)(prop)
8 |
9 | def check(minSuccessfulTests: Int)(prop: Prop): Unit = {
10 | val resultHolder = new ResultHolder
11 | prop.check {
12 | _.withTestCallback(resultHolder).withMinSuccessfulTests(minSuccessfulTests)
13 | }
14 | val result = resultHolder.result
15 | result.status match {
16 | case PropException(_, e, _) ⇒ throw e
17 | case _ ⇒ assert(result.passed)
18 | }
19 | }
20 |
21 | implicit def utestCheckToProp: Unit ⇒ Prop = { (_) ⇒ Prop.apply(true) }
22 |
23 | class ResultHolder extends TestCallback {
24 | var result: Result = _
25 |
26 | override def onTestResult(name: String, result: Result): Unit = {
27 | this.result = result
28 | }
29 |
30 | override def toString = s"ResultHolder($result)"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/sshd/src/test/scala/ammonite/sshd/SshdReplTest.scala:
--------------------------------------------------------------------------------
1 | package ammonite.sshd
2 |
3 | import utest._
4 |
5 | import scala.concurrent.{Await, Promise}
6 | import scala.language.postfixOps
7 | import scala.concurrent.duration._
8 | import SshTestingUtils._
9 |
10 | object SshdReplTest extends TestSuite {
11 | val remotePromise = Promise[Boolean]()
12 |
13 | override val tests = Tests {
14 | // Diabled on charge of flakiness
15 |
16 | // test("canExecuteRemoteCommand") - retry(3){ // Flaky, not sure why
17 | // withTmpDirectory { tmpDir =>
18 | // val repl = new SshdRepl(
19 | // SshServerConfig("localhost", 0, testUsername, testPassword, tmpDir),
20 | // predef = "val predefinedValue = \"Hello\""
21 | // )
22 | // repl.start()
23 | // val client = sshClient((testUsername, testPassword), "localhost", repl.port)
24 | // client.connect()
25 | // assert(client.isConnected)
26 | //
27 | // val shell = new Shell(client)
28 | // shell.connect()
29 | // assert(shell.isConnected)
30 | //
31 | // shell.input.println("2 + 2")
32 | // shell.input.println("import ammonite.sshd.SshdReplTest")
33 | // shell.input.println("predefinedValue")
34 | // shell.input.println("SshdReplTest.remotePromise.success(true)")
35 | // shell.input.println("exit")
36 | //
37 | // assert(Await.result(remotePromise.future, 60 seconds))
38 | // shell.awaitToBecomeDisconnected(60 seconds)
39 | //
40 | // val outputLines = shell.output.readAll.lines.toList
41 | // val Seq(firstBannerLine, secondBannerLine) = outputLines.take(2)
42 | // val Seq(mathTestPrompt, mathOutput) = outputLines.slice(2, 4)
43 | // val Seq(importAppPackage, importResult) = outputLines.slice(4, 6)
44 | // val Seq(checkPredef, checkPredefResult) = outputLines.slice(6, 8)
45 | //
46 | // assert(
47 | // firstBannerLine.startsWith("Welcome to the Ammonite Repl"),
48 | // secondBannerLine.contains("Scala"),
49 | // secondBannerLine.contains("Java")
50 | // )
51 | // assert(
52 | // mathTestPrompt.contains("2"),
53 | // mathTestPrompt.contains("+"),
54 | // mathOutput.contains("4")
55 | // )
56 | // assert(
57 | // importAppPackage.contains("import"),
58 | // importAppPackage.contains("ammonite.sshd.SshdReplTest"),
59 | // !importResult.toLowerCase.contains("error")
60 | // )
61 | // assert(
62 | // checkPredef.contains("predefinedValue"),
63 | // checkPredefResult.contains("Hello")
64 | // )
65 | // }
66 | // }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/terminal/src/main/scala/ammonite/terminal/ConsoleDim.scala:
--------------------------------------------------------------------------------
1 | package ammonite.terminal
2 |
3 | import sun.misc.{Signal, SignalHandler}
4 |
5 | final class ConsoleDim {
6 |
7 | @volatile private var dimsOpt: Option[(Int, Int)] = None
8 | private var initialized = false
9 | private val lock = new Object
10 |
11 | private def setup(): Unit = {
12 |
13 | // From https://stackoverflow.com/q/31594364/3714539
14 |
15 | val terminalSizeChangedHandler: SignalHandler =
16 | new SignalHandler {
17 | override def handle(sig: Signal): Unit =
18 | lock.synchronized {
19 | dimsOpt = None
20 | }
21 | }
22 |
23 | Signal.handle(new Signal("WINCH"), terminalSizeChangedHandler)
24 |
25 | initialized = true
26 | }
27 |
28 | private def dims(): (Int, Int) =
29 | dimsOpt.getOrElse {
30 | lock.synchronized {
31 | dimsOpt.getOrElse {
32 | if (!initialized)
33 | setup()
34 | val dims = (TTY.consoleDim("cols"), TTY.consoleDim("lines"))
35 | dimsOpt = Some(dims)
36 | dims
37 | }
38 | }
39 | }
40 |
41 | def width(): Int =
42 | dims()._1
43 | def height(): Int =
44 | dims()._2
45 |
46 | }
47 |
48 | object ConsoleDim {
49 |
50 | lazy val get: ConsoleDim =
51 | new ConsoleDim
52 |
53 | def width(): Int =
54 | get.width()
55 | def height(): Int =
56 | get.height()
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/terminal/src/main/scala/ammonite/terminal/FilterTools.scala:
--------------------------------------------------------------------------------
1 | package ammonite.terminal
2 |
3 | /**
4 | * A collection of helpers that to simpify the common case of building filters
5 | */
6 | object FilterTools {
7 |
8 | /**
9 | * Shorthand for pattern matching on [[TermState]]
10 | */
11 | val TS = TermState
12 |
13 | def findChunks(b: Vector[Char], c: Int) = {
14 | val chunks = LineReader.splitBuffer(b)
15 | // The index of the first character in each chunk
16 | val chunkStarts = chunks.inits.map(x => x.length + x.sum).toStream.reverse
17 | // Index of the current chunk that contains the cursor
18 | val chunkIndex = chunkStarts.indexWhere(_ > c) match {
19 | case -1 => chunks.length - 1
20 | case x => x - 1
21 | }
22 | (chunks, chunkStarts, chunkIndex)
23 | }
24 |
25 | def firstRow(cursor: Int, buffer: Vector[Char], width: Int) = {
26 | cursor < width && (buffer.indexOf('\n') >= cursor || buffer.indexOf('\n') == -1)
27 | }
28 | def firstRowInfo(ti: TermInfo) = firstRow(ti.ts.cursor, ti.ts.buffer, ti.width)
29 | def lastRow(cursor: Int, buffer: Vector[Char], width: Int) = {
30 | (buffer.length - cursor) < width &&
31 | (buffer.lastIndexOf('\n') < cursor || buffer.lastIndexOf('\n') == -1)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/terminal/src/main/scala/ammonite/terminal/Protocol.scala:
--------------------------------------------------------------------------------
1 | package ammonite.terminal
2 |
3 | case class TermInfo(ts: TermState, width: Int)
4 |
5 | sealed trait TermAction
6 | case class Printing(ts: TermState, stdout: String) extends TermAction
7 | case class TermState(inputs: LazyList[Int], buffer: Vector[Char], cursor: Int, msg: fansi.Str = "")
8 | extends TermAction
9 | object TermState {
10 | def unapply(ti: TermInfo): Option[(LazyList[Int], Vector[Char], Int, fansi.Str)] = {
11 | TermState.unapply(ti.ts)
12 | }
13 | def unapply(ti: TermAction): Option[(LazyList[Int], Vector[Char], Int, fansi.Str)] = ti match {
14 | case ts: TermState => Some((ts.inputs, ts.buffer, ts.cursor, ts.msg))
15 | case _ => None
16 | }
17 |
18 | }
19 | case class ClearScreen(ts: TermState) extends TermAction
20 | case object Exit extends TermAction
21 | case class Result(s: String) extends TermAction
22 |
--------------------------------------------------------------------------------
/terminal/src/main/scala/ammonite/terminal/Terminal.scala:
--------------------------------------------------------------------------------
1 | package ammonite.terminal
2 |
3 | /**
4 | * The core logic around a terminal; it defines the base `filters` API
5 | * through which anything (including basic cursor-navigation and typing)
6 | * interacts with the terminal.
7 | *
8 | * Maintains basic invariants, such as "cursor should always be within
9 | * the buffer", and "ansi terminal should reflect most up to date TermState"
10 | */
11 | object Terminal {
12 |
13 | type Action = (Vector[Char], Int) => (Vector[Char], Int)
14 | type MsgAction = (Vector[Char], Int) => (Vector[Char], Int, String)
15 |
16 | /**
17 | * Blockingly reads a line from the given input stream and returns it.
18 | *
19 | * @param prompt The prompt to display when requesting input
20 | * @param reader The input-stream where characters come in, e.g. System.in
21 | * @param writer The output-stream where print-outs go, e.g. System.out
22 | * @param filters A set of actions that can be taken depending on the input,
23 | * to manipulate the internal state of the terminal.
24 | * @param displayTransform code to manipulate the display of the buffer and
25 | * cursor, without actually changing the logical
26 | * values inside them.
27 | */
28 | def readLine(
29 | prompt: Prompt,
30 | reader: java.io.Reader,
31 | writer: java.io.Writer,
32 | filters: Filter,
33 | displayTransform: (Vector[Char], Int) => (fansi.Str, Int) = LineReader.noTransform
34 | ): Option[String] = {
35 | TTY.withSttyOverride(TTY.readLineStty()) {
36 | new LineReader(ConsoleDim.width(), prompt, reader, writer, filters, displayTransform)
37 | .readChar(TermState(LazyList.continually(reader.read()), Vector.empty, 0, ""), 0)
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/terminal/src/test/resource/toobig.txt:
--------------------------------------------------------------------------------
1 | class Ansi(output: Writer){
2 | def control(n: Int, c: Char) = output.write(s"\033[" + n + c)
3 |
4 | /**
5 | * Moves to the desired row and column, using individual
6 | * cursor movements. `0` is in the top/left counting up
7 | * towards the bottom/right, and `-1` is in the bottom/right
8 | * counting down towards the top/left
9 | */
10 | def moveTo(row: Int, col: Int) = {
11 | if (row >= 0) {
12 | up(9999)
13 | down(row)
14 | }else{
15 | down(9999)
16 | up(-1-row)
17 | }
18 | if (col >= 0) {
19 | left(9999)
20 | right(col)
21 | }else{
22 | right(9999)
23 | left(-1-col)
24 | }
25 | }
26 | /**
27 | * Move up `n` squares
28 | */
29 | def up(n: Int) = if (n == 0) "" else control(n, 'A')
30 | /**
31 | * Move down `n` squares
32 | */
33 | def down(n: Int) = if (n == 0) "" else control(n, 'B')
34 | /**
35 | * Move right `n` squares
36 | */
37 | def right(n: Int) = if (n == 0) "" else control(n, 'C')
38 | /**
39 |
40 |
41 | /**
42 | * Clear the screen
43 | *
44 | * n=0: clear from cursor to end of screen
45 | * n=1: clear from cursor to start of screen
46 | * n=2: clear entire screen
47 | */
48 | def clearScreen(n: Int) = control(n, 'J')
49 |
50 | }
--------------------------------------------------------------------------------
/terminal/src/test/scala/ammonite/terminal/Checker.scala:
--------------------------------------------------------------------------------
1 | package ammonite.terminal
2 |
3 | import ammonite.terminal.filters.{GUILikeFilters, BasicFilters, ReadlineFilters}
4 | import utest._
5 | object Checker {
6 | def normalize(s: String) = {
7 | // Only do line/margin mangling for multi-line strings
8 | if (s.indexOf('\n') == -1) s
9 | else {
10 | val lines = Predef.augmentString(s).lines.toVector
11 | val min = lines.map(_.indexWhere(_ != ' '))
12 | .filter(_ != -1)
13 | .min
14 | lines.drop(1).dropRight(1).map(_.drop(min)).mkString("\n").replace("\\\n", "")
15 |
16 | }
17 | }
18 |
19 | def apply(width: Int, grid: String) =
20 | new Checker(width, normalize(grid))
21 | }
22 |
23 | /**
24 | * A shell emulator that you can use to test out sequences of various
25 | * [[Terminal.Action]]s against an in-memory (Vector[Char], Int) and
26 | * verify that they do the right thing.
27 | */
28 | class Checker(width: Int, grid: String) {
29 | override def toString = s"Checker($stringGrid)"
30 | var currentGrid = grid.replace("_", "").toVector
31 | var currentCursor = grid.indexOf('_')
32 | var currentMsg = ""
33 | Predef.assert(
34 | currentCursor != -1,
35 | "Cannot find `_` in grid passed to Checker, it needs to " +
36 | "exist to tell the checker where the cursor starts off at"
37 | )
38 | def runMsg(actions: Terminal.MsgAction*) = {
39 | val (endGrid, endCursor, endMsg) = actions.foldLeft((currentGrid, currentCursor, "")) {
40 | case ((g, c, m0), f) =>
41 | val (g1, c1, msg) = f(g, c)
42 | (g1, math.min(g1.length, math.max(0, c1)), msg)
43 | }
44 | currentGrid = endGrid
45 | currentCursor = endCursor
46 | currentMsg = endMsg
47 | this
48 | }
49 | def run(actions: Terminal.Action*) = {
50 | runMsg(actions.map { f => (b: Vector[Char], c: Int) =>
51 | val (b1, c1) = f(b, c)
52 | (b1, c1, "")
53 | }: _*)
54 | }
55 | def stringGrid = {
56 | val prefix = currentGrid.take(currentCursor)
57 | val suffix = currentGrid.drop(currentCursor)
58 | val middle = "_"
59 |
60 | (prefix ++ middle ++ suffix).mkString
61 | }
62 | def check(end0: String) = {
63 | val expectedStringGrid = Checker.normalize(end0)
64 | val actualGrid = stringGrid
65 | assert(actualGrid == expectedStringGrid)
66 | this
67 | }
68 | def checkMsg(expectedMsg: String) = {
69 | assert(currentMsg == expectedMsg)
70 | this
71 | }
72 | def apply(end0: String, actions: Terminal.Action*) = {
73 | run(actions: _*)
74 | check(end0)
75 | }
76 | val edit = new ReadlineFilters.CutPasteFilter()
77 | val down: Terminal.Action = BasicFilters.moveDown(_, _, width)
78 | val up: Terminal.Action = BasicFilters.moveUp(_, _, width)
79 | val home: Terminal.Action = BasicFilters.moveStart(_, _, width)
80 | val end: Terminal.Action = BasicFilters.moveEnd(_, _, width)
81 | val wordLeft: Terminal.Action = GUILikeFilters.wordLeft
82 | val wordRight: Terminal.Action = GUILikeFilters.wordRight
83 | }
84 |
--------------------------------------------------------------------------------
/terminal/src/test/scala/ammonite/terminal/HeightTests.scala:
--------------------------------------------------------------------------------
1 | package ammonite.terminal
2 |
3 | import utest._
4 |
5 | import scala.collection.{immutable => imm}
6 |
7 | object HeightTests extends TestSuite {
8 | val tests = Tests {
9 |
10 | test("a") {
11 | val height = LineReader.calculateHeight0(
12 | LineReader.splitBuffer("abcde".toVector),
13 | width = 2
14 | )
15 | assert(height == Seq(3))
16 | // ab
17 | // cd
18 | // e
19 | }
20 | test("b") {
21 | val height = LineReader.calculateHeight0(
22 | LineReader.splitBuffer("abcd".toVector),
23 | width = 2
24 | )
25 | assert(height == Seq(3))
26 | // ab
27 | // cd
28 | // |
29 | }
30 | test("c") {
31 | val height = LineReader.calculateHeight0(
32 | LineReader.splitBuffer("abcd".toVector),
33 | width = 2
34 | )
35 | assert(height == Seq(3))
36 | // |b
37 | // cd
38 | // _
39 | }
40 |
41 | test("d") {
42 | val height = LineReader.calculateHeight0(
43 | LineReader.splitBuffer("ab\ncd".toVector),
44 | width = 2
45 | )
46 | assert(height == Seq(2, 2))
47 | // |b
48 | // _
49 | // cd
50 | // _
51 | }
52 |
53 | test("e") {
54 | val height = LineReader.calculateHeight0(
55 | LineReader.splitBuffer("ab\ncd".toVector),
56 | width = 2
57 | )
58 | assert(height == Seq(2, 2))
59 | // ab
60 | // _
61 | // cd
62 | // |
63 | }
64 | test("f") {
65 | val height = LineReader.calculateHeight0(
66 | LineReader.splitBuffer("ab\ncd".toVector),
67 | width = 2
68 | )
69 | assert(height == Seq(2, 2))
70 | // ab
71 | // |
72 | // cd
73 | // _
74 | }
75 |
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/terminal/src/test/scala/ammonite/terminal/TestMain.scala:
--------------------------------------------------------------------------------
1 | package ammonite.terminal
2 |
3 | import java.io.OutputStreamWriter
4 |
5 | import ammonite.terminal.filters._
6 | import GUILikeFilters.SelectionFilter
7 | import ammonite.terminal.LazyList.~:
8 |
9 | import scala.annotation.tailrec
10 |
11 | // Test Unicode: 漢語;𩶘da
12 | /**
13 | * A "full" test terminal including all readline-style functionality
14 | * included as filters, but without any Scala/Ammonite specific logic
15 | * at all. Provides a minimal environment for manual testing
16 | */
17 | object TestMain {
18 |
19 | def main(args: Array[String]): Unit = {
20 | System.setProperty("ammonite-sbt-build", "true")
21 | var history = List.empty[String]
22 | val selection = GUILikeFilters.SelectionFilter(indent = 4)
23 | def multilineFilter: Filter = Filter.partial {
24 | case TermState(13 ~: rest, b, c, _) if b.count(_ == '(') != b.count(_ == ')') =>
25 | BasicFilters.injectNewLine(b, c, rest)
26 | }
27 | val reader = new java.io.InputStreamReader(System.in)
28 | val cutPaste = ReadlineFilters.CutPasteFilter()
29 | rec()
30 | @tailrec def rec(): Unit = {
31 | val historyFilter = new HistoryFilter(() => history.toVector, fansi.Color.Blue)
32 | Terminal.readLine(
33 | Console.MAGENTA + (0 until 10).mkString + "\n@@@ " + Console.RESET,
34 | reader,
35 | new OutputStreamWriter(System.out),
36 | Filter.merge(
37 | UndoFilter(),
38 | cutPaste,
39 | historyFilter,
40 | multilineFilter,
41 | selection,
42 | BasicFilters.tabFilter(4),
43 | GUILikeFilters.altFilter,
44 | GUILikeFilters.fnFilter,
45 | ReadlineFilters.navFilter,
46 | // Example multiline support by intercepting Enter key
47 | BasicFilters.all
48 | ),
49 | // Example displayTransform: underline all non-spaces
50 | displayTransform = (buffer, cursor) => {
51 | // underline all non-blank lines
52 |
53 | def hl(b: Vector[Char]): Vector[Char] = b.flatMap {
54 | case ' ' => " "
55 | case '\n' => "\n"
56 | case c => Console.UNDERLINED + c + Console.RESET
57 | }
58 | // and highlight the selection
59 | val ansiBuffer = fansi.Str(SeqCharSequence(hl(buffer)))
60 | val (newBuffer, cursorOffset) = SelectionFilter.mangleBuffer(
61 | selection,
62 | ansiBuffer,
63 | cursor,
64 | fansi.Reversed.On
65 | )
66 | val newNewBuffer = HistoryFilter.mangleBuffer(
67 | historyFilter,
68 | newBuffer,
69 | cursor,
70 | fansi.Color.Green
71 | )
72 |
73 | (newNewBuffer, cursorOffset)
74 | }
75 | ) match {
76 | case None => println("Bye!")
77 | case Some(s) =>
78 | history = s :: history
79 | println(s)
80 | rec()
81 | }
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------