Coder Social home page Coder Social logo

akinsho / flutter-tools.nvim Goto Github PK

View Code? Open in Web Editor NEW
881.0 13.0 70.0 6 MB

Tools to help create flutter apps in neovim using the native lsp

License: MIT License

Lua 94.93% Vim Script 5.07%
nvim neovim flutter lsp flutter-apps dart closing-tags

flutter-tools.nvim's Introduction

flutter-tools.nvim

Build flutter and dart applications in neovim using the native LSP. It adds the ability to easily launch flutter applications, debug them, as well as extending/exposing LSP functionality such as the widget guides, an outline view of your widgets, and hot reloading.

This plugin draws inspiration from emacs-lsp/lsp-dart, coc-flutter and nvim-metals.

New to Neovim's LSP Client?

Skip this section if you have already configured nvim lsp.

If you haven't set up nvim's lsp client before there are a few things you should know/steps to follow before setting up this plugin.

This plugin only enhances and adds to the functionality provided by nvim. It does not by itself provide autocompletion, code actions or configure how errors from the language server are displayed. This is all handled by configuring the lsp client.

This plugin handles things like starting and managing flutter application processes allowing for hot reloading, hot restarting, selecting devices/emulators to run as well as niceties like an outline window, widget guides etc. Other core lsp functionality has to be configured via nvim lsp.

To set up the lsp client please read the lsp documentation this can be found in :h lsp as well nvim-lspconfig's README which provides information on how to setup autocompletion and code-actions, those are not configured via this plugin ๐Ÿ™.

A minimal native LSP configuration might look like:

 " Show hover
nnoremap K <Cmd>lua vim.lsp.buf.hover()<CR>
 " Jump to definition
nnoremap gd <Cmd>lua vim.lsp.buf.definition()<CR>
 " Open code actions using the default lsp UI, if you want to change this please see the plugins above
nnoremap <leader>ca <Cmd>lua vim.lsp.buf.code_action()<CR>
 " Open code actions for the selected visual range
xnoremap <leader>ca <Cmd>lua vim.lsp.buf.range_code_action()<CR>

Please note this is not a replacement for reading the documentation, this is only to show new users what some basic setup might look like.

Prerequisites

  • neovim 0.8.0+

Installation

using vim-plug

Plug 'nvim-lua/plenary.nvim'
Plug 'stevearc/dressing.nvim' " optional for vim.ui.select
Plug 'akinsho/flutter-tools.nvim'

using packer.nvim

use {
    'akinsho/flutter-tools.nvim',
    requires = {
        'nvim-lua/plenary.nvim',
        'stevearc/dressing.nvim', -- optional for vim.ui.select
    },
}

using lazy.nvim

{
    'akinsho/flutter-tools.nvim',
    lazy = false,
    dependencies = {
        'nvim-lua/plenary.nvim',
        'stevearc/dressing.nvim', -- optional for vim.ui.select
    },
    config = true,
}

This plugin depends on plenary.nvim, please make sure it is installed.

This plugin depends on vim.ui.select which allows users to control what UI is used for selecting from a list of options. If you don't have a UI configured for vim.ui.select then I highly recommend the excellent dressing.nvim.

Warning

  • flutter tools does not depend on nvim-lspconfig. The two can co-exist but please ensure you do NOT configure dartls using lspconfig. It will be automatically set up by this plugin instead.

  • You might encounter issues using this plugin on the master channel of flutter.

Setup

Vimscript

lua << EOF
  require("flutter-tools").setup {} -- use defaults
EOF

Lua

require("flutter-tools").setup {} -- use defaults

Features

Run flutter app with hot reloading

hot reload

Start emulators or connected devices

flutter-devices

Visualise colours from LSP

lsp-colours

Visualise logs

dev log

Widget guides (experimental, default: disabled)

Widget guides

Outline window

Outline window

Closing Tags

closing tags

Statusline decorations

App version

app_version

