C.W.K.
Stream
Lesson 02 of 04 · published

Treesitter and Telescope — Structure + Find

~15 min · neovim, treesitter, telescope

Level 0Trapped
0 XP0/35 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

Treesitter — code as a tree, not as regex

Vim's classic syntax highlighting is regex-based: it pattern-matches token types and colors them. It works, but it can't understand code. Treesitter parses code into a real Abstract Syntax Tree (AST) and uses that for highlighting, indentation, and structural text objects. Faster, more accurate, and unlocks features regex can't dream of.

What treesitter gives you in practice

  • Better highlighting — string interpolation, JSX nesting, Markdown code blocks all colored correctly.
  • Smart indentation for languages where context matters (Python, Lua, JSX).
  • Incremental selection — hit Ctrl-Space, your selection grows by one AST node at a time. Word → expression → statement → function. Almost magical for visual selection.
  • Structural text objects with the partner plugin nvim-treesitter-textobjects: af (a function), if (inner function), ac (a class), ic (inner class). Combine with operators: daf deletes the whole function, cif changes the function body.
  • Fold by syntax — actual code-aware folds, not the regex approximation.

Telescope — fuzzy find anything

telescope.nvim is the fuzzy finder. Files, buffers, grep results, LSP symbols, recent files, help tags, git branches, command history — anything that has "a list of options to pick from" can be a Telescope picker. The interaction model is identical for all of them: pop the picker, type to filter, Enter to pick.

The pickers you'll use daily

  • find_files — fuzzy file open. Replaces Cmd-P.
  • live_grep — search file contents across the project. Replaces Cmd-Shift-F.
  • buffers — switch between open buffers.
  • oldfiles — recently opened files (across Neovim restarts).
  • lsp_document_symbols — outline of the current file (functions, classes).
  • lsp_workspace_symbols — search any symbol in the project.
  • diagnostics — LSP errors and warnings, filterable.
  • help_tags — Neovim's help system, fuzzy-searchable.
Telescope replaces three menus. The command palette, the file open dialog, and the global search panel collapse into one keybinding pattern. Once your fingers know <leader>ff, <leader>fg, <leader>fb, opening anything in any project is two keystrokes plus a few characters of fuzzy matching.

Code

Treesitter — full setup·lua
{
  "nvim-treesitter/nvim-treesitter",
  build = ":TSUpdate",
  event = { "BufReadPost", "BufNewFile" },
  dependencies = {
    "nvim-treesitter/nvim-treesitter-textobjects",
  },
  config = function()
    require("nvim-treesitter.configs").setup({
      ensure_installed = {
        "lua", "python", "javascript", "typescript", "tsx",
        "html", "css", "json", "yaml", "toml", "bash",
        "markdown", "markdown_inline", "vim", "vimdoc", "regex",
      },
      auto_install = true,
      highlight = { enable = true },
      indent = { enable = true },
      incremental_selection = {
        enable = true,
        keymaps = {
          init_selection    = "<C-Space>",
          node_incremental  = "<C-Space>",
          scope_incremental = "<C-s>",
          node_decremental  = "<BS>",
        },
      },
      textobjects = {
        select = {
          enable = true,
          lookahead = true,
          keymaps = {
            ["af"] = "@function.outer",
            ["if"] = "@function.inner",
            ["ac"] = "@class.outer",
            ["ic"] = "@class.inner",
            ["aa"] = "@parameter.outer",
            ["ia"] = "@parameter.inner",
          },
        },
        move = {
          enable = true,
          set_jumps = true,
          goto_next_start = {
            ["]f"] = "@function.outer",
            ["]c"] = "@class.outer",
          },
          goto_previous_start = {
            ["[f"] = "@function.outer",
            ["[c"] = "@class.outer",
          },
        },
      },
    })
  end,
}
Telescope — full setup with the daily-use keymap·lua
{
  "nvim-telescope/telescope.nvim",
  cmd = "Telescope",
  dependencies = {
    "nvim-lua/plenary.nvim",
    { "nvim-telescope/telescope-fzf-native.nvim", build = "make" },
  },
  keys = {
    { "<leader>ff", "<cmd>Telescope find_files<CR>",  desc = "Find files" },
    { "<leader>fg", "<cmd>Telescope live_grep<CR>",   desc = "Live grep" },
    { "<leader>fb", "<cmd>Telescope buffers<CR>",     desc = "Buffers" },
    { "<leader>fh", "<cmd>Telescope help_tags<CR>",   desc = "Help" },
    { "<leader>fr", "<cmd>Telescope oldfiles<CR>",    desc = "Recent files" },
    { "<leader>fd", "<cmd>Telescope diagnostics<CR>", desc = "Diagnostics" },
    { "<leader>fs", "<cmd>Telescope lsp_document_symbols<CR>", desc = "Symbols (file)" },
    { "<leader>fS", "<cmd>Telescope lsp_workspace_symbols<CR>", desc = "Symbols (project)" },
    { "<leader>/",  "<cmd>Telescope current_buffer_fuzzy_find<CR>", desc = "Search buffer" },
  },
  opts = {
    defaults = {
      file_ignore_patterns = { "node_modules", ".git/" },
      layout_strategy = "flex",
    },
  },
  config = function(_, opts)
    require("telescope").setup(opts)
    pcall(require("telescope").load_extension, "fzf")
  end,
}
Treesitter text objects in action·vim
daf       " delete a function (whole thing including signature)
dif       " delete inside a function (just the body)
vac       " visually select around a class
yif       " yank the body of a function
]f        " jump to next function start
[f        " jump to previous function start
]c        " jump to next class start
[c        " jump to previous class start

External links

Exercise

Install the treesitter and telescope blocks above. Open a real codebase. (1) <leader>ff + a few characters of a filename — open it. (2) <leader>fg + a string only used in one file — jump straight to it. (3) Inside a function, press Ctrl-Space repeatedly and watch the selection grow by AST nodes. (4) Use daf to delete a whole function. Each move should feel like "how did I do this without it."

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.