{"id":37028405,"url":"https://github.com/outr/sourcecode","last_synced_at":"2026-01-14T03:23:39.242Z","repository":{"id":57726906,"uuid":"344561670","full_name":"outr/sourcecode","owner":"outr","description":"Scala library providing \"source\" metadata to your program, similar to Python's __name__, C++'s __LINE__ or Ruby's __FILE__. ","archived":false,"fork":true,"pushed_at":"2021-03-04T18:26:56.000Z","size":438,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-03-26T14:21:39.667Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"com-lihaoyi/sourcecode","license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/outr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-03-04T17:52:20.000Z","updated_at":"2024-03-26T14:21:39.668Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/outr/sourcecode","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/outr/sourcecode","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outr%2Fsourcecode","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outr%2Fsourcecode/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outr%2Fsourcecode/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outr%2Fsourcecode/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/outr","download_url":"https://codeload.github.com/outr/sourcecode/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outr%2Fsourcecode/sbom","scorecard":{"id":714976,"data":{"date":"2025-08-11","repo":{"name":"github.com/outr/sourcecode","commit":"84a3dbf4a003e1fba0fbbcbb9cdb4af550c6682d"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-22T09:20:12.296Z","repository_id":57726906,"created_at":"2025-08-22T09:20:12.296Z","updated_at":"2025-08-22T09:20:12.296Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408831,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-14T03:23:38.475Z","updated_at":"2026-01-14T03:23:39.236Z","avatar_url":"https://github.com/outr.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"SourceCode [![Build Status](https://travis-ci.org/lihaoyi/sourcecode.svg?branch=master)](https://travis-ci.org/lihaoyi/sourcecode) [![Join the chat at https://gitter.im/lihaoyi/Ammonite](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/lihaoyi/sourcecode?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge) [![Maven Central](https://img.shields.io/maven-central/v/com.lihaoyi/sourcecode_2.11.svg)](https://maven-badges.herokuapp.com/maven-central/com.lihaoyi/sourcecode_2.11)\n==========\n\n```scala\n\"com.lihaoyi\" %% \"sourcecode\" % \"0.2.3\" // Scala-JVM\n\"com.lihaoyi\" %%% \"sourcecode\" % \"0.2.3\" // Scala.js / Scala Native\n```\n\n`sourcecode` is a small Scala library for that provides common \"source code\"\ncontext to your program at runtime, similar to Python's `__name__`, C++'s\n`__LINE__` or Ruby's `__FILE__`. For example, you can ask for the file-name\nand line number of the current file, either through the `()` syntax or via an\nimplicit:\n\n```scala\nval file = sourcecode.File()\nassert(file.endsWith(\"/sourcecode/shared/src/test/scala/sourcecode/Tests.scala\"))\n\nval line = implicitly[sourcecode.Line]\nassert(line == 16)\n```\n\nThis might not be something you want to use for \"business logic\", but is very\nhelpful for things like [debugging](#debug-prints), [logging](#logging) or \nproviding automatic diagnostics for [DSLs](#embedding-domain-specific-languages). \nThis information is also available via an `implicit`, letting you write functions\nthat automatically pull it in. \n\nUsing SourceCode on code dealing with lots of anonymous functions or anonymous\nclasses can easily turn what you see in your debug printouts from this:\n\n![Before](docs/Before.png)\n\nTo this:\n\n![After](docs/After.png)\n\nBy capturing source information you can use to give your objects and function \nmeaningful names that tell you where they were defined, automatically without \nneeding you to manually assign a string-ID to every anonymous function or \nanonymous class you define all over your code bas. \n\nIf you like using Sourcecode, you might also enjoy this book by the author which\nteaches you Scala in a similarly simple and straightforward way:\n\n- [Hands-on Scala Programming](https://www.handsonscala.com/) https://www.handsonscala.com/\n\nTable of Contents\n=================\n\n- [Overview](#overview)\n- [Examples](#examples)\n- [Use Cases](#use-cases)\n    - [Logging](#logging)\n    - [Enums](#enums)\n    - [Debug Prints](#debug-prints)\n    - [Embedding Domain-Specific Languages](#embedding-domain-specific-languages)\n- [Version History](#version-history)\n\nOverview\n========\nThe kinds of compilation-time data that `sourcecode` provides are:\n\n- `sourcecode.File`: full path of the current file where the call occurs\n- `sourcecode.FileName`: name of the current file where the call occurs; less\n    verbose than `sourcecode.File` but often enough for debugging purposes\n- `sourcecode.Line`: current line number\n- `sourcecode.Name`: the name of the nearest enclosing definition: `val`,\n  `class`, whatever.\n- `sourcecode.FullName`: the name of the nearest enclosing definition: `val`,\n  `class`, whatever, prefixed by the names of all enclosing `class`s, `trait`s,\n  `object`s or `package`s. Note that this does *not* include other enclosing\n  `def`s, `val`s, `var`s or `lazy val`s`\n- `sourcecode.Enclosing`: the name of the nearest enclosing definition: `val`,\n  `class`, whatever, prefixed by the names of all enclosing `class`s, `trait`s,\n  `object`s or `package`s, `def`s, `val`s, `var`s or `lazy val`s`\n- `sourcecode.Text[T]`: when you want to take a value of type `T`, but also \n  want to get the \"source text\" of that particular value. Note that if \n  you have multiple statements in a `{}` block, `sourcecode.Text` will only \n  capture the source code for the last expression that gets returned. This\n  implicit is slightly experimental; be sure to report any bugs you find!\n- `sourcecode.Args`: the arguments that where provided to the nearest enclosing \n  method\n- `sourcecode.Name.Machine`, `sourcecode.FullName.Machine` and \n  `sourcecode.Enclosing.Machine` which are similar to `sourcecode.Name`,\n  `sourcecode.FullName` and `sourcecode.Enclosing` except they do not filter\n  out synthetic method names; e.g. if you want to see the `\u003cinit\u003e` names or\n  `\u003clocal foo\u003e` names as part of the path, use these instead.\n\nAll these are available both via `()` and as implicits, e.g. `sourcecode.File`\ncan be summoned via `sourcecode.File()` or `implicitly[sourcecode.File].value`.\nThis also means you can define functions that pull in this information\nautomatically:\n\n```scala\ndef foo(arg: String)(implicit file: sourcecode.File) = {\n  ... do something with arg ...\n  ... do something with file.value ...\n}\n\nfoo(\"hello\") // the implicit sourcecode.File is filled in automatically\n```\n\n`sourcecode` does not rely on runtime reflection or stack inspection, and\nis done at compile-time using macros. This means that it is both orders of\nmagnitude faster than e.g. getting file-name and line-numbers using stack\ninspection, and also works on Scala.js where reflection and stack inspection\ncan't be used.\n\nExamples\n========\n\nHere are a few examples of `sourcecode`'s core functions being used in a \nvariety of contexts. Hopefully they will give you an idea of how the various\nimplicits behave:\n\n```scala\npackage sourcecode\n\nobject Implicits {\n  def implicitRun() = {\n    val name = implicitly[sourcecode.Name]\n    assert(name.value == \"name\")\n\n    val fullName = implicitly[sourcecode.FullName]\n    assert(fullName.value == \"sourcecode.Implicits.fullName\")\n\n    val enclosing = implicitly[sourcecode.Enclosing]\n    assert(enclosing.value == \"sourcecode.Implicits.implicitRun enclosing\")\n\n    val pkg = implicitly[sourcecode.Pkg]\n    assert(pkg.value == \"sourcecode\")\n\n    val file = implicitly[sourcecode.File]\n    assert(file.value.endsWith(\"/sourcecode/Implicits.scala\"))\n\n    val fileName = implicitly[sourcecode.FileName]\n    assert(fileName.value == \"Implicits.scala\")\n\n    val line = implicitly[sourcecode.Line]\n    assert(line.value == 23)\n\n    lazy val myLazy = {\n      trait Bar{\n        val name = implicitly[sourcecode.Name]\n        assert(name.value == \"name\")\n\n        val fullName = implicitly[sourcecode.FullName]\n        assert(fullName.value == \"sourcecode.Implicits.Bar.fullName\")\n\n        val file = implicitly[sourcecode.File]\n        assert(file.value.endsWith(\"/sourcecode/Implicits.scala\"))\n\n        val fileName = implicitly[sourcecode.FileName]\n        assert(fileName.value == \"Implicits.scala\")\n\n        val line = implicitly[sourcecode.Line]\n        assert(line.value == 40)\n\n        val enclosing = implicitly[sourcecode.Enclosing]\n        assert(\n          (enclosing.value == \"sourcecode.Implicits.implicitRun myLazy$lzy Bar#enclosing\") ||\n          (enclosing.value == \"sourcecode.Implicits.implicitRun myLazy Bar#enclosing\") // encoding changed in Scala 2.12\n        )\n      }\n      val b = new Bar{}\n    }\n    myLazy\n  }\n}\n```\n\nNote that in \"normal\" usage you would not directly call `implicitly` to summon \nup `sourcecode` values; rather, you would add implicit parameters of these \ntypes to your functions. That would make these values automatically available\nto your functions without needing to manually keep passing them in. Apart from\nsummoning them via implicits, you can also use the `apply` method on each type\nto pull them in using the `()` syntax:\n\n```scala\npackage sourcecode\n\nobject Implicits {\n  def implicitRun() = {\n    val name = implicitly[sourcecode.Name]\n    assert(name.value == \"name\")\n\n    val fullName = implicitly[sourcecode.FullName]\n    assert(fullName.value == \"sourcecode.Implicits.fullName\")\n\n    val enclosing = implicitly[sourcecode.Enclosing]\n    assert(enclosing.value == \"sourcecode.Implicits.implicitRun enclosing\")\n\n    val pkg = implicitly[sourcecode.Pkg]\n    assert(pkg.value == \"sourcecode\")\n\n    val file = implicitly[sourcecode.File]\n    assert(file.value.endsWith(\"/sourcecode/Implicits.scala\"))\n\n    val fileName = implicitly[sourcecode.FileName]\n    assert(fileName.value == \"Implicits.scala\")\n\n    val line = implicitly[sourcecode.Line]\n    assert(line.value == 23)\n\n    lazy val myLazy = {\n      trait Bar{\n        val name = implicitly[sourcecode.Name]\n        assert(name.value == \"name\")\n\n        val fullName = implicitly[sourcecode.FullName]\n        assert(fullName.value == \"sourcecode.Implicits.Bar.fullName\")\n\n        val file = implicitly[sourcecode.File]\n        assert(file.value.endsWith(\"/sourcecode/Implicits.scala\"))\n\n        val fileName = implicitly[sourcecode.FileName]\n        assert(fileName.value == \"Implicits.scala\")\n\n        val line = implicitly[sourcecode.Line]\n        assert(line.value == 40)\n\n        val enclosing = implicitly[sourcecode.Enclosing]\n        assert(\n          (enclosing.value == \"sourcecode.Implicits.implicitRun myLazy$lzy Bar#enclosing\") ||\n          (enclosing.value == \"sourcecode.Implicits.implicitRun myLazy Bar#enclosing\") // encoding changed in Scala 2.12\n        )\n      }\n      val b = new Bar{}\n    }\n    myLazy\n  }\n}\n```\n\nBy default, the various implicits all ignore any synthetic `\u003cinit\u003e`,  \n`\u003clocal Foo\u003e` or `$anonfun` methods that might be present:\n\n```scala\npackage sourcecode\n\nobject NoSynthetic {\n  def run() = {\n    class EnumValue(implicit name: sourcecode.Name){\n      override def toString = name.value\n    }\n    object Foo extends EnumValue\n\n    assert(Foo.toString == \"Foo\")\n\n    object Bar{\n      assert(sourcecode.Name() == \"Bar\")\n      assert(sourcecode.FullName() == \"sourcecode.NoSynthetic.Bar\")\n      assert(sourcecode.Enclosing() == \"sourcecode.NoSynthetic.run Bar\")\n    }\n    Bar\n  }\n}\n```\n\nIf you want these synthetic methods to be shown, use the `.Machine` versions\nof each of these instead:\n\n```scala\npackage sourcecode\n\nobject Synthetic {\n  def run() = {\n    class EnumValue(implicit name: sourcecode.Name.Machine){\n      override def toString = name.value\n    }\n    object Foo extends EnumValue\n\n    assert(Foo.toString == \"\u003cinit\u003e\")\n\n    object Bar{\n      assert(sourcecode.Name.Machine() == \"\u003clocal Bar\u003e\", sourcecode.Name())\n      assert(sourcecode.FullName.Machine() == \"sourcecode.Synthetic.Bar.\u003clocal Bar\u003e\")\n      assert(sourcecode.Enclosing.Machine() == \"sourcecode.Synthetic.run Bar.\u003clocal Bar\u003e\")\n    }\n    Bar\n  }\n}\n```\n\nHopefully this has given you a reasonable feel for *what** sourcecode does. You\nmay still be wondering *why* we would want any of this: what could we possibly \nuse these things for? Why would we want to write code that depends on our \npackage paths or variable names? The section below will provide use cases that\nyou will hopefully be able to relate to. \n\nUse Cases\n=========\n\nAt first it might seem strange to make use of these source-level details in\nyour program: shouldn't a program's meaning not change under re-formatting and\nre-factoring?\n\nIt turns out that there are a number of entirely valid use cases for this sort\nof information that is both extremely handy, and also would not be surprising\nat all to a developer using your API. Here are a few example use cases:\n\nLogging\n-------\n\nYou can use `sourcecode.File` and `sourcecode.Line` to define `log` functions\nthat automatically capture their line number and file-name\n\n```scala\ndef log(foo: String)(implicit line: sourcecode.Line, file: sourcecode.File) = {\n  println(s\"${file.value}:${line.value} $foo\")\n}\n\nlog(\"Foooooo\") // sourcecode/shared/src/test/scala/sourcecode/Tests.scala:86 Fooooo\n```\n\nThis can be handy for letting you see where the log lines are coming from,\nwithout tediously tagging every log statement with a unique prefix.\nFurthermore, this happens at compile time, and is thus orders of magnitude\nfaster than getting this information by generating stack traces, and works\non Scala.js where stack-inspection does not. Lastly, if you want additional \ninformation such as method names, class names, or packages to be provided to\nyour logging function, you can easily do so by asking for the `sourcecode.Name`\nor `sourcecode.FullName` or `sourcecode.Pkg` implicits.\n\nEnums\n-----\n\nYou can use `sourcecode.Name` to define an enumeration-value factory function\nthat automatically assigns names to the enum values based on the name of the\n`val` that it is assigned to\n\n```scala\npackage sourcecode\n\nobject EnumExample {\n  def run() = {\n    case class EnumValue(name: String){\n      override def toString = name\n    }\n    class Enum{\n      def value(implicit name: sourcecode.Name) = EnumValue(name.value)\n    }\n    object MyEnum extends Enum{\n      val firstItem = value\n      val secondItem = value\n    }\n    assert(MyEnum.firstItem.toString == \"firstItem\")\n    assert(MyEnum.secondItem.toString == \"secondItem\")\n  }\n}\n```\n\nThis is very handy, and this functionality is used in a number of libraries\nsuch as [FastParse](http://lihaoyi.github.io/fastparse/) and\n[Scalatags](http://lihaoyi.github.io/scalatags/#CSSStylesheets) to provide\na boilerplate-free experience while still providing good debuggability\nand convenience.\n\nSometimes you want to make sure that different enum values in differently\nnamed enums (or even an enum of the same name in a different package!) are\ngiven unique names. In that case, you can use `sourcecode.FullName` or\n`sourcecode.Enclosing` to capture the full path e.g.\n`\"com.mypkg.MyEnum.firstItem\"` and `\"com.mypkg.MyEnum.secondItem\"`:\n \n```scala\npackage sourcecode\n\nobject EnumFull {\n  def run() = {\n    case class EnumValue(name: String){\n      override def toString = name\n    }\n    class Enum{\n      def value(implicit name: sourcecode.FullName) = EnumValue(name.value)\n    }\n    object MyEnum extends Enum{\n      val firstItem = value\n      val secondItem = value\n    }\n    assert(MyEnum.firstItem.toString == \"sourcecode.EnumFull.MyEnum.firstItem\")\n    assert(MyEnum.secondItem.toString == \"sourcecode.EnumFull.MyEnum.secondItem\")\n  }\n}\n```\nYou can also use `sourcecode.Name` in an constructor, in which case it'll be \npicked up during inheritance:\n\n```scala\nclass EnumValue(implicit name: sourcecode.Name){\n  override def toString = name.value\n}\nobject Foo extends EnumValue\nprintln(Foo.toString)\nassert(Foo.toString == \"Foo\")\n```\n\nDebug Prints\n------------\n\nHow many times have you written tedious code like\n```scala\nobject Bar{\n  def foo(arg: String) = {\n    println(\"Bar.foo: \" + arg)\n  }\n}\n```\n\nWhere you have to prefix every print statement with the name of the enclosing\nclasses, objects or functions to make sure you can find your print output\n2-3 minutes later? With `source.Enclosing`, you can get this for free:\n\n```scala\ndef debug[V](value: sourcecode.Text[V])(implicit enclosing: sourcecode.Enclosing) = {\n  println(enclosing.value + \" [\" + value.source + \"]: \" + value.value)\n}\n\nclass Foo(arg: Int){\n  debug(arg) // sourcecode.DebugRun.main Foo [arg]: 123\n  def bar(param: String) = {\n    debug(arg -\u003e param)\n  }\n}\nnew Foo(123).bar(\"lol\")  // sourcecode.DebugRun.main Foo#bar [arg -\u003e param]: (123,lol)\n```\n\nYou can easily vary the amount of verbosity, e.g. by swapping the \n`sourcecode.Enclosing` for a `sourcecode.Name` if you think it's too verbose:\n\n```scala\ndef debug[V](value: sourcecode.Text[V])(implicit name: sourcecode.Name) = {\n  println(name.value + \" [\" + value.source + \"]: \" + value.value)\n}\n\nclass Foo(arg: Int){\n  debug(arg) // Foo [arg]: 123\n  def bar(param: String) = {\n    debug(param -\u003e arg)\n  }\n}\nnew Foo(123).bar(\"lol\")  // bar [param]: lol\n```\n\nOr leaving it out entirely:\n\n```scala\ndef debug[V](value: sourcecode.Text[V]) = {\n  println(\"[\" + value.source + \"]: \" + value.value)\n}\n\nclass Foo(arg: Int){\n  debug(arg) // [arg]: 123\n  def bar(param: String) = {\n    debug(param -\u003e arg)\n  }\n}\nnew Foo(123).bar(\"lol\")  // [param]: lol\n```\n\nThus you can easily configure how much information your `debug` helper method\nneeds, at its definition, without having to hunt all over your codebase for the\nvarious `debug` call-sites you left lying around and manually tweaking the \nverbosity of each one. Furthermore, if you want additional information like\n`sourcecode.Line` or `sourcecode.File`, that's all just one implicit away.\n\nThe [PPrint](http://www.lihaoyi.com/upickle-pprint/pprint) \nlibrary provides a `pprint.log` method that does exactly this: prints out the\nvalue provided (in this case pretty-printing it with colors and nice formatting\n\u0026 indentation) together with the enclosing context and line number, so you\ncan easily distinguish your individual prints later:\n\n```scala\nscala\u003e class Foo{\n     |   def bar(grid: Seq[Seq[Int]]) = {\n     |     // automatically capture and print out source context \n     |     pprint.log(grid, tag=\"grid\") \n     |   }\n     | }\ndefined class Foo\n\nscala\u003e new Foo().bar(Seq(0 until 10, 10 until 20, 20 until 30))\npkg.Foo#bar \"grid\":12\nList(\n  Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9),\n  Range(10, 11, 12, 13, 14, 15, 16, 17, 18, 19),\n  Range(20, 21, 22, 23, 24, 25, 26, 27, 28, 29)\n)\n```\n\n`pprint.log` is itself defined as \n\n```scala\ndef log[T: PPrint](value: T, tag: String = \"\")\n                  (implicit cfg: Config = Config.Colors.PPrintConfig,\n                   path: sourcecode.Enclosing,\n                   line: sourcecode.Line) = ...\n```\n\nUsing `sourcecode.Enclosing` and `sourcecode.Line` to provide the context to\nbe printed. You can, or course, define your own `log` method in the same way,\ncustomizing it to print or not-print exactly what you want to see via the \nimplicits that `sourcecode` provides!\n\n`sourcecode.Args` can be used to access all parameters that where provided \nto a method:\n\n```scala\ndef debug(implicit name: sourcecode.Name, args: sourcecode.Args): Unit = {\n  println(name.value + args.value.map(_.map(a =\u003e a.source + \"=\" + a.value).mkString(\"(\", \", \", \")\")).mkString(\"\"))\n}\n\ndef foo(bar: String, baz: Int)(p: Boolean): Unit = {\n  debug\n}\n\nfoo(\"baz\", 42)(true) // foo(bar=baz, baz=42)(p=true)\n```\n\nEmbedding Domain-Specific Languages\n-----------------------------------\n\nThe Scala programming is a popular choice to embed domain-specific languages:\nthat means that you start with some external language, e.g. this \n[MathProg] example\n\n```scala\nparam m;\nparam n;\nparam l;\n\nset I := 1 .. m;\nset J := 1 .. n;\nset K := 1 .. l;\n\nparam c{J};\nparam d{K};\nparam a{I, J};\n\nvar x{J} integer, \u003e= 0;\nvar y{K} \u003e= 0;\n```\n\nThe linked slides has more detail about what exactly this language does (it\ndescribes mathematical optimization problems). For a variety of reasons, you \nmay prefer to write this as part of a Scala program instead: for example you\nmay want Scala's IDE support, or its ability to define functions that help\nreduce boilerplate, or maybe you like the way the compiler provides type errors\nwhen you do the wrong thing.\n\nA first attempt at converting this to Scala may look like this:\n\n```scala\nval m = param(\"m\")\nval n = param(\"n\")\nval l = param(\"l\")\n\nval I = set(\"I\") := 1 to m\nval J = set(\"J\") := 1 to m\nval K = set(\"K\") := 1 to m\n\nval c = param(\"c\", J)\nval d = param(\"d\", K)\nval a = param(\"a\", I, J)\n\nval x = xvar(\"x\", J).integer \u003e= 0\nval y = xvar(\"y\", K) \u003e= 0\n```\n\nThere's a bunch of duplication around the names of the `val`s: each `val`\nhas its name repeated in a string that gets passed to the expression on the\nright. This is for the program to use the name of the `val` later: for example\nwhen printing error messages, or the results of the computation, you want to\nsee which `val`s are involved! Thus you end up duplicating the names over and\nover and over.\n\nWith sourcecode, you can easily define `param` `set` and `xvar` as taking \nimplicit `sourcecode.Name`s, thus eliminating all the boilerplate involved in \nduplicating names:\n\n```scala\nval m = param\nval n = param\nval l = param\n\nval I = set := 1 to m\nval J = set := 1 to m\nval K = set := 1 to m\n\nval c = param(J)\nval d = param(K)\nval a = param(I, J)\n\nval x = xvar(J).integer \u003e= 0\nval y = xvar(K) \u003e= 0\n```\n\nThe popular [FastParse](http://www.lihaoyi.com/fastparse/) parser-combinator\nlibrary uses sourcecode for exactly this use case\n\n```scala\nimport fastparse.all._\nval A = P( \"aa\" )\nval B = P( \"bb\" )\nval C = P( (A | B).rep(1) )\n\nC.parse(\"aabb\") // Success((), 4)\nC.parse(\"X\") // Failure((A | B):1:1 ...\"X\")\n```\n\nAs you can see, the names of the rules `A` and `B` are embedded in the error\nmessages for parse failures. This makes debugging parsers far easier, while \nsaving you the effort of duplicating the name of the parser in possibly \nhundreds of rules in a large parser. In this case, it is the `P(...)` function\nwhich takes an implicit `sourcecode.Name` that does this work:\n\n```scala\ndef P[T](p: =\u003e Parser[T])(implicit name: sourcecode.Name): Parser[T] =\n    parsers.Combinators.Rule(name.value, () =\u003e p)\n```\n\nAnd forwards the name on to the actual `Rule` object, which can make use of it\nin its `.toString` method.\n\nVersion History\n===============\n\n0.2.2\n-----\n\n- Support for Scala-Native 0.4.0\n\n0.1.9\n-----\n\n- `$anonfun` segments are now ignored by `sourcecode.Enclosing`\n\n0.1.8\n-----\n\n- Add `sourceco.FileName` implicit\n\n0.1.7\n-----\n\n- Support for Scala 2.13.0 final\n\n0.1.5\n-----\n- Upgrade Scala, ScalaJS, Scala Native versions ([a21c11a](https://github.com/lihaoyi/sourcecode/commit/a21c11a2d92351013161cb9a889754bcf7095f86))\n\n0.1.4\n-----\n\n- Add Scala Native support [#34](https://github.com/lihaoyi/sourcecode/pull/34)\n- Add 2.13.0-M1 support, [#30](https://github.com/lihaoyi/sourcecode/pull/30)\n- Add OSGi header to jar manifests, [#32](https://github.com/lihaoyi/sourcecode/pull/32)\n\n0.1.3\n-----\n\n- Add scala 2.12.x support, thanks to \n  [Lars Hupel](https://github.com/larsrh)\n\n0.1.2\n-----\n\n- Add `sourcecode.Args` implicit, which can be used to capture debugging information\n  about the nearest enclosing function call for logging/debugging, thanks to \n  [Benjamin Hagemeister](https://github.com/benhag)\n\n- Attempted fix for [#17](https://github.com/lihaoyi/sourcecode/issues/17) and \n  [#13](https://github.com/lihaoyi/sourcecode/issues/13), thanks to\n  [Simeon H.K. Fitch](https://github.com/metasim) \n\n0.1.1\n-----\n\n- Ignore `\u003clocal foo\u003e` and `\u003cinit\u003e` symbols when determining `sourcecode.Name`, \n  `sourcecode.FullName` or `sourcecode.Enclosing`. If you want these, use the\n  `sourcecode.Name.Machine`/`sourcecode.FullName.Machine`/`sourcecode.Enclosing.Machine`\n  implicits instead.\n   \n- Add `sourcecode.Text` implicit to capture source code of an expression\n\n- Add implicit conversions to `sourcecode.*`, so you can pass in a `String`\n  to manually satisfy and implicit wanting a `sourcecode.Name` or \n  `sourcecode.FullName` or `sourcecode.File`, an `Int` to satisfy an implicit \n  asking for `sourcecode.Line` \n\n- `sourcecode.Enclosing` has been simplified to take a single `String` rather\n  than the previous `Vector[Chunk]`.\n  \n- Added the `sourcecode.Pkg` implicit, which provides the current \n  enclosing package without any of the `class`s/`object`s/`def`s/etc.. Can be \n  subtracted from `sourcecode.Enclosing` if you *only* want the \n  `class`s/`object`s/`def`s/etc.\n\n0.1.0\n-----\n\n- First release\n\n[MathProg]: http://www.slideshare.net/gerferra/an-embedded-dsl-to-manipulate-mathprog-mixed-integer-programming-models-within-scala\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foutr%2Fsourcecode","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foutr%2Fsourcecode","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foutr%2Fsourcecode/lists"}