Usage

  • FlutterRun - Run the current project. This needs to be run from within a flutter project.
  • FlutterDevices - Brings up a list of connected devices to select from.
  • FlutterEmulators - Similar to devices but shows a list of emulators to choose from.
  • FlutterReload - Reload the running project.
  • FlutterRestart - Restart the current project.
  • FlutterQuit - Ends a running session.
  • FlutterDetach - Ends a running session locally but keeps the process running on the device.
  • FlutterOutlineToggle - Toggle the outline window showing the widget tree for the given file.
  • FlutterOutlineOpen - Opens an outline window showing the widget tree for the given file.
  • FlutterDevTools - Starts a Dart Dev Tools server.
  • FlutterDevToolsActivate - Activates a Dart Dev Tools server.
  • FlutterCopyProfilerUrl - Copies the profiler url to your system clipboard (+ register). Note that commands FlutterRun and FlutterDevTools must be executed first.
  • FlutterLspRestart - This command restarts the dart language server, and is intended for situations where it begins to work incorrectly.
  • FlutterSuper - Go to super class, method using custom LSP method dart/textDocument/super.
  • FlutterReanalyze - Forces LSP server reanalyze using custom LSP method dart/reanalyze.
  • FlutterRename - Renames and updates imports if lsp.settings.renameFilesWithClasses == "always"

FlutterRun

The flutter run command can also optionally take arguments that you might otherwise pass on the commandline such as :FlutterRun --flavor <tasty>, :FlutterRun --no-sound-null-safety.


FlutterOutline

The outline window allows you to see the high level layout of the current buffer.

Full Configuration

Please note you do not need to copy and paste this whole block, this is just to show what options are available You can add keys from the block beneath if there is any behaviour you would like to override or change.

NOTE: Only one of flutter_path and flutter_lookup_cmd should be set. These two keys are two ways of solving the same problem so will conflict if both are set.

-- alternatively you can override the default configs
require("flutter-tools").setup {
  ui = {
    -- the border type to use for all floating windows, the same options/formats
    -- used for ":h nvim_open_win" e.g. "single" | "shadow" | {<table-of-eight-chars>}
    border = "rounded",
    -- This determines whether notifications are show with `vim.notify` or with the plugin's custom UI
    -- please note that this option is eventually going to be deprecated and users will need to
    -- depend on plugins like `nvim-notify` instead.
    notification_style = 'native' | 'plugin'
  },
  decorations = {
    statusline = {
      -- set to true to be able use the 'flutter_tools_decorations.app_version' in your statusline
      -- this will show the current version of the flutter app from the pubspec.yaml file
      app_version = false,
      -- set to true to be able use the 'flutter_tools_decorations.device' in your statusline
      -- this will show the currently running device if an application was started with a specific
      -- device
      device = false,
      -- set to true to be able use the 'flutter_tools_decorations.project_config' in your statusline
      -- this will show the currently selected project configuration
      project_config = false,
    }
  },
  debugger = { -- integrate with nvim dap + install dart code debugger
    enabled = false,
    run_via_dap = false, -- use dap instead of a plenary job to run flutter apps
    -- if empty dap will not stop on any exceptions, otherwise it will stop on those specified
    -- see |:help dap.set_exception_breakpoints()| for more info
    exception_breakpoints = {}
    register_configurations = function(paths)
      require("dap").configurations.dart = {
        <put here config that you would find in .vscode/launch.json>
      }
    end,
  },
  flutter_path = "<full/path/if/needed>", -- <-- this takes priority over the lookup
  flutter_lookup_cmd = nil, -- example "dirname $(which flutter)" or "asdf where flutter"
  root_patterns = { ".git", "pubspec.yaml" }, -- patterns to find the root of your flutter project
  fvm = false, -- takes priority over path, uses <workspace>/.fvm/flutter_sdk if enabled
  widget_guides = {
    enabled = false,
  },
  closing_tags = {
    highlight = "ErrorMsg", -- highlight for the closing tag
    prefix = ">", -- character to use for close tag e.g. > Widget
    enabled = true -- set to false to disable
  },
  dev_log = {
    enabled = true,
    notify_errors = false, -- if there is an error whilst running then notify the user
    open_cmd = "tabedit", -- command to use to open the log buffer
  },
  dev_tools = {
    autostart = false, -- autostart devtools server if not detected
    auto_open_browser = false, -- Automatically opens devtools in the browser
  },
  outline = {
    open_cmd = "30vnew", -- command to use to open the outline buffer
    auto_open = false -- if true this will open the outline automatically when it is first populated
  },
  lsp = {
    color = { -- show the derived colours for dart variables
      enabled = false, -- whether or not to highlight color variables at all, only supported on flutter >= 2.10
      background = false, -- highlight the background
      background_color = nil, -- required, when background is transparent (i.e. background_color = { r = 19, g = 17, b = 24},)
      foreground = false, -- highlight the foreground
      virtual_text = true, -- show the highlight using virtual text
      virtual_text_str = "โ– ", -- the virtual text character to highlight
    },
    on_attach = my_custom_on_attach,
    capabilities = my_custom_capabilities -- e.g. lsp_status capabilities
    --- OR you can specify a function to deactivate or change or control how the config is created
    capabilities = function(config)
      config.specificThingIDontWant = false
      return config
    end,
    -- see the link below for details on each option:
    -- https://github.com/dart-lang/sdk/blob/master/pkg/analysis_server/tool/lsp_spec/README.md#client-workspace-configuration
    settings = {
      showTodos = true,
      completeFunctionCalls = true,
      analysisExcludedFolders = {"<path-to-flutter-sdk-packages>"},
      renameFilesWithClasses = "prompt", -- "always"
      enableSnippets = true,
      updateImportsOnRename = true, -- Whether to update imports and other directives when files are renamed. Required for `FlutterRename` command.
    }
  }
}

