{"id":32164375,"url":"https://github.com/voger/clouseau","last_synced_at":"2026-02-24T04:01:24.301Z","repository":{"id":57484213,"uuid":"107035550","full_name":"voger/clouseau","owner":"voger","description":"A IO.inspect enhancement","archived":false,"fork":false,"pushed_at":"2019-09-22T18:10:10.000Z","size":55,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-24T01:59:40.198Z","etag":null,"topics":["debugging-tool","elixir","macros"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/voger.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2017-10-15T17:56:10.000Z","updated_at":"2022-03-18T21:19:48.000Z","dependencies_parsed_at":"2022-08-26T12:24:01.590Z","dependency_job_id":null,"html_url":"https://github.com/voger/clouseau","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/voger/clouseau","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/voger%2Fclouseau","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/voger%2Fclouseau/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/voger%2Fclouseau/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/voger%2Fclouseau/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/voger","download_url":"https://codeload.github.com/voger/clouseau/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/voger%2Fclouseau/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29771038,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-24T04:01:02.180Z","status":"ssl_error","status_checked_at":"2026-02-24T03:59:49.901Z","response_time":75,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["debugging-tool","elixir","macros"],"created_at":"2025-10-21T14:45:17.234Z","updated_at":"2026-02-24T04:01:24.294Z","avatar_url":"https://github.com/voger.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Presentation\nClouseau is a silly little inspector. Essentialy is an enhancement over the [IO.inspect](https://hexdocs.pm/elixir/IO.html#inspect/2) function.\nIt adds the functionality to display the file, module and line number of the calling location.\nAlso it can optionaly display a line under the inspected term, to separate it from other output\non the screen and optionaly colorize the output. \n\n\n# How to install\n\nAdd `clouseau` to your list of dependencies in `mix.exs`\n\n```elixir\ndef deps do\n  [\n    #...\n    {:clouseau, \"~\u003e 0.5.0\"}\n  ]\nend\n```\n\n\n\n# How to use\n\nIn order to use Clouseau you first must require the `Cl` module\n\n```elixir\nrequire Cl\n```\n\nClouseau exports two macros: `Cl.inspect/2` and `Cl.inspect/3`. Just use them instead of `IO.inspect`.\n\n\n```elixir\nCl.inspect(\"test\", label: \"This is a test\")\n```\n\nor if you want colors and a bottom border\n\n```elixir\nCl.inspect(\"test\", label: \"-cb This is a test\")\n```\n\nOf course the `Cl.inspect/2` macro can be used in a pipe\n\n```elixir\nconn\n  |\u003e Cl.inspect(label: \"-cb Before magic\")\n  |\u003e do_some_magic()\n  |\u003e Cl.inspect(label: \"-cb After magic\")\n```\n\n\nThat's it. You can return to your code now.\n\n\n\nIf you wish to do some customization continue reading below.\n\n## Switches\n\nBoth macros are ready to use out of the box. By default they display the file, module and line where the macro was called, above the label and the inspected term.\n\nclouseau uses [OptionParser](https://hexdocs.pm/elixir/OptionParser.html) to parse the switches. The switches can be given directly in the label option. You can use switches to modify what will be shown.\n\n\n```elixir\nCl.inspect({\"test\", 7, %{banana: :yellow}}, label: \"--no-file Test showing only module and line\")\n# Clouseau.ClTest:20\n# Test showing only module and line: {\"test\", 7, %{banana: :yellow}}\n```\n\n```elixir\nCl.inspect({\"test\", 7, %{banana: :yellow}}, label: \"-b Test With border\", syntax_colors: [number: :blue])\n# lib/cltest.ex\n# Clouseau.ClTest:26\n# Test With border: {\"test\", 7}\n# -------------------------------------------------------------------------------------\n# {\"test\", 7}\n```\n\n\nSwitches must be grouped in the beginning of the string. Any non-switch group of characters stops the parser and the rest of the line is treated as the text of the label. For example:\n\n```elixir\nCl.inspect({\"test\", 7, [banana: :yellow]}, label: \"--no-module --no-line -b Showing only the --file option. The --no-border option has no effect\")\n# lib/cltest.ex\n# Showing only the --file option. The --no-border option has no effect: {\"test\", 7, [banana: \"split\"]}\n# --------------------------------------------------------------------------------------------------------------------------------------------------\n```\n\n---\n**Note:** The first space on the label text is always discarded. The rest of the spaces stay there. This is intentional to keep it as consistent as possible\nwith `IO.inspect` who does not trim white spaces. For example:\n\n```elixir\nCl.inspect({\"test\", 7}, label: \"-b      Test With border\", syntax_colors: [number: :blue])\n#lib/cltest.ex\n#Clouseau.ClTest:26\n#     Test With border: {\"test\", 7}\n#------------------------------------------------------------------------------------------\n```\n\nThe distance between the switch and the text is 6 spaces while the result displays 5 spaces. If, for some reason, you depend on `IO.inspect` not triming the\nwhite space, keep this behavior in mind.\n\n\n---\n\n### The available switches are:\n\n\n| Switch    | Type     | Default | Shortcut | Description                                                                                        |\n|-----------|----------|---------|----------|----------------------------------------------------------------------------------------------------|\n| file      | :boolean | true    | f        | Display the file where this call happened                                                          |\n| full_path | :boolean | false   | none     | Display the file as absolute path or relative to project root. Default is relative to project root |\n| module    | :boolean | true    | m        | Display the module where this call happened                                                        |\n| line      | :boolean | true    | l        | Display the line where this call happened                                                          |\n| text      | :boolean | true    | t        | Display the descriptive text for the label                                                         |\n| border    | :boolean | false   | b        | Display a border under the inspected term                                                          |\n| colors    | :boolean | false   | c        | Colorize the inspected term                                                                        |\n\nIf you wish to have your default set of switches you can set options in your config\n\n```elixir\nconfig :clouseau,\ndefault_switches: [module: true, line: true, file: true, border: true, colors: true]\n```\n\n\n\n## Template\n\nclouseau uses an [EEx](https://hexdocs.pm/eex/EEx.html) template to display the various parts of the label.\nThe template uses a custom engine `Clouseau.TemplateEngine` instead of the default `EEx.SmartEngine`. The differences are:\n\n* It doesn't add a line break on tag's end. Instead you shoud add a `\"\\n\" `where you want a line break. The reason for this change is beacuse this way the line break can be controlled with conditionals.\n* It supports a `has_val?/1` function that returns `false` if the value is one of `nil`, `false` or `\"\"`.\n* The `@` function desn't use `Access.fetch/2` but `Map.get/2` to get the value. It does not warn or rise any errors. Instead it returns an empty string.\n* It can use IO Lists.\n\n\nThe format of the label is not configurable on the fly. If, for example, it is prefered to display the module before the line, this can be changed only by using a diferent template at compile time.\n\nYou can use a custom template by setting in your config. Below is shown the default template as an example.\n\n```elixir\nconfig :clouseau,\ntemplate: \"\"\"\n\u003c% import IO.ANSI %\u003e\n\u003c%= if has_val?(file), do: from_iolist [:blue,  @file, :reset, \"\\n\"] %\u003e\n\u003c%= if has_val?(module), do: from_iolist [:green, @module, \":\"] %\u003e\n\u003c%= if has_val?(line), do:  from_iolist [:red, @line] %\u003e\n\u003c%= if has_val?(module) || has_val?(line), do: from_iolist [:reset, \"\\n\"] %\u003e\n\u003c%= if has_val?(text), do: from_iolist [:yellow, @text, :reset, \": \"] %\u003e\n\"\"\"\n```\n\n## Inspect Colors\n\nThe colors for the inspected term are choosen to match those of iex. If you wish to change any of the default colors you can do so in your config\n\n```elixir\nconfig :clouseau,\n  syntax_colors: [\n    string: :red,\n    number: :yellow\n]\n\n```\n\nThe above snipet will replace the default colors for strings and numbers.\n\nOr directly in you macro call\n\n```elixir\n%{\n  \"doors\" =\u003e 2,\n  \"windows\" =\u003e 5,\n} \n|\u003e Cl.inspect(label: \"-bc Test with border and colors\", syntax_colors: [number: :red])\n```\n\nIf the `syntax_colors` option is used in the macro call, then the default colors or colors used in the `syntax_colors` option in `config.exs` are not used.\n\n```elixir\n%{\n  :answer =\u003e 42,\n  :comment =\u003e \"The Answer to the Ultimate Question of Life, The Universe, and Everything.\"\n\n} \n|\u003e Cl.inspect(syntax_colors: [number: :red])\n```\n\nIn the above snippet, only the numbers will be colored.\n\nIf colors are defined in `config.exs` they will be merged with the default colors. Any defined color will override the default.\n\nColors can be displayed either by using the `-c` switch in the call, by defining the `colors: true` in `config.exs` or the `syntax_colors` option in the call.\n\n\n## Credo\n\nclouseau provides two custom credo checks: `Clouseau.Check.Warning.ClInspect` and `Clouseau.Check.Warning.RequireCl`. To use them just append them to the `:checks` option in your `.credo.exs` file.\n\n```elixir\nchecks: [\n\n  # ... some checks\n\n  # Custom checks can be created using `mix credo.gen.check`.\n  #\n\n  {Clouseau.Check.Warning.ClInspect},\n  {Clouseau.Check.Warning.RequireCl},\n]\n```\n\n# TODO\n* Add some tests\n* Add dialyzer documentation\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvoger%2Fclouseau","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvoger%2Fclouseau","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvoger%2Fclouseau/lists"}