-- ======================================================================== -- FLUTTER/DART PROFILE - Language-specific plugins and LSP configuration -- ======================================================================== -- -- This file contains all Flutter and Dart-specific plugins and configurations. -- These plugins will ONLY load when you open a .dart file, keeping your -- startup time fast and avoiding conflicts with other languages. -- -- Key features to configure here: -- - Flutter tools (hot reload, device management, widget inspector) -- - Dart LSP (dartls via flutter-tools) -- - Dart-specific formatters and linters -- - Flutter-specific keymaps (e.g., fr for Flutter Run) -- -- Usage: Just open a .dart file and these plugins will automatically load! -- ======================================================================== return { -- ======================================================================== -- NVIM-DAP - Debug Adapter Protocol for Flutter debugging -- ======================================================================== -- Load DAP when opening Dart files to enable breakpoint debugging { 'mfussenegger/nvim-dap', ft = 'dart', dependencies = { 'rcarriga/nvim-dap-ui', 'nvim-neotest/nvim-nio', }, }, -- ======================================================================== -- FLUTTER TOOLS - Complete Flutter development environment -- ======================================================================== -- Provides Flutter-specific features like hot reload, device management, -- widget inspector, and integrates the Dart LSP server. -- -- Flutter-specific keymaps (available in .dart files): -- fr - Flutter Run (start app) -- fq - Flutter Quit (stop app) -- fR - Flutter Hot Restart -- fd - Flutter Devices (show connected devices) -- fe - Flutter Emulators (launch emulator) -- fo - Flutter Outline (toggle outline/widget tree) -- fc - Flutter Copy Profile URL (for DevTools) -- -- Debug keymaps: -- - Start/Continue debugging -- - Step over -- - Step into -- - Step out -- db - Toggle breakpoint -- dB - Set conditional breakpoint -- dc - Continue -- dt - Terminate debugging -- ======================================================================== { 'nvim-flutter/flutter-tools.nvim', ft = 'dart', -- Only load when opening Dart files dependencies = { 'nvim-lua/plenary.nvim', 'stevearc/dressing.nvim', -- Optional: better UI for Flutter commands 'mfussenegger/nvim-dap', 'rcarriga/nvim-dap-ui', 'nvim-neotest/nvim-nio', }, config = function() -- Get shared LSP capabilities from blink.cmp local capabilities = require('blink.cmp').get_lsp_capabilities() require('flutter-tools').setup { -- Flutter SDK path (usually auto-detected, but you can specify if needed) -- flutter_path = '/path/to/flutter/bin/flutter', lsp = { capabilities = capabilities, -- Settings passed to the Dart LSP settings = { -- Show TODOs in the problems pane showTodos = true, -- Completion settings completeFunctionCalls = true, -- Enable/disable specific lints -- analysisExcludedFolders = {}, renameFilesWithClasses = 'prompt', enableSnippets = true, }, }, -- Flutter-specific settings decorations = { statusline = { -- Set to true to show Flutter app info in statusline app_version = false, device = true, -- Show device name }, }, widget_guides = { enabled = true, -- Show visual guides for widget nesting }, closing_tags = { highlight = 'Comment', -- Highlight color for closing tags prefix = '// ', -- Text to show before closing tag enabled = true, -- Show closing tags for widgets }, dev_log = { enabled = true, notify_errors = false, -- Don't show error notifications for log buffer issues open_cmd = 'tabedit', -- Open logs in a new tab focus_on_open = false, -- Don't auto-focus the log window }, debugger = { enabled = true, -- Enable Flutter debugger integration run_via_dap = true, -- Use DAP for debugging -- Flutter tools will automatically register DAP configurations -- No need to manually configure launch.json }, } -- ======================================================================== -- DAP UI SETUP - Beautiful debugging interface -- ======================================================================== local dap, dapui = require 'dap', require 'dapui' -- Configure DAP UI dapui.setup { icons = { expanded = '▾', collapsed = '▸', current_frame = '*' }, controls = { icons = { pause = '⏸', play = '▶', step_into = '⏎', step_over = '⏭', step_out = '⏮', step_back = 'b', run_last = '▶▶', terminate = '⏹', disconnect = '⏏', }, }, -- Fix layout to prevent resizing issues with Neo-tree layouts = { { elements = { { id = 'scopes', size = 0.25 }, { id = 'breakpoints', size = 0.25 }, { id = 'stacks', size = 0.25 }, { id = 'watches', size = 0.25 }, }, size = 40, -- Fixed width instead of percentage position = 'right', -- Changed to right to avoid conflict with Neo-tree on left }, { elements = { { id = 'repl', size = 0.5 }, { id = 'console', size = 0.5 }, }, size = 10, -- Fixed height position = 'bottom', }, }, } -- Automatically open/close DAP UI -- Don't close Neo-tree, they can coexist now (DAP on right, Neo-tree on left) dap.listeners.after.event_initialized['dapui_config'] = dapui.open dap.listeners.before.event_terminated['dapui_config'] = dapui.close dap.listeners.before.event_exited['dapui_config'] = dapui.close -- Fix for Flutter Tools log buffer becoming non-modifiable -- This catches all buffer types that might be used for Flutter logs vim.api.nvim_create_autocmd({ 'BufEnter', 'BufWinEnter' }, { pattern = '*', callback = function(args) local bufname = vim.api.nvim_buf_get_name(args.buf) -- Check if this is a Flutter log buffer if bufname:match('__FLUTTER_DEV_LOG__') or vim.bo[args.buf].filetype == 'log' then vim.bo[args.buf].modifiable = true vim.bo[args.buf].readonly = false vim.bo[args.buf].buftype = '' -- Make it a normal buffer end end, }) -- Also fix it whenever Flutter tries to write to the log vim.api.nvim_create_autocmd('BufModifiedSet', { pattern = '*', callback = function(args) local bufname = vim.api.nvim_buf_get_name(args.buf) if bufname:match('__FLUTTER_DEV_LOG__') then vim.bo[args.buf].modifiable = true end end, }) -- ======================================================================== -- FLUTTER-SPECIFIC KEYMAPS -- ======================================================================== -- These keymaps are only available when editing Dart files -- They provide quick access to common Flutter commands -- ======================================================================== vim.api.nvim_create_autocmd('FileType', { pattern = 'dart', callback = function() local opts = { buffer = true, silent = true } -- Flutter run/quit (instant, prompts for device) vim.keymap.set('n', 'fr', 'FlutterRun', vim.tbl_extend('force', opts, { desc = '[F]lutter [R]un' })) vim.keymap.set('n', 'fq', 'FlutterQuit', vim.tbl_extend('force', opts, { desc = '[F]lutter [Q]uit' })) vim.keymap.set('n', 'fR', 'FlutterRestart', vim.tbl_extend('force', opts, { desc = '[F]lutter Hot [R]estart' })) -- Code Actions (Cmd+. equivalent) - wrap, remove, extract widgets, etc. vim.keymap.set('n', '.', vim.lsp.buf.code_action, vim.tbl_extend('force', opts, { desc = 'Code Actions (Cmd+.)' })) vim.keymap.set('v', '.', vim.lsp.buf.code_action, vim.tbl_extend('force', opts, { desc = 'Code Actions (Cmd+.)' })) -- Alternative: use the default LSP keymap vim.keymap.set('n', 'gra', vim.lsp.buf.code_action, vim.tbl_extend('force', opts, { desc = '[G]oto Code [A]ction' })) vim.keymap.set('v', 'gra', vim.lsp.buf.code_action, vim.tbl_extend('force', opts, { desc = '[G]oto Code [A]ction' })) -- Device management vim.keymap.set('n', 'fd', 'FlutterDevices', vim.tbl_extend('force', opts, { desc = '[F]lutter [D]evices' })) vim.keymap.set('n', 'fe', 'FlutterEmulators', vim.tbl_extend('force', opts, { desc = '[F]lutter [E]mulators' })) -- Dev tools vim.keymap.set('n', 'fo', 'FlutterOutlineToggle', vim.tbl_extend('force', opts, { desc = '[F]lutter [O]utline Toggle' })) vim.keymap.set( 'n', 'fc', 'FlutterCopyProfilerUrl', vim.tbl_extend('force', opts, { desc = '[F]lutter [C]opy Profiler URL' }) ) vim.keymap.set('n', 'fl', 'FlutterLspRestart', vim.tbl_extend('force', opts, { desc = '[F]lutter [L]SP Restart' })) -- ======================================================================== -- DEBUG KEYMAPS - Available only in Dart files -- ======================================================================== -- Function key shortcuts (standard debugging) vim.keymap.set('n', '', function() require('dap').continue() end, vim.tbl_extend('force', opts, { desc = 'Debug: Start/Continue' })) vim.keymap.set('n', '', function() require('dap').step_over() end, vim.tbl_extend('force', opts, { desc = 'Debug: Step Over' })) vim.keymap.set('n', '', function() require('dap').step_into() end, vim.tbl_extend('force', opts, { desc = 'Debug: Step Into' })) vim.keymap.set('n', '', function() require('dap').step_out() end, vim.tbl_extend('force', opts, { desc = 'Debug: Step Out' })) -- Leader-based debug commands vim.keymap.set('n', 'db', function() require('dap').toggle_breakpoint() end, vim.tbl_extend('force', opts, { desc = '[D]ebug: Toggle [B]reakpoint' })) vim.keymap.set('n', 'dB', function() require('dap').set_breakpoint(vim.fn.input 'Breakpoint condition: ') end, vim.tbl_extend('force', opts, { desc = '[D]ebug: Set Conditional [B]reakpoint' })) vim.keymap.set('n', 'dc', function() require('dap').continue() end, vim.tbl_extend('force', opts, { desc = '[D]ebug: [C]ontinue' })) vim.keymap.set('n', 'dt', function() require('dap').terminate() end, vim.tbl_extend('force', opts, { desc = '[D]ebug: [T]erminate' })) vim.keymap.set('n', 'du', function() require('dapui').toggle() end, vim.tbl_extend('force', opts, { desc = '[D]ebug: Toggle [U]I' })) -- Register groups with which-key require('which-key').add { { 'f', group = '[F]lutter', mode = 'n' }, { 'd', group = '[D]ebug', mode = 'n' }, } end, }) end, }, }