You can override any options available in the lspconfig setup, this call essentially wraps it and adds some extra flutter specific handlers and utilisation options.

NOTE: By default this plugin excludes analysis of the packages in the flutter SDK. If for example you jump to the definition of StatelessWidget, the lsp will not try and index the 100s (maybe 1000s) of files in that directory. If for some reason you would like this behaviour set analysisExcludedFolders = {} You cannot/should not edit the files in the sdk directly so diagnostic analysis of these file is pointless.

Exclude Note for Windows: To ignore packages installed with pub, consider adding vim.fn.expand("$HOME/AppData/Local/Pub/Cache") to analysisExcludedFolders if you are using PowerShell.

Project Configuration

It is possible to configure how each project is run using neovim's exrc functionality (see :help exrc). This allows you to create an exrc file e.g. .nvim.lua and put the project configurations inside it. This is similar conceptually to vscode's launch.json file.

-- .nvim.lua
-- If you have more than one setup configured you will be prompted when you run
-- your app to select which one you want to use
require('flutter-tools').setup_project({
  {
    name = 'Development', -- an arbitrary name that you provide so you can recognise this config
    flavor = 'DevFlavor', -- your flavour
    target = 'lib/main_dev.dart', -- your target
    device = 'pixel6pro', -- the device ID, which you can get by running `flutter devices`
    dart_define = {
      API_URL = 'https://dev.example.com/api',
      IS_DEV = true,
    },
    dart_define_from_file = 'config.json' -- the path to a JSON configuration file
  },
  {
    name = 'Web',
    device = 'chrome',
    flavor = 'WebApp',
    web_port = 4000
  },
  {
    name = 'Profile',
    flutter_mode = 'profile', -- possible values: `debug`, `profile` or `release`, defaults to `debug`
  }
})

you can also specify the configuration as an object if there is only one

require('flutter-tools').setup_project({
  name = 'Development',
  flavor = 'DevFlavor',
  device = 'pixel6pro',
  target = 'lib/main_dev.dart',
  dart_define = { ... },
  dart_define_from_file = 'config.json'
})

Flutter binary

In order to run flutter commands you might need to pass either a path or a command to the plugin so it can find your installation of flutter. Most people will not need this since it will find the executable path of flutter if it is in your $PATH.

If using something like asdf or some other version manager or in some other custom way, then you need to pass in a command by specifying flutter_lookup_cmd = <my-command>. If you have a full path already you can pass it in using flutter_path.

If you are on linux and using snap, this plugin will automatically set the flutter_lookup_cmd to flutter sdk-path which allows finding snap installations of flutter. If this doesn't work for any reason likely an old version of flutter before this command was added, you can set your flutter_path to "<INSERT-HOME-DIRECTORY>/snap/flutter/common/flutter/bin/flutter" which is where this is usually installed by snap.

Highlights

Highlight groups that are user configurable to change the appearance of certain UI elements.

  • FlutterToolsOutlineIndentGuides - indent guides for the outline window

Widget guides

To configure the highlight colour you can override the FlutterWidgetGuides highlight group.

Statusline decorations

You can add metadata about the flutter application to your statusline using the g:flutter_tools_decorations dictionary that is created if you have set any of the decorations to true in your configuration.

The currently supported decorations are:

  • App version - The current version of the app from the pubspec.yaml.
  • Device - the device passed to the flutter run command

To add them to your config you can do something like

function _G.statusLine()
  return vim.g.flutter_tools_decorations.app_version
end
vim.opt.statusline ='%!v:statusLine()'

see :h statusline for more information on how to create a statusline.

Telescope Integration

telescope picker

You can list available commands in this plugin using telescope.nvim.

In order to set this up, you can explicitly load the extension.

require("telescope").load_extension("flutter")

Or alternatively telescope can lazy load extension but the Telescope command will not autocomplete lazy loaded modules.

