{"id":24901761,"url":"https://github.com/goose97/timber.nvim","last_synced_at":"2026-05-03T04:39:21.939Z","repository":{"id":258286821,"uuid":"873682713","full_name":"Goose97/timber.nvim","owner":"Goose97","description":null,"archived":false,"fork":false,"pushed_at":"2024-11-02T00:50:22.000Z","size":227,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-11-02T01:25:16.466Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Lua","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/Goose97.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-10-16T14:43:38.000Z","updated_at":"2024-11-02T00:50:26.000Z","dependencies_parsed_at":"2024-11-02T01:25:19.244Z","dependency_job_id":"121bf1e6-3612-4c0e-938e-bf6ba3d607c6","html_url":"https://github.com/Goose97/timber.nvim","commit_stats":null,"previous_names":["goose97/neolog","goose97/timber.nvim"],"tags_count":0,"template":false,"template_full_name":"ellisonleao/nvim-plugin-template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Goose97%2Ftimber.nvim","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Goose97%2Ftimber.nvim/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Goose97%2Ftimber.nvim/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Goose97%2Ftimber.nvim/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Goose97","download_url":"https://codeload.github.com/Goose97/timber.nvim/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245898314,"owners_count":20690466,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":"2025-02-01T21:17:41.108Z","updated_at":"2026-05-03T04:39:21.930Z","avatar_url":"https://github.com/Goose97.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"# timber.nvim\n\nInsert log statements blazingly fast and capture log results inline 🪵\n\nhttps://github.com/user-attachments/assets/6bbcb1ab-45a0-45f3-a03a-1d0780219362\n\n## Table of contents\n\n- [Features](#features)\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [Setup](#setup)\n- [Usage](#usage)\n- [Comparison with other plugins](#comparison-with-other-plugins)\n- [Misc](#misc)\n\n## Features\n\n- Quickly insert log statements\n  - Automatically capture the log targets and log position using Treesitter\n  - Customizable log templates\n- Support batch log statements (multiple log target statements)\n- Dot-repeat actions\n- Support various languages:\n  - Javascript (include JSX)\n  - Typescript (include JSX)\n  - Lua\n  - Ruby\n  - Elixir\n  - Golang\n  - Rust\n  - Python\n  - C\n  - C++\n  - Java\n  - C#\n  - Odin\n  - Bash\n  - Swift\n  - Kotlin\n  - Scala\n  - Dart\n  - [Fallback for others](#fallback-for-non-treesitter-languages)\n\n## Requirements\n\n- [Neovim 0.10+](https://github.com/neovim/neovim/releases)\n- [Recommended] [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter): to support languages, users need to install appropriate Treesitter parsers. `nvim-treesitter` provides an easy interface to manage them.\n- [Optional] [telescope.nvim](https://github.com/nvim-telescope/telescope.nvim): required for log statements search feature.\n\n## Installation\n\ntimber.nvim supports multiple plugin managers\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003elazy.nvim\u003c/strong\u003e\u003c/summary\u003e\n\n```lua\n{\n    \"Goose97/timber.nvim\",\n    version = \"*\", -- Use for stability; omit to use `main` branch for the latest features\n    event = \"VeryLazy\",\n    config = function()\n        require(\"timber\").setup({\n            -- Configuration here, or leave empty to use defaults\n        })\n    end\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003epacker.nvim\u003c/strong\u003e\u003c/summary\u003e\n\n```lua\nuse({\n    \"Goose97/timber.nvim\",\n    tag = \"*\", -- Use for stability; omit to use `main` branch for the latest features\n    config = function()\n        require(\"timber\").setup({\n            -- Configuration here, or leave empty to use defaults\n        })\n    end\n})\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003emini.deps\u003c/strong\u003e\u003c/summary\u003e\n\n```lua\nlocal MiniDeps = require(\"mini.deps\");\n\nMiniDeps.add({\n    source = \"Goose97/timber.nvim\",\n})\n\nrequire(\"timber\").setup({\n    -- Configuration here, or leave empty to use defaults\n})\n```\n\u003c/details\u003e\n\n## Setup\n\nYou will need to call `require(\"timber\").setup()` to intialize the plugin. You can pass in a configuration table to customize the plugin.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eDefault configuration\u003c/strong\u003e\u003c/summary\u003e\n\n```lua\n{\n    log_templates = {\n        default = {\n            -- Templates with auto_import: when inserting a log statement, the import line is inserted automatically\n            -- Applies to batch log statements as well\n            -- javascript = {\n            --   [[logger.info('hello world')]],\n            --   auto_import = [[const logger = require('pino')()]]\n            -- }\n            javascript = [[console.log(\"%log_target\", %log_target)]],\n            typescript = [[console.log(\"%log_target\", %log_target)]],\n            astro = [[console.log(\"%log_target\", %log_target)]],\n            vue = [[console.log(\"%log_target\", %log_target)]],\n            jsx = [[console.log(\"%log_target\", %log_target)]],\n            tsx = [[console.log(\"%log_target\", %log_target)]],\n            lua = [[print(\"%log_target\", %log_target)]],\n            luau = [[print(\"%log_target\", %log_target)]],\n            ruby = [[puts(\"%log_target #{%log_target}\")]],\n            elixir = [[IO.inspect(%log_target, label: \"%log_target\")]],\n            go = [[log.Printf(\"%log_target: %v\\n\", %log_target)]],\n            rust = [[println!(\"%log_target: {:#?}\", %log_target);]],\n            python = [[print(f\"{%log_target=}\")]],\n            c = [[printf(\"%log_target: %s\\n\", %log_target);]],\n            cpp = [[std::cout \u003c\u003c \"%log_target: \" \u003c\u003c %log_target \u003c\u003c std::endl;]],\n            java = [[System.out.println(\"%log_target: \" + %log_target);]],\n            c_sharp = [[Console.WriteLine($\"%log_target: {%log_target}\");]],\n            odin = [[fmt.printfln(\"%log_target: %v\", %log_target)]],\n            swift = [[print(\"%log_target:\", %log_target)]],\n            kotlin = [[println(\"%log_target: ${%log_target}\")]],\n            scala = [[println(s\"%log_target: ${%log_target}\")]],\n            dart = [[print(\"%log_target: ${%log_target}\");]],\n        },\n        plain = {\n            javascript = [[console.log(\"%insert_cursor\")]],\n            typescript = [[console.log(\"%insert_cursor\")]],\n            astro = [[console.log(\"%insert_cursor\")]],\n            vue = [[console.log(\"%insert_cursor\")]],\n            jsx = [[console.log(\"%insert_cursor\")]],\n            tsx = [[console.log(\"%insert_cursor\")]],\n            lua = [[print(\"%insert_cursor\")]],\n            luau = [[print(\"%insert_cursor\")]],\n            ruby = [[puts(\"%insert_cursor\")]],\n            elixir = [[IO.puts(%insert_cursor)]],\n            go = [[log.Printf(\"%insert_cursor\")]],\n            rust = [[println!(\"%insert_cursor\");]],\n            python = [[print(f\"%insert_cursor\")]],\n            c = [[printf(\"%insert_cursor \\n\");]],\n            cpp = [[std::cout \u003c\u003c \"%insert_cursor\" \u003c\u003c std::endl;]],\n            java = [[System.out.println(\"%insert_cursor\");]],\n            c_sharp = [[Console.WriteLine(\"%insert_cursor\");]],\n            odin = [[fmt.println(\"%insert_cursor\")]],\n            swift = [[print(\"%insert_cursor\")]],\n            kotlin = [[println(\"%insert_cursor\")]],\n            scala = [[println(\"%insert_cursor\")]],\n            dart = [[print(\"%insert_cursor\");]],\n        },\n    },\n    batch_log_templates = {\n        default = {\n            javascript = [[console.log({ %repeat\u003c\"%log_target\": %log_target\u003e\u003c, \u003e })]],\n            typescript = [[console.log({ %repeat\u003c\"%log_target\": %log_target\u003e\u003c, \u003e })]],\n            astro = [[console.log({ %repeat\u003c\"%log_target\": %log_target\u003e\u003c, \u003e })]],\n            vue = [[console.log({ %repeat\u003c\"%log_target\": %log_target\u003e\u003c, \u003e })]],\n            jsx = [[console.log({ %repeat\u003c\"%log_target\": %log_target\u003e\u003c, \u003e })]],\n            tsx = [[console.log({ %repeat\u003c\"%log_target\": %log_target\u003e\u003c, \u003e })]],\n            lua = [[print(string.format(\"%repeat\u003c%log_target=%s\u003e\u003c, \u003e\", %repeat\u003c%log_target\u003e\u003c, \u003e))]],\n            luau = [[print(`%repeat\u003c%log_target={%log_target}\u003e\u003c, \u003e`)]],\n            ruby = [[puts(\"%repeat\u003c%log_target: #{%log_target}\u003e\u003c, \u003e\")]],\n            elixir = [[IO.inspect({ %repeat\u003c%log_target\u003e\u003c, \u003e })]],\n            go = [[log.Printf(\"%repeat\u003c%log_target: %v\u003e\u003c, \u003e\\n\", %repeat\u003c%log_target\u003e\u003c, \u003e)]],\n            rust = [[println!(\"%repeat\u003c%log_target: {:#?}\u003e\u003c, \u003e\", %repeat\u003c%log_target\u003e\u003c, \u003e);]],\n            python = [[print(f\"%repeat\u003c{%log_target=}\u003e\u003c, \u003e\")]],\n            c = [[printf(\"%repeat\u003c%log_target: %s\u003e\u003c, \u003e\\n\", %repeat\u003c%log_target\u003e\u003c, \u003e);]],\n            cpp = [[std::cout %repeat\u003c\u003c\u003c \"%log_target: \" \u003c\u003c %log_target\u003e\u003c \u003c\u003c \"\\n  \" \u003e \u003c\u003c std::endl;]],\n            java = [[System.out.printf(\"%repeat\u003c%log_target=%s\u003e\u003c, \u003e%n\", %repeat\u003c%log_target\u003e\u003c, \u003e);]],\n            c_sharp = [[Console.WriteLine($\"%repeat\u003c%log_target: {%log_target}\u003e\u003c, \u003e\");]],\n            odin = [[fmt.printfln(\"%repeat\u003c%log_target: %v\u003e\u003c, \u003e\", %repeat\u003c%log_target\u003e\u003c, \u003e)]],\n            swift = [[print(\"%repeat\u003c%log_target: %log_target\u003e\u003c, \u003e\")]],\n            kotlin = [[println(\"%repeat\u003c%log_target=${%log_target}\u003e\u003c, \u003e\")]],\n            scala = [[println(s\"%repeat\u003c%log_target=${%log_target}\u003e\u003c, \u003e\")]],\n            dart = [[print(s\"%repeat\u003c%log_target=${%log_target}\u003e\u003c, \u003e\");]],\n        },\n    },\n    template_placeholders = {\n        filename = function()\n          return vim.fn.expand(\"%:t\")\n        end,\n        -- Custom placeholder. For example, this can be used in log templates as %truncated_line\n        -- truncated_line = function(ctx)\n        --   local line = ctx.log_target:start()\n        --   return nvim_buf_get_lines(0, line - 1, line, false)[1]:sub(1, 16)\n        -- end,\n    },\n    -- The string to search for when deleting or commenting log statements\n    -- Can be used in log templates as %log_marker placeholder\n    log_marker = \"🪵\",\n    -- Controls the flash highlight\n    highlight = {\n        -- After a log statement is inserted\n        on_insert = true,\n        -- After a log target is added to a batch\n        on_add_to_batch = true,\n        -- After a log entry is shown/jumped to in the summary panel\n        on_summary_show_entry = true,\n        -- The duration of the flash highlight\n        duration = 500,\n    },\n    keymaps = {\n        -- Set to false to disable the default keymap for specific actions\n        -- insert_log_below = false,\n        insert_log_below = \"glj\",\n        insert_log_above = \"glk\",\n        insert_plain_log_below = \"glo\",\n        insert_plain_log_above = \"gl\u003cS-o\u003e\",\n        insert_batch_log = \"glb\",\n        add_log_targets_to_batch = \"gla\",\n        insert_log_below_operator = \"g\u003cS-l\u003ej\",\n        insert_log_above_operator = \"g\u003cS-l\u003ek\",\n        insert_batch_log_operator = \"g\u003cS-l\u003eb\",\n        add_log_targets_to_batch_operator = \"g\u003cS-l\u003ea\",\n    },\n    -- Set to false to disable all default keymaps\n    default_keymaps_enabled = true,\n    log_watcher = {\n        enabled = false,\n        sources = {},\n        -- The length of the preview snippet display as extmarks\n        preview_snippet_length = 32,\n    },\n    log_summary = {\n        -- Keymaps for the summary window\n        keymaps = {\n            -- Set to false to disable the default keymap for specific actions\n            -- show_entry = false,\n            show_entry = \"\u003cCR\u003e\",\n            jump_to_entry = \"o\",\n            next_entry = \"]]\",\n            prev_entry = \"[[\",\n            close = \"q\",\n        },\n        -- Set to false to disable all default keymaps in the summary window\n        default_keymaps_enabled = true,\n        -- Customize the summary window\n        win = {\n            -- Control the width of the summary window\n            -- They can be a single integer (number of columns)\n            -- or a float from 0 to 1 (percentage of the current window width e.g. 0.4 for 40%)\n            -- or an array of mixed types\n            -- width = {60, 0.4} means \"the lesser of 60 columns and 40% of the current window width\"\n            width = { 60, 0.4 },\n            -- Determines where the summary window will be opened: left, right\n            position = \"left\",\n            -- Customize the window options\n            opts = {},\n        },\n    },\n}\n```\n\n\u003c/details\u003e\n\n### Keymaps\n\nThe default configuration comes with a set of default keymaps:\n\n| Action | Keymap | Description |\n| -      | -      | -           |\n| insert_log_below | glj | Insert a log statement below the cursor |\n| insert_log_above | glk | Insert a log statement above the cursor |\n| insert_plain_log_below | glo | Insert a plain log statement below the cursor |\n| insert_plain_log_above | gl\\\u003cS-o\\\u003e | Insert a plain log statement above the cursor |\n| add_log_targets_to_batch | gla | Add a log target to the batch |\n| insert_batch_log | glb | Insert a batch log statement |\n\nTo include context in log statements, insert time tracking log statements, etc, see [RECIPES](https://github.com/Goose97/timber.nvim/blob/main/doc/RECIPES.md#advanced-logging-use-cases) guide for keymap inspiration.\n\n## Usage\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eInsert log statements\u003c/strong\u003e\u003c/summary\u003e\n\nThere are two kinds of log statements:\n\n1. Single log statements: log statements that may or may not capture single log target\n2. Batch log statements: log statements that capture multiple log targets\n\nThese examples use the default configuration. The `|` denotes the cursor position.\n\n```help\n    Old text                    Command         New text\n    --------------------------------------------------------------------------------------------\n    local str = \"H|ello\"        glj             local str = \"Hello\"\n                                                print(\"str\", str)\n    --------------------------------------------------------------------------------------------\n    foo(st|r)                   glk             print(\"str\", str)\n                                                foo(str)\n    --------------------------------------------------------------------------------------------\n    foo(st|r, num)              vi(glb          foo(str, num)\n                                                print(string.format(\"str=%s, num=%s\", str, num))\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eCustomize log statements\u003c/strong\u003e\u003c/summary\u003e\n\nThe content of the log statement can be customized via templates. `timber.nvim` supports some special placeholders which will be replaced after inserting:\n\n- `%log_target`: the log target text\n- `%line_number`: the line number of the log target\n- `%filename`: the name of the current file\n\n```lua\nlocal opts = {\n    log_templates = {\n        default = {\n            lua = [[print(\"LOG %log_target ON LINE %filename:%line_number\", %log_target)]],\n        },\n    },\n}\n\nrequire(\"timber\").setup(opts)\n```\n\nOut of the box, `timber.nvim` provides [default templates](https://github.com/Goose97/timber.nvim/blob/main/lua/timber/config.lua) for all supported languages.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eClear/comment log statements\u003c/strong\u003e\u003c/summary\u003e\n\nTo use these features, you need to configure `log_marker`. The default is 🪵. This `log_marker` will be search/grep to find the log statement lines. Make sure to include it in your log templates. A convenient way to do it is using the `%log_marker` placeholder:\n\n```lua\n\nopts = {\n    log_templates = {\n        default = {\n            lua = [[print(\"%log_marker \" .. %log_target)]],\n        },\n    },\n    log_marker = \"🪵\", -- Or any other string, e.g: MY_LOG\n}\n```\n\nClear all log statements in the current buffer:\n\n```lua\nrequire(\"timber.actions\").clear_log_statements({ global = false })\n```\n\nor comment all log statements in the current buffers (call this again will uncomment them):\n\n```lua\nrequire(\"timber.actions\").toggle_comment_log_statements({ global = false })\n```\n\nUse `global = true` to perform the action on all files. `timber.nvim` uses grep to find all log statements in your project. For this to work, you need to make sure your `grepprg` is suitable. The search comand will be invoked as: `\u003cgrepprg\u003e \u003clog_marker\u003e`. These are some recommendations, ranking from most to least recommended:\n\n```lua\nvim.o.grepprg = \"rg --vimgrep --no-heading --smart-case\" -- Use ripgrep\nvim.o.grepprg = \"git grep --line-number --column\" -- Use git\nvim.o.grepprg = \"grep --line-number --with-filename -R --exclude-dir=.git\" -- Use grep\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eSearch log statements\u003c/strong\u003e\u003c/summary\u003e\n\nSimilar to clear/comment log statements feature, you need to configure `log_marker`. `timber.nvim` uses `telescope.nvim` to search log statements:\n\n```lua\nrequire(\"timber.actions\").search_log_statements()\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eCapture log output\u003c/strong\u003e\u003c/summary\u003e\n\n`timber.nvim` can monitor multiple sources and capture the log output. For example, a common use case is to capture the log output from a test runner or from a log file.\n\nHere's an example configuration:\n\n```lua\nrequire(\"timber\").setup({\n    log_templates = {\n        default = {\n            lua = [[print(\"%watcher_marker_start\" .. %log_target .. \"%watcher_marker_end\")]],\n        },\n    },\n    log_watcher = {\n        enabled = true,\n        -- A table of source id and source configuration\n        sources = {\n            log_file = {\n                type = \"filesystem\",\n                name = \"Log file\",\n                path = \"/tmp/debug.log\",\n            },\n            neotest = {\n                -- Test runner\n                type = \"neotest\",\n                name = \"Neotest\",\n            },\n        },\n    }\n})\n\n-- Configure neotest consumer if source neotest is used\nrequire(\"neotest\").setup({\n    consumers = {\n        timber = require(\"timber.watcher.sources.neotest\").consumer,\n    },\n})\n```\n\nThe configuration does two things:\n\n1. It adds the watcher marker placeholders to the log template. These markers help us extract the log results from the sources. For example, the log statement can print to stdout something like this: `🪵ZGH|Hello World|ZGH`. Notice the log content `Hello World` flanked by two markers.\n2. It enables the log watcher and configures the log watcher to monitor two sources: a file and the [neotest](https://github.com/nvim-neotest/neotest) test run output.\n\nAfter the log results are captured, a snippet of the log result will be displayed inline next to the log statement. You can also see the full log content inside a floating window using `require(\"timber.buffers\").open_float()`\n\n![image](https://github.com/user-attachments/assets/e2ea2765-f43d-4ca2-91b5-a02d07f9a4ce)\n\nSee how to setup syntax highlighting for the float buffer in [RECIPES](https://github.com/Goose97/timber.nvim/blob/main/doc/RECIPES.md#pretty-captured-log-buffer).\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eShow log output summary\u003c/strong\u003e\u003c/summary\u003e\n\nYou can view the captured log output in a split window:\n\n```lua\nrequire(\"timber.summary\").open({ focus = true })\n```\n\nhttps://github.com/user-attachments/assets/469cd456-f4a3-4d20-833c-ea1be908776c\n\nThe summary window will show all captured log entries in chronological order. You can view or jump to the log statement line using `o` or `\u003cCR\u003e` with the default mappings.\n\nThe summary window has the following keymaps:\n\n| Action | Keymap | Description |\n| -      | -      | -           |\n| show_entry | \\\u003cCR\\\u003e | Show the buffer contains the log entry |\n| jump_to_entry | o | Same as show_entry, but also move cursor to the location |\n| next_entry | ]] | Jump to next log entry in the summary window |\n| prev_entry | [[ | Jump to prev log entry in the summary window |\n| close | q | Close the summary window |\n| show_help | ? | Show the keymaps for the summary window |\n\n\u003c/details\u003e\n\n## Comparison with other plugins\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003etimber.nvim\u003c/strong\u003e\u003c/summary\u003e\n\n- Pros:\n    - Capture log target using Treesitter. This makes inserting log statements more accurate.\n\n    ```lua\n    if (\n        foo \u003e bar and\n        -- print(\"foo\", foo) - ❌ Non-Treesitter plugin will insert here\n        bar \u003e baz\n    ) then\n        -- print(\"foo\", foo) - ✅ timber.nvim will insert here\n    end\n    ```\n\n    - Insert multiple log statements at once using visual mode\n    - Capture multiple log targets in a single statement. This makes log output more readable and organized.\n    - Can capture log output and display it inline or in a floating window\n\n- Cons:\n    - Treesitter requires hand-written queries for each languages. It does not support all languages out of the box.\n    - Must install Treesitter parser for each language\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003edebugprint.nvim\u003c/strong\u003e\u003c/summary\u003e\n\n[Repo](https://github.com/andrewferrier/debugprint.nvim)\n\n- More mature plugin: support more languages and has fallback heuristic for non-supported languages.\n- Has more features: prompt users to choose expressions to print, print in insert mode\n- Logging mechanism does not use Treesitter as much as timber.nvim\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003envim-chainsaw\u003c/strong\u003e\u003c/summary\u003e\n\n[Repo](https://github.com/chrisgrieser/nvim-chainsaw)\n\n- Comes with many built-in commands: objectLog, typeLog, assertLog, etc\n- Logging mechanism does not use Treesitter as much as timber.nvim\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eprinter.nvim\u003c/strong\u003e\u003c/summary\u003e\n\n[Repo](https://github.com/rareitems/printer.nvim)\n\n- Support only `below` log position or put the log statement into yank register\n- Does not use Treesitter to power log\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003elogsitter.nvim\u003c/strong\u003e\u003c/summary\u003e\n\n[Repo](https://github.com/gaelph/logsitter.nvim)\n\n- Use Treesitter to power log\n- Limited support for languages: only Javascript like, Golang, Lua, Python, Swift\n- Log statements customization is limited: can only specify the log prefix and separator\n\u003c/details\u003e\n\n\n## Misc\n\n### Highlight groups\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to see all highlight groups\u003c/summary\u003e\n\n\u003c!-- hl_start --\u003e\n\n| Highlight Group | Default Group | Description |\n| ----------------------------- | ----------------------- | ------------------------------ |\n| **Timber.Insert** | _Search_ | Flash highlight when insert log statements |\n| **Timber.AddToBatch** | _Search_ | Flash highlight when add log targets to batch |\n| **Timber.LogStatement** | _none_ | Log statement line |\n| **Timber.LogPlaceholderSnippet** | _DiagnosticVirtualTextInfo_ | Captured log output snippet |\n| **Timber.LogPlaceholderTime** | _none_ | Captured log output time |\n| **Timber.FloatingWindowEntrySeparator** | _FloatBorder_ | Horizontal separator between entries in the floating window |\n| **Timber.SummaryEntryHeader** | _none_ | Entry header in the summary window |\n| **Timber.SummaryEntryBodyHighlighted** | _PmenuSel_ | Highlighted entry body in the summary window |\n| **Timber.SummaryJumpToLine** | _Search_ | Flash highlight when jump to line in the summary window |\n\n\u003c!-- hl_end --\u003e\n\n\u003c/details\u003e\n\n### Fallback for non-Treesitter languages\n\nIn case the language does not have a Treesitter parser, the plugin will fallback to use a simple capture mechanism for the `%log_target` placeholder:\n\n1. In normal mode, capture the current word under cursor\n2. In visual mode, capture the selection range\n\n### Tips\n\nIt's common for languages to have syntax to access fields from an object/instance. For example, in Lua, we have `foo.bar`\nor `foo[\"bar\"]`. It introduces a problem: we have more than one potential log targets. Consider this case (`|` denotes\nthe cursor position):\n\n  ```\n  local foo = ba|r.baz[\"baf\"]\n  ```\n\n`bar`, `bar.baz`, and `bar.baz[\"baf\"]` are all sensible choices here, what should we choose? `timber.nvim` applies some\n[heuristic](https://github.com/Goose97/timber.nvim/blob/main/doc/HOW-IT-WORKS.md#Heuristic) to choose the target.\n\nA good rule of thumb is placing your cursor in last part of the field access chain if you want to log it.\n\n```\nlocal foo = ba|r.baz.baf --\u003e print(\"bar\", bar)\nlocal foo = bar.ba|z.baf --\u003e print(\"bar.baz\", bar.baz)\nlocal foo = bar.baz.ba|f --\u003e print(\"bar.baz.baf\", bar.baz.baf)\n```\n\n### Contributing\n\nAny contributions are highly welcome. If you want to support new languages or extend functionalities of existing languages,\nplease read [this documentation](https://github.com/Goose97/timber.nvim/blob/main/doc/HOW-IT-WORKS.md) about the internal of\n`timber.nvim` first. For bug reports, feature requests, or discussions, please file a [Github issue](https://github.com/Goose97/timber.nvim/issues).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoose97%2Ftimber.nvim","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgoose97%2Ftimber.nvim","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoose97%2Ftimber.nvim/lists"}