NFlutter acts as a powerful code generator, transforming concise NFlutter code into standard Dart (gen.dart file), optimizing the creation of Flutter widgets and nesting structures.
Drawing inspiration from indentation based languages, NFlutter simplifies syntax by eliminating brackets and commas, making Flutter/Dart development more intuitive and efficient.
Ideal for developers focused on productivity and code clarity in Flutter projects.
Initially, NFlutter stood for ‘No brackets, No commas’, or ‘No distractions’, emphasizing its goal to eliminate syntactical clutter. However, over time, it has come to represent ‘Neat Flutter’, reflecting its effectiveness in creating neat and clean code.
Fluent, Clutter-Free Syntax: A streamlined approach to coding that reduces the need for excessive syntactical elements.
Dual-Language Support: Offers seamless integration with the standard Dart language.
Easy Widget Editing: Simplifies the process of editing widgets in Flutter.
No Vendor Lock: NFlutter generates regular Dart source files, ensuring compatibility and flexibility.
Generated Code Preview Panel: Allows developers to view the Dart code generated from NFlutter DSL in real-time.
IntelliJ IDE with the Dart plugin installed.
Flutter SDK installed on your system.
Open IntelliJ IDEA.
Navigate to the IntelliJ Marketplace by selecting Menu > File > Settings > Plugins > Marketplace
.
Search for “NFlutter” and install the plugin.
Alternatively, visit IntelliJ Plugins Marketplace online and search for NFlutter.
To start using NFlutter in your project:
In IntelliJ IDEA, navigate to Menu > File > New
.
Select “NFlutter File” (or use the shortcut Ctrl+Alt+N
).
Name your file with a .nf
extension (e.g., simple.nf
).
By following these steps, you’ll have the necessary environment set up to begin developing with NFlutter. The .nf
files you create will allow you to write Flutter code using the NFlutter DSL, which will be automatically transpiled
into Dart code.
This will demonstrate how NFlutter simplifies the Flutter code while maintaining the same functionality.
Create a New NFlutter File:
simple.nf
Write the NFlutter Code:
simple.nf
:import 'package:flutter/material.dart';
class Simple extends StatelessWidget {
@override
Widget build(BuildContext context) {
return <nf>
Column =
children: []=
Text = 'This is NFlutter' maxLines: 2
Text = 'Hello World'
</nf>
}
}
Import Statement: Just like in Dart, we start with importing necessary packages.
Simple Widget: We define a StatelessWidget
named Simple
.
NFlutter Syntax: Inside the build
method, the <nf>
tag indicates the start of NFlutter DSL.
When you save the simple.nf file, NFlutter automatically generates the corresponding Dart code in a simple.gen.dart file.
This Dart file contains the standard Flutter code equivalent to your NFlutter code, which you can run in your Flutter environment.
NFlutter also includes a handy Preview Pane feature to visualize the Dart code generated from your NFlutter code.
To open the NFlutter Preview Pane, go to Menu > View > Tool Windows > NFlutter Preview
This tool window will display the Dart code that corresponds to your NFlutter file.
Understanding the grammar of NFlutter is key to effectively using the DSL. The primary component of this grammar is
the <nf></nf>
Tag.
<nf></nf>
TagMarks the start and end of an NFlutter DSL code section.
The code written within <nf></nf>
is automatically transpiled into Dart code. By default, a semicolon is emitted
at the end of the transpiled Dart code.
Example in NFlutter:
return <nf>
Text = 'hello'
</nf>
return Text('hello');
<nf></nf>
TagThe <nf></nf>
tag is integrated into the auto-completion feature. This integration streamlines the process of
entering NFlutter code blocks.
Usage:
When you start typing nf, the auto-completion option for <nf></nf>
will appear.
Selecting this option will automatically insert the complete <nf></nf>
tag structure into your code.
<nf nosc>
Tag (no semicolon)Purpose: Similar to the <nf>
tag but specifically designed to not emit a semicolon at the end of the Dart code.
Use Case: This variation is useful in scenarios where a semicolon is not needed for example when placed in mid of expression.
<dart></dart>
TagThe <dart></dart>
tag in NFlutter serves a specific purpose within the DSL, allowing the integration of standard Dart
code directly within an NFlutter code section.
Functionality: This tag enables the insertion of pure Dart code within an NFlutter block.
Use Cases: It’s particularly useful for scenarios where Dart-specific syntax or functionality is needed that might not be directly supported or easily expressed in NFlutter.
Selective Use: While the <dart>
tag is available, it’s often not necessary to use it. NFlutter’s seamless
integration with Dart means that in most cases, simply wrapping an expression in brackets will revert to standard Dart
syntax.
Using <dart>
Tag:
Text = <dart> (a > b) ? 'a' : 'b' </dart>
Text = ((a > b) ? 'a' : 'b')
In NFlutter, the equals sign (=
) is used to replace the traditional use of brackets in Dart, simplifying function and
constructor calls. Understanding how to use =
is crucial for writing concise and readable NFlutter code.
Replacement for Brackets: In NFlutter, instead of wrapping arguments with brackets, you use the =
sign.
Automatic Bracket Placement: NFlutter automatically places an opening bracket at the position of =
and determines
where to place the closing bracket based on the placement of arguments.
There are two ways to place arguments relative to the =
sign:
Arguments are placed on the same line as the =
sign.
Each argument is separated by a space.
The closing bracket is automatically placed at the end of the line.
Example:
Text = 'This is NFlutter' maxLines: 2
Arguments are placed on a new line after the =
sign and are indented.
The closing bracket is placed at the end of the indented block or at the closing of the NFlutter code section.
Example:
Text =
'This is NFlutter'
maxLines: 2
In NFlutter, the ‘[]=’ symbol is used to replace the traditional collection definitions (like lists or arrays) in Dart. Understanding its usage is essential for handling collections efficiently in NFlutter.
Replacement for Collection Brackets: The ‘[]=’ symbol is used in place of square brackets []
to define
collections.
Scope and Indentation: The collection items are defined in a multi-line indented block, where each item is separated by a newline. NFlutter automatically places the opening and closing square brackets based on the indented block.
Multi-Line Indented Arguments Only: The ‘[]=’ symbol supports only multi-line indented arguments. Each new line within the indented block represents an item in the collection.
Example:
Column =
children: []=
Text = 'hello'
Text = 'world'
Using ‘[]=’ for Empty Collections: For defining an empty collection, you can use ‘[]=’ without any following arguments. This will produce an empty collection in the generated Dart code.
Preferred Syntax for Clarity: However, for better clarity, it is recommended to use the standard Dart syntax for defining empty collections.
NFlutter Example: children: []=
Preferred Dart Syntax: children: []
NFlutter allows the use of simple Dart expressions as values for arguments, streamlining the integration of dynamic values within the DSL.
Simple Dart Expressions: These are supported natively within NFlutter syntax, allowing for a fluid and concise coding experience.
Complex Expressions: For more intricate expressions, you can seamlessly transition back to standard Dart syntax.
This can be done by enclosing the expression in brackets or using the <dart></dart>
tag.
Example: (notice the switch to dart by using brackets)
style: Theme.of(context).primaryTextTheme.titleLarge
NFlutter simplifies the inclusion of lambda functions in your code, supporting both arrow and braces styles for lambda syntax.
Arrow Lambda: Ideal for concise, single-expression functions.
Braces Lambda: Suitable for more complex functions that may contain multiple statements.
Example:
//Arrow Lambda
onTap: () => context.go("/page1")
//Braces Lambda
onTap: () { context.go("/page1"); }
NFlutter is designed not just to simplify Flutter development with its own syntax but also to allow effortless integration with standard Dart code. This feature is especially useful in scenarios where the more verbose Dart syntax might be preferred or required.
Automatic Syntax Switching: Inside an NFlutter code section, the grammar automatically switches to Dart when you
open any of the following blocks: ()
, []
, {}
.
Returning to NFlutter: The syntax reverts back to NFlutter once the block is closed. This means you exit the Dart syntax by closing the corresponding block that initiated the switch.
Flexibility: This feature offers the best of both worlds - the simplicity of NFlutter and the full capabilities of Dart. It allows developers to choose the most appropriate syntax for each part of their code.
Column =
children: []=
const Text = 'Welcome to NFlutter'
// Dart block starts
(a > b? const Text('a') : const Text('b'))
// Dart block ends
const Text = 'End of example'
Navigator.of(context, rootNavigator: true).push<void> =
TextStyle = color: Colors.grey[800]
style: TextStyle =
background: (Paint()
..color = Colors.red
..strokeWidth = 20
..strokeJoin = StrokeJoin.round
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke)
IconButton =
icon: const Icon = Icons.search
tooltip: 'Search'
onPressed: () { // Dart block starts
showDialog('Search pressed');
} // Dart block ends
<dart> if(10>11) Text('a') else Text('b') </dart>
NFlutter offers several editing features to facilitate a smoother coding experience, especially when working with its unique syntax.
NFlutter simplifies the process of reordering arguments in a multi-line argument list. This feature is particularly useful when you need to adjust the sequence of widgets or parameters in your Flutter code.
Functionality: In a multi-line argument list within NFlutter code, you can move arguments up and down the list.
IDE Shortcut: The feature is accessible through the IDE’s ‘Move Statement Up/Down’ shortcut.
Ctrl+Shift+ ↑ to move an argument up.
Ctrl+Shift+ ↓ to move an argument down.
Enhancing Code Structure: This feature is invaluable for quickly reorganizing code, ensuring that your widgets and parameters are in the desired order.
Ease of Reformatting: To facilitate the re-indentation of large code blocks, NFlutter allows you to move blocks of code left or right.
How to Use:
Place the caret on a code element.
The operation will include the element under the caret and all indented code elements below it.
Use Alt+Left
to move the block left and Alt+Right
to move it right. \
Transformation: In an NFlutter code section, you can convert single line arguments to multi-line format by
pressing Enter
on any argument.
Note: This feature does not apply to multiline literal strings, as converting these might disrupt their intended format.
Automatic Indentation Fix: When you delete a portion of code in an NFlutter code section, NFlutter attempts to automatically preserve and correct the indentation of the subsequent code.
NFlutter includes a Preview Pane feature to visualize the Dart code generated from your NFlutter code.
The Preview Pane updates as you save your .nf
file.
Instant Feedback: This allows you to instantly see the Dart equivalent of your NFlutter code, which is useful for understanding how NFlutter translates into Dart
To open the NFlutter Preview Pane, go to Menu > View > Tool Windows > NFlutter Preview.
This tool window will display the Dart code that corresponds to your NFlutter file.
NFlutter extends its integration with common IDE features by supporting the Structure view tool window. This functionality is particularly useful for navigating and understanding the hierarchical structure of NFlutter code.
Purpose: The Structure view provides a tree view of the code structure, allowing you to see and navigate to different components of your NFlutter code easily.
Accessing the Tool: You can open the Structure view in most IDEs by navigating
to View > Tool Windows > Structure
or by using the associated shortcut, typically found in the IDE documentation or
settings.
Improved Navigation: Quickly jump to different parts of your code, such as classes, methods, and specific NFlutter widgets, directly from the Structure view.
Enhanced Code Understanding: Get an overview of the entire file’s structure at a glance, making it easier to understand the code’s layout and flow, especially in larger files.
NFlutter supports debugging of Flutter applications using the standard Dart debugger. While it currently does not offer debugging specifically for NFlutter syntax, it fully integrates with Dart debugging tools.
Configuration: To set up debugging, open your project’s Run/Debug configurations.
Steps:
Go to Run > Edit Configurations…
.
Click Add New Configuration
.
Choose NFlutter
.
Select the main Dart file from which to start, the target device, and optionally, any additional * *arguments**.
Note: For a more comprehensive debugging experience, especially for UI and performance aspects, consider using the Flutter plugin alongside NFlutter.
To create a new NFlutter .nf file, navigate to Menu > File > New
. select “NFlutter File” (or use the
shortcut Ctrl+Alt+N
).
Automatic On Save: The primary way to generate Dart code from an NFlutter file is simply by saving the file. When
you save a .nf
file, NFlutter automatically transpiles the code into a corresponding .gen.dart
file.
Manual Trigger Option: In addition to the automatic generation upon saving, you can manually trigger code
generation. This can be done using the keyboard shortcut Ctrl+Shift+G
.
NFlutter’s integration with common IDE features enhances the developer’s experience by streamlining various aspects of coding and navigation.
Here’s some of IDE features that are compatible with NFlutter:
Code Completion
Quick Fix
Code Formatting
Search for Symbol/Class
Find Usages
Goto Reference
Code Folding
Comment/Uncomment
Quotes, Brackets and Braces completion
Spell checking