This can be accessed using Telescope flutter commands or require('telescope').extensions.flutter.commands()

FVM

telescope fvm

If you have fvm installed and enabled in your config, you can change your Flutter SDK via a Telescope picker.

This can be accessed using Telescope flutter fvm or require('telescope').extensions.flutter.fvm()

Debugging

Requires nvim-dap

-- with packer
use 'mfussenegger/nvim-dap'

This plugin integrates with nvim-dap to provide debug capabilities. Currently if debugger.enabled is set to true in the user's config it will expect nvim-dap to be installed. If dap is this plugin will use flutter or dart native debugger to debug your project.

To use the debugger you need to run :lua require('dap').continue()<CR>. This will start your app. You should then be able to use dap commands to begin to debug it. For more information on how to use nvim-dap please read the project's README or see :h dap. Note that running the app this way will prevent commands such as :FlutterRestart, :FlutterReload from working.

Alternatively, if you prefer always running your app via dap, you can set debugger.run_via_dap = true in your config. This way you benefit from the debugging abilities of DAP, AND you can still use :FlutterRestart, :FlutterReload, etc.

You can use the debugger.register_configurations to register custom runner configuration (for example for different targets or flavor). If your flutter repo contains launch configurations in .vscode/launch.json you can use them via this config :

  debugger = {
    enabled = true,
    register_configurations = function(_)
      require("dap").configurations.dart = {}
      require("dap.ext.vscode").load_launchjs()
    end,
  },

Since there is an overlap between this plugin's log buffer and the repl buffer when running via dap, you may use the dev_log.enabled configuration option if you want.

Also see:

  • nvim-dap-ui - a plugin which provides a nice UI for nvim-dap.

FAQ

The LSP isn't starting what do I do?

One of the commonest reasons this happens is that for some reason your local flutter binary either can't be found or is throwing an error. You can see the output of this by checking the lsp logs. You can do this by running

:lua vim.cmd('edit '..vim.lsp.get_log_path())<CR>

This will open your lsp logs. You can then check for any error messages.

flutter-tools.nvim's People

Contributors

akinsho avatar andersevenrud avatar bjornevik avatar bruce3x avatar ch-vik avatar changyiyao avatar charly6596 avatar clement-buchart avatar fallenangel97 avatar github-actions[bot] avatar huylg avatar igorkhramtsov avatar igorlfs avatar jidn avatar joshpetit avatar leoncruz avatar letavocado avatar m-salman-a avatar mahanrahmati avatar mikeborodin avatar muzaffar-omer avatar nank1ro avatar nghialm269 avatar rlch avatar robertbrunhage avatar sidlatau avatar simrat39 avatar singalhimanshu avatar thesmader avatar wancup avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flutter-tools.nvim's Issues

Fix overlapping notification windows

Currently when multiple notifications are open they all open in the same position. Instead new windows should check the co-ordinates of the last window and adjust where they open based on that

Clear pending jobs when user quits running flutter

This was raised in #13 that currently a user cannot, stop running flutter and restart it. This will be because the reference to the old job is still present and not cleared yet so a new job can start. To fix this I need to clear the job when the quit command is called. Also if the command exits for any reason this should also trigger the job being cleared.

flutter outline causes performance issue on large widget tree

Hi,

With flutter_outline enabled, when I open a file with large widget tree, the flutter outline takes a long time to draw, after that my neovim starts to lag: inserting text/auto completion becomes slow, cursor moving also gets lag, ...

Reproduce:

  1. Create a new project:
flutter create bug
cd bug
  1. Edit lib/main.dart:
Click to expand
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, this.title}) : super(key: key);

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String? title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      // This call to setState tells the Flutter framework that something has
      // changed in this State, which causes it to rerun the build method below
      // so that the display can reflect the updated values. If we changed
      // _counter without calling setState(), then the build method would not be
      // called again, and so nothing would appear to happen.
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title!),
      ),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Column(
          // Column is also a layout widget. It takes a list of children and
          // arranges them vertically. By default, it sizes itself to fit its
          // children horizontally, and tries to be as tall as its parent.
          //
          // Invoke "debug painting" (press "p" in the console, choose the
          // "Toggle Debug Paint" action from the Flutter Inspector in Android
          // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
          // to see the wireframe for each widget.
          //
          // Column has various properties to control how it sizes itself and
          // how it positions its children. Here we use mainAxisAlignment to
          // center the children vertically; the main axis here is the vertical
          // axis because Columns are vertical (the cross axis would be
          // horizontal).
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'You have pushed the button this many times:',
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}
  1. Open lib/main.dart in neovim with flutter_outline = true.

