CodeField
A customizable code text field supporting syntax highlighting
Live demo
A live demo showcasing a few language / themes combinaisons
Showcase
The experimental VM dlox uses CodeField in its online editor
Features
- Code highlight for 189 built-in languages with 90 themes thanks to flutter_highlight
- Easy language highlight customization through the use of theme maps
- Fully customizable code field style through a TextField like API
- Handles horizontal/vertical scrolling and vertical expansion
- Supports code modifiers
- Works on Android, iOS, and Web
Code modifiers help manage indents automatically
The editor is wrapped in a horizontal scrollable container to handle long lines
Installing
In the pubspec.yaml
of your flutter project, add the following dependency:
dependencies: ... code_text_field: <latest_version>
In your library add the following import:
import 'package:code_text_field/code_field.dart';
Simple example
A CodeField widget works with a CodeController which dynamically parses the text input according to a language and renders it with a theme map
import 'package:flutter/material.dart'; import 'package:code_text_field/code_field.dart'; // Import the language & theme import 'package:highlight/languages/dart.dart'; import 'package:flutter_highlight/themes/monokai-sublime.dart'; class CodeEditor extends StatefulWidget { @override _CodeEditorState createState() => _CodeEditorState(); } class _CodeEditorState extends State<CodeEditor> { CodeController? _codeController; @override void initState() { super.initState(); final source = "void main() {\n print(\"Hello, world!\");\n}"; // Instantiate the CodeController _codeController = CodeController( text: source, language: dart, theme: monokaiSublimeTheme, ); } @override void dispose() { _codeController?.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return CodeField( controller: _codeController!, textStyle: TextStyle(fontFamily: 'SourceCode'), ); } }
Here, the monospace font Source Code Pro has been added to the assets folder and to the pubspec.yaml file
Parser options
On top of a language definition, world-wise styling can be specified in the stringMap field
_codeController = CodeController( //... stringMap: { "Hello": TextStyle(fontWeight: FontWeight.bold, color: Colors.red), "world": TextStyle(fontStyle: FontStyle.italic, color: Colors.green), }, );
More complex regexes may also be used with the patternMap. When a language is used though, its regexes patterns take precedence over patternMap and stringMap.
_codeController = CodeController( //... patternMap: { r"\B#[a-zA-Z0-9]+\b": TextStyle(fontWeight: FontWeight.bold, color: Colors.purpleAccent), }, );
Both patternMap and stringMap can be used without specifying a language
_codeController = CodeController( text: source, patternMap: { r'".*"': TextStyle(color: Colors.yellow), r'[a-zA-Z0-9]+\(.*\)': TextStyle(color: Colors.green), }, stringMap: { "void": TextStyle(fontWeight: FontWeight.bold, color: Colors.red), "print": TextStyle(fontWeight: FontWeight.bold, color: Colors.blue), }, );
Code Modifiers
Code modifiers can be created to react to special keystrokes. The default modifiers handle tab to space & automatic indentation. Here’s the implementation of the default TabModifier
class TabModifier extends CodeModifier { const TabModifier() : super('\t'); @override TextEditingValue? updateString( String text, TextSelection sel, EditorParams params) { final tmp = replace(text, sel.start, sel.end, " " * params.tabSpaces); return tmp; } }
API
CodeField
CodeField({ Key? key, required this.controller, this.minLines, this.maxLines, this.expands = false, this.wrap = false, this.background, this.decoration, this.textStyle, this.padding = const EdgeInsets.symmetric(), this.lineNumberStyle = const LineNumberStyle(), this.cursorColor, this.textSelectionTheme, this.lineNumberBuilder, this.focusNode })
LineNumberStyle({ this.width = 42.0, this.textAlign = TextAlign.right, this.margin = 10.0, this.textStyle, this.background, })
CodeController
CodeController({ String? text, this.language, this.theme, this.patternMap, this.stringMap, this.params = const EditorParams(), this.modifiers = const <CodeModifier>[ const IntendModifier(), const CloseBlockModifier(), const TabModifier(), ], })
Limitations
- Autocomplete disabling on android doesn’t work yet
- The TextField cursor doesn’t seem to be handling space inputs properly on the web platform. Pending issue resolution. The flag
webSpaceFix
fixes it by swapping spaces with transparent middle points.
Notes
A breaking change to the TextEditingController
was introduced in flutter beta, dev & master channels. The branch beta should comply with those changes.
Download customizable code text field widget source code on GitHub
Provides the list of the opensource Flutter apps collection with GitHub repository.