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.