Fix flutter widget guides for parent widgets

The current implementation of flutter guides doesn't correctly show guide lines which cover multiple child widgets. Instead the guide lines end at the first child.

goal

image

current state

image

Add prompt to name when extracting widget, local variable or method

Another idea inspired by coc-flutter, is to intercept code actions such that when a user selects wrap with widget extract widget or extract method we can show the user a prompt to collect the name to use and send that with the code action request.

I'm not sure how easy the idea of intercepting lsp actions is but this will be similar to how #38 is implemented in the end. There is also some prior art in coc-flutter but it won't really work exactly the same given the different underlying mechanics

Make flutter path configurable

Some flutter installations such as using snap on ubuntu don't get automatically picked up whilst running flutter <command> using nvim's job start. Allow a user to specify the flutter path in their config. Technically this is already possible by specifying a different command in the lsp config but make it more explicit so it can be used throughout this project

Bad argument #2 to 'join'

On MS Windows when open Neovim always shows this error message:

Captura de Tela 2021-05-06 aฬ€s 09 32 36

Any idea about what can be?

Thanks in advance.

[Question] best integreted with external snippet `vsnip`

i'm use

akinsho/flutter-tools.nvim
hrsh7th/vim-vsnip
Neevash/awesome-flutter-snippets

for snippet and lsp , because i cant use lsp only for build widget as StatefulWidget ,
but i can't now use vsnip and this plugin akinsho/flutter-tools.nvim ,
because lsp give me ton of suggestion at the end i see vsnip suggestion

  • how i can handle snippet/lsp
  • why i cant use snippet of widget from lsp without snippet

Fix complete function calls and expand methods and function calls

One very nice thing that coc-flutter does it that it converts completions like function(...) into actual snippets that a user can then use their completion plugin to expand. It actually does this manually here. It intercepts the completion handler and changes certain results into snippets. It would be nice to implement something similar.

One consideration though is that the dart lsp recently added a completeFunctionCalls which is a native way with the lsp to do a similar thing i.e. it will fill in the arguments for a function or method call. This doesn't work out of the box though with nvim lsp not sure why

Invalid border style: "rounded"

image
I'm getting that error after updating, caused by this default config value

I'm using NVIM v0.5.0-dev+1311-gf8173df4d
Probably rounded was added in a later version?

Not a big deal. Changing it to anything listed in :h nvim_open_with() solves it. (shadow for example)
It would be nice to have something in the readme mentioning it, for those having this issue in the future.

Error with `flutter_outline` enabled

Hi,
with the option flutter_outline enabled, I have this error message that shows up when I insert a new line under a widget for example:

Error executing vim.schedule lua callback: ...s/start/flutter-tools.nvim/lua/flutter-tools/outline.lua:484: attempt to perform arithmetic on local 'index' (a nil value)  

Here's my configuration for flutter-tools:

local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities.textDocument.completion.completionItem.snippetSupport = true

require("flutter-tools").setup {
  flutter_outline = {
    enabled = true
  },
  lsp = {
    capabilities = capabilities
  }
}

This message only appears if I edit lines where the outline is visually set.

I used the starter flutter project to test it.

Thanks!

Open devtools in the browser automatically

  • Open devtools in the browser automatically whenever the server is detected (we either have devtools_url and profiler_url or devtools_profiler_url available)
  • This should be configurable, add an option to opt-out

See #44 (comment) for more context.

Possibility to define custom dartls command

Since it's not recommended using lspconfig in conjunction with dartls when using this plugin, I'm wondering about situations where you have a plain Dart codebase (no Flutter) that depends on an a specific version of Dart and not the one provided in the Flutter SDK.

I'm not sure if this is a real problem (maybe more like a question of if this setup can cause any issues relating to it), but thought I'd open an issue on it anyways because this came to mind during #30 when I was messing around with settings trying to override the dartls cmd like this:

require("flutter-tools").setup {
  lsp = {
    cmd = { "some", "custom", "path", "outside", "flutter", "sdk" }
  }
}

User's configuration is not taken into account when getting sdk path

Hi,
Thanks for the great plugin.

After this commit b5fcd4b, I wasn't able to set my own flutter_lookup_cmd anymore.

I tried to put vim.notify(vim.inspect(_config)) after this line, and I don't see my configuration in the output.
I also tried vim.notify(vim.inspect(require("flutter-tools/config").get())) there but still not see my configuration.

It seems like the user configuration is lost. I tried to fix it but my lua is not good enough.

My configuration:

require'flutter-tools'.setup{
  experimental = {
    lsp_derive_paths = true,
  },
  flutter_lookup_cmd = "asdf where flutter",
  flutter_outline = {
    highlight = "NonText",
    enabled = true,
  },
  closing_tags = {
    highlight = "Comment",
    prefix = "-- "
  },
  dev_log = {
    open_cmd = "tabedit",
  },
  outline = {
    open_cmd = "30vnew",
  },
  lsp = {
    on_attach = on_attach,
    capabilities = capabilities,
  }
}

(btw there are some typos in the readme: derive_lsp_paths -> lsp_derive_paths, asdf which flutter -> asdf where flutter)

Issues with lspsga

Hey @akinsho, I got around to experiment with flutter, and I'm so glad you have worked an development environment for it.

There some issue that break float window and some features related to lspsaga code actions, If you are still using can you take a look.

Thanks

How to enable auto complete

Can you provide any working config file for enabling auto complete ?
It shows name of widget and classes but doesn't generate any code snippets.

Unable to Launch Emulators from FlutterEmulators

I can see the emulators when executing Flutter emulators.
image
But pressing enter on either option does nothing. No error messages. Nothing. The window just stays where it is. I can continue to scroll through the options but nothing happens.

These are the android tools I am using
image

And here is the flutter package I am using
image

Running emulator @default on the command line does work.
image

If there's anything more I can provide, please let me know!

Lagging when navigating Flutter SDK

This may not be related to flutter-tools but instead https://github.com/hrsh7th/nvim-compe but would love to hear if you have a solution for it.

When navigating the Flutter source code, it starts lagging immensely which I think is related to how there are errors everywhere and this also hinders navigating deeper in the SDK, for example navigating to StatefulWidget from here.
image

Do you have this issue? Or do you have any specific configurations done to not get errors when navigating the Flutter SDK?

Support custom sdk paths

First of all thank you for this great job. This is a very promising plugin.
I'm having headaches, though, to make the language server to work. Flutter commands are working fine, but LSP doesn't.

When I check the LSP log it is complaining about the dart snapshot. I'll still check yet, but I suspect that is caused by the fact that I have Dart inside Flutter SDK and also standalone.

That being said, I'd like to be able to select the SDK folder (instead of the flutter path only) to make sure the plugin is invoking the analysis server I want.

not connecting to dartls

I'm having problem with not connecting to lsp.

if O.lang.dart.flutter_tools.active then
  require('flutter-tools').setup{}
else
  require("lspconfig").dartls.setup {
    cmd = { "dart", O.lang.dart.sdk_path, "--lsp" },
    on_attach = require("lsp").common_on_attach,
    init_options = {
      closingLabels = false,
      flutterOutline = false,
      onlyAnalyzeProjectsWithOpenFiles = false,
      outline = false,
      suggestFromUnimportedLibraries = true,
    },
  }
end
  use {
    "akinsho/flutter-tools.nvim",
    requires = "nvim-lua/plenary.nvim",
    disable = not O.lang.dart.flutter_tools.active,
  }

I have flutter set in $PATH so I just left it default.
It worked once before but for some reason it stopped working.

not working/initialize

the plugin not initializing automatically(LSP,Closing Tags,Outline window) then I run

:FlutterDevTools

I receve this error

flutter-tools.nvim/lua/flutter-tools/dev_tools.lua:12: bad argument #1 to 'ipairs' (table expected, got number)

same result on both linux and windows

linux neovim version:

0.5.0-dev+1101

windows neovim version:

0.5.0-dev+1099

plugin manager:

paq-nvim

my config(init.lua):

https://github.com/tredeneo/configs/blob/main/init.lua

Lsp rename,delete and create file

Investigate whether dart's lsp supports updating imports and renaming imports using the lsp. This was added to neovim recently for use in nvim-jdtls. I'd like to find out if this can also be used here.

outline.lua error

i just install the plugin with vim-plug and initialize it using default setting, but i get this message.

Error detected while processing /home/syarif/.dotfiles/config/nvim/init.vim: line   19:
E5113: Error while calling lua chunk: vim.lua:129: ...plugged/flutter-tools.nvim/lua/flutter-tools/outline.lua:46: invalid escape sequence near '"'

Integrate with nvim-dap

Integrate nvim-dap so users can debug easily after setting up this plugin.
Will require some thinking around how to source the dart debugger and integrate it here

Closing Tags, Widget guides and Outline Window not working

The Cloasing Tags don't show up. The Widget guides as well, Even though I explicitly set them to true in my config as follows:
widget_guides = {
enabled = true,
},

Also, When trying to open the Flutter outline :FlutterOutline it says:
"Sorry There's no outline for this file. "
I did try them with different files and in different projects.

lsp_derive_paths does not work anymore

Hi,
After commit b9e707a, lsp_derive_paths feature does not work for me anymore.

The result of the res variable here

local res = result[1]
if res then
local flutter_sdk_path = utils.remove_newlines(res)

is "/home/nghialm/.asdf/installs/flutter/2.0.4-stable/home/nghialm/.asdf/installs/flutter/2.0.4-stable" (the result is duplicated)

I put some print statements to help debug:

diff --git a/lua/flutter-tools/job.lua b/lua/flutter-tools/job.lua
index 1fdb99a..50a558a 100644
--- a/lua/flutter-tools/job.lua
+++ b/lua/flutter-tools/job.lua
@@ -77,6 +78,8 @@ end
 ---stderr or stdout with only a single line
 function Job:__process_result(_, data, name)
   if data and type(data) == "table" then
+    print(vim.inspect(self))
+    print("JOB DATA: "..name.." data: "..vim.inspect(data))
     if data[#data] == "" then
       data[#data] = nil
     end

Here is the result:

{
  cmd = "asdf where flutter",
  id = 3,
  on_exit = <function 1>,
  on_stderr = <function 2>,
  <metatable> = <1>{
    __index = <table 1>,
    __is_alive = <function 3>,
    __make_args = <function 4>,
    __process_result = <function 5>,
    __set_status = <function 6>,
    close = <function 7>,
    new = <function 8>,
    result = { "" },
    send = <function 9>,
    start = <function 10>,
    status = 0,
    sync = <function 11>
  }
}
JOB DATA: stdout data: { "/home/nghialm/.asdf/installs/flutter/2.0.4-stable", "" }
{
  cmd = "asdf where flutter",
  id = 3,
  on_exit = <function 1>,
  on_stderr = <function 2>,
  <metatable> = <1>{
    __index = <table 1>,
    __is_alive = <function 3>,
    __make_args = <function 4>,
    __process_result = <function 5>,
    __set_status = <function 6>,
    close = <function 7>,
    new = <function 8>,
    result = { "/home/nghialm/.asdf/installs/flutter/2.0.4-stable" },
    send = <function 9>,
    start = <function 10>,
    status = 0,
    sync = <function 11>
  }
}
JOB DATA: stderr data: { "" }

{
  cmd = "asdf where flutter",
  id = 4,
  on_exit = <function 1>,
  on_stderr = <function 2>,
  <metatable> = <1>{
    __index = <table 1>,
    __is_alive = <function 3>,
    __make_args = <function 4>,
    __process_result = <function 5>,
    __set_status = <function 6>,
    close = <function 7>,
    new = <function 8>,
    result = { "/home/nghialm/.asdf/installs/flutter/2.0.4-stable" },
    send = <function 9>,
    start = <function 10>,
    status = 0,
    sync = <function 11>
  }
}
JOB DATA: stdout data: { "/home/nghialm/.asdf/installs/flutter/2.0.4-stable", "" }
{
  cmd = "asdf where flutter",
  id = 4,
  on_exit = <function 1>,
  on_stderr = <function 2>,
  <metatable> = <1>{
    __index = <table 1>,
    __is_alive = <function 3>,
    __make_args = <function 4>,
    __process_result = <function 5>,
    __set_status = <function 6>,
    close = <function 7>,
    new = <function 8>,
    result = { "/home/nghialm/.asdf/installs/flutter/2.0.4-stable/home/nghialm/.asdf/installs/flutter/2.0.4-stable" },
    send = <function 9>,
    start = <function 10>,
    status = 0,
    sync = <function 11>
  }
}
JOB DATA: stderr data: { "" }

It seems like the function is called twice, and although the two jobs have different job ids, the result table is shared between them.

Update README screenshots

It's not possible to see all the commands as shown in the picture anymore and might confuse some people
image

Fix extract widget code action (+/- others)

Since moving the native lsp from coc-flutter I've noticed that the extract widget code action that dart supplies for flutter doesn't seem to work anymore. I don't know if this is due to a missing lsp capability we need to send that coc sends, or if there is an error in executing the code action that is just not being reported.

Potential solutions:

  1. Debug the code action by overriding the handler, triggering it and seeing if it is erroring.
  2. Check coc/dart's lsp docs to see if we are missing a capability

dartls won't run without setting $PATH

If I don't explicitly add the Flutter bin directory to $PATH I get the following error:

Client 1 quit with exit code 64 and signal 0

This is using the following setup (I tried adding the executable name there too as well as some other combinations, with same result):

require'flutter-tools'.setup{
    flutter_path = '/mnt/ssd-data/flutter/bin'
}

If I start a new terminal session, update the $PATH, then confirm it:

**bunch of paths**:/mnt/ssd-data/flutter/bin

Then launch neovim, everything works like expected.

Autostart devtools

Currently, if the plugin doesn't detect the complete devtools url from the flutter run console output (the one including devtools server and app url) we would need to start the devtools server manually.
Would be nice to have a configurable option to autostart the server if the plugin doesn't detect it.
This happens when running web.

For more context, see #44 (comment) and #44 (comment)

Flutter sdk is not starting

this is my config init.lua config

require'lspconfig'.dartls.setup{
  filetypes = {"dart"},
  init_options = {
    closingLabels = false,
    flutterOutline= true,
    onlyAnalyzeProjectsWithOpenFiles = false,
    outline=false,
    suggestFromUnimportedLibraries = true,
  }
}

require("flutter-tools").setup {
  experimental = { -- map of feature flags
    lsp_derive_paths = false, -- experimental: Attempt to find the user's flutter SDK
  },
  debugger = { -- experimental: integrate with nvim dap
    enabled = false,
  },
  flutter_path = "/opt/flutter/bin/flutter", -- <-- this takes priority over the lookup
  flutter_lookup_cmd = 'flutter', -- example "dirname $(which flutter)" or "asdf where flutter"
  widget_guides = {
    enabled = false,
  },
  closing_tags = {
    highlight = "ErrorMSG",
    prefix = ">",
    enabled = true,
  },
  dev_log = {
    open_cmd = "tabedit", -- command to use to open the log buffer
  },
  outline = {
    open_cmd = "30vnew", -- command to use to open the outline buffer
  },
  lsp = {
    settings = {
      showTodos = true,
      completeFunctionCalls = true,
    }
  }
}

require("telescope").load_extension("flutter")

Untitled

provide example config

Would be nice to see an example config for how to get this up and running with Flutter.

I am personally using coc-flutter but would love to move to this, but having a hard to getting everything working, such as autocomplete, error messages and so on.

p.s. Great work and keep it up ๐Ÿ˜Š

:FlutterRun fails on windows

Hi.
I found that :FlutterRun fails on windows with this error.

E5108: Error executing lua ...\site\pack\packer\start\plenary.nvim\lua\plenary\job.lua:400: Failed to spawn process: {
  _additional_on_exit_callbacks = {},
  _shutdown_check = <userdata 1>,
  _stderr_results = {},
  _stdout_results = {},
  _user_on_exit = <function 1>,
  _user_on_stderr = <function 2>,
  _user_on_stdout = <function 3>,
  args = { "run" },
  command = "C:\\flutter\\bin\\flutter",
  enable_handlers = true,
  enable_recording = true,
  interactive = true,
  pid = "ENOENT: no such file or directory",
  stderr = <userdata 2>,
  stdin = <userdata 3>,
  stdout = <userdata 4>,
  user_data = {},
  <metatable> = <1>{
    __index = <table 1>,
    _create_uv_options = <function 4>,
    _execute = <function 5>,
    _pipes_are_closed = <function 6>,
    _prepare_pipes = <function 7>,
    _reset = <function 8>,
    _shutdown = <function 9>,
    _stop = <function 10>,
    add_on_exit_callback = <function 11>,
    after = <function 12>,
    after_failure = <function 13>,
    after_success = <function 14>,
    and_then = <function 15>,
    and_then_on_failure = <function 16>,
    and_then_on_failure_wrap = <function 17>,
    and_then_on_success = <function 18>,
    and_then_on_success_wrap = <function 19>,
    and_then_wrap = <function 20>,
    chain = <function 21>,
    chain_status = <function 22>,
    co_wait = <function 23>,
    is_job = <function 24>,
    join = <function 25>,
    new = <function 26>,
    pid = <function 27>,
    result = <function 28>,
    send = <function 29>,
    shutdown = <function 30>,
    start = <function 31>,
    stderr_result = <function 32>,
    sync = <function 33>,
    wait = <function 34>
  }
}

The executable file name for flutter in windows is flutter.bat, but flutter is running, which is probably causing this problem.

FlutterRun custom flags

I'm working on an app with different mains to support various flavors (development and production).
I need the --target and --flavor flags.

I could implement this with a flags variable in commands.lua and making a command to set its value. Suggestions welcomed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.