Lucy_Editor

Lucy_Editor is a powerful lightweight text and code editor widget and a module in the Reqable project. It can be used as a simple text area or to develop a code editor with complex functions. Unlike Flutter's default TextField component, Lucy_Editor is specifically tailored for the display and input of multi-line text and offers the following features:

  • Two-way horizontal and vertical scrolling.
  • Text syntax highlighting.
  • Content collapsing and expanding.
  • Input hints and auto-completion.
  • Search and replace.
  • Custom context menu builder.
  • Shortcut keys.
  • Large text display and editing.
  • Line numbers and focus line builder.
  • Smart input.
  • Improve performance.

Lucy_Editor is not a secondary encapsulation based on TextField, but independently implements the layout, drawing, event processing, etc. It is specifically optimized for large texts, providing extremely high performance and fixed some issues of TextField.

Lucy_Editor offers a high degree of freedom. For example, developers can control whether to enable horizontal scrolling (word wrap), enable read-only mode, display line numbers, display content folding, define custom shortcut keys, and specify text syntax highlighting.

You can run the example project to experience it.

Getting Started

Add the followings in pubspec.yaml.

dependencies:
  lucy_editor: ^1.0.0

Like TextField, Lucy_Editor uses CodeLineEditingController as the controller. The following sample code creates the simplest editor component, which is not much different from TextField.

Widget build(BuildContext context) {
  return CodeEditor(
    controller: CodeLineEditingController.fromText('Hello Reqable'),
  );
}

Text Syntax Highlighting

The text highlighting of Lucy_Editor is based on Re-Highlight and supports nearly a hundred languages ​​and theme styles. Developers can freely choose and configure the code Highlight. The following code specifies the JSON syntax highlighting rules and applies the Atom One Light code coloring.

CodeEditor(
  style: CodeEditorStyle(
    codeTheme: CodeHighlightTheme(
      languages: {
        'json': CodeHighlightThemeMode(
          mode: langJson
        )
      },
      theme: atomOneLightTheme
    ),
  ),
);

Line Numbers and Fold/Unfold Markers

Lucy_Editor supports configuring whether to display code line numbers and code folding marks, and developers can also implement display styles and layouts by themselves. The example code below shows the default style, built with indicatorBuilder.

CodeEditor(
  indicatorBuilder: (context, editingController, chunkController, notifier) {
    return Row(
      children: [
        DefaultCodeLineNumber(
          controller: editingController,
          notifier: notifier,
        ),
        DefaultCodeChunkIndicator(
          width: 20,
          controller: chunkController,
          notifier: notifier
        )
      ],
    );
  },
);

Code Folding and Unfolding Detection

By default, Lucy_Editor will automatically detect the folding areas of {} and []. Developers can control whether to detect or write their own detection rules. DefaultCodeChunkAnalyzer is the default detector. If you wish to disable detection, you can use NonCodeChunkAnalyzer.

CodeEditor(
  chunkAnalyzer: DefaultCodeChunkAnalyzer(),
);

If you want to customize it, just implement the CodeChunkAnalyzer interface.

abstract class CodeChunkAnalyzer {

  List<CodeChunk> run(CodeLines codeLines);

}

Scroll Control

Lucy_Editor supports two-way scrolling, so two ScrollController are used, and developers can use CodeScrollController to construct.

CodeEditor(
  scrollController: CodeScrollController(
    verticalScroller: ScrollController(),
    horizontalScroller: ScrollController(),
  )
);

Find and Replace

Lucy_Editor implements search and replace control logic, but does not provide a default UI. Developers need to write the UI of the search panel according to the actual situation of their own projects, and use the findBuilder attribute to set up their own search and replace UI.

CodeEditor(
  findBuilder: (context, controller, readOnly) => CodeFindPanelView(controller: controller, readOnly: readOnly),
);

The CodeFindPanelView in the above example is implemented by the developer himself. For the detailed implementation process, please refer to the code in example.

Context Menu

Lucy_Editor implements the control logic of the desktop context menu and the mobile long-press selection menu, but does not provide a default UI. Developers need to implement the SelectionToolbarController interface and setup it through toolbarController.

CodeEditor(
  toolbarController: _MyToolbarController(),
);

Shortcuts

Lucy_Editor has the built-in default shortcut hotkeys, and developers can also use shortcutsActivatorsBuilder to set custom shortcut hotkeys. Of course, the shortcut keys only work on the desktop.

The shortcut keys supported by Lucy_Editor are as follows:

  • Select all (Control/Command + A)
  • Cut selected/current line (Control/Command + V)
  • Copy selected/current line (Control/Command + C)
  • Paste (Control/Command + V)
  • Undo (Control/Command + Z)
  • Redo (Shift + Control/Command + Z)
  • Select the current line (Control/Command + L)
  • Delete current line (Control/Command + D)
  • Move current line (Alt + ↑/↓)
  • Continuous selection (Shift + ↑/↓/←/→)
  • Move cursor (↑/↓/←/→)
  • Move to top/bottom of page (Control/Command + ↑/↓)
  • Indent (Tab)
  • Unindent (Shift + Tab)
  • Comment/uncomment a single line (Control/Command + /)
  • Comment/uncomment multiple lines (Shift + Control/Command + /)
  • Character transpose (Control/Command + T)
  • Search (Control/Command + F)
  • Replace (Alt + Control/Command + F)
  • Save (Control/Command + S)

Code Hints and Auto-Completion

Lucy_Editor supports using the CodeAutocomplete component to implement code input prompts and automatic completion. Lucy_Editor implements basic control logic, but the code prompt content, auto-completion rules and display UI need to be defined by the developer.

CodeAutocomplete(
  builder: (context, notifier, onSelected) {
    // TODO
  },
  language: langDart,
  child: CodeEditor()
);

Note that Lucy_Editor is only a lightweight editor and does not have the IDE dynamic syntax analysis, so the code prompts and completion have many limitations. You can refer to the code in example to implement a simple code prompt and completion.

Used By

Lucy_Editor has been extensively practiced in the Reqable project. You are welcome to download Reqable to experience it.

License

MIT License

If you would like to sponsor this project, you can support us by purchasing a Reqable license.

Libraries

languages/javascript
languages/lib/common
languages/lib/javascript
languages/lib/mathematica
languages/lib/php
languages/lib/typescript
lucy_editor
styles/a11y-dark
styles/a11y-light
styles/agate
styles/all
styles/an-old-hope
styles/androidstudio
styles/arduino-light
styles/arta
styles/ascetic
styles/atom-one-dark
styles/atom-one-dark-reasonable
styles/atom-one-light
styles/base16/apathy
styles/base16/apprentice
styles/base16/ashes
styles/base16/atelier-cave
styles/base16/atelier-cave-light
styles/base16/atelier-dune
styles/base16/atelier-dune-light
styles/base16/atelier-estuary
styles/base16/atelier-estuary-light
styles/base16/atelier-forest
styles/base16/atelier-forest-light
styles/base16/atelier-heath
styles/base16/atelier-heath-light
styles/base16/atelier-lakeside
styles/base16/atelier-lakeside-light
styles/base16/atelier-plateau
styles/base16/atelier-plateau-light
styles/base16/atelier-savanna
styles/base16/atelier-savanna-light
styles/base16/atelier-seaside
styles/base16/atelier-seaside-light
styles/base16/atelier-sulphurpool
styles/base16/atelier-sulphurpool-light
styles/base16/atlas
styles/base16/bespin
styles/base16/black-metal
styles/base16/black-metal-bathory
styles/base16/black-metal-burzum
styles/base16/black-metal-dark-funeral
styles/base16/black-metal-gorgoroth
styles/base16/black-metal-immortal
styles/base16/black-metal-khold
styles/base16/black-metal-marduk
styles/base16/black-metal-mayhem
styles/base16/black-metal-nile
styles/base16/black-metal-venom
styles/base16/brewer
styles/base16/bright
styles/base16/brogrammer
styles/base16/brush-trees
styles/base16/brush-trees-dark
styles/base16/chalk
styles/base16/circus
styles/base16/classic-dark
styles/base16/classic-light
styles/base16/codeschool
styles/base16/colors
styles/base16/cupcake
styles/base16/cupertino
styles/base16/danqing
styles/base16/darcula
styles/base16/dark-violet
styles/base16/darkmoss
styles/base16/darktooth
styles/base16/decaf
styles/base16/default-dark
styles/base16/default-light
styles/base16/dirtysea
styles/base16/dracula
styles/base16/edge-dark
styles/base16/edge-light
styles/base16/eighties
styles/base16/embers
styles/base16/equilibrium-dark
styles/base16/equilibrium-gray-dark
styles/base16/equilibrium-gray-light
styles/base16/equilibrium-light
styles/base16/espresso
styles/base16/eva
styles/base16/eva-dim
styles/base16/flat
styles/base16/framer
styles/base16/fruit-soda
styles/base16/gigavolt
styles/base16/github
styles/base16/google-dark
styles/base16/google-light
styles/base16/grayscale-dark
styles/base16/grayscale-light
styles/base16/green-screen
styles/base16/gruvbox-dark-hard
styles/base16/gruvbox-dark-medium
styles/base16/gruvbox-dark-pale
styles/base16/gruvbox-dark-soft
styles/base16/gruvbox-light-hard
styles/base16/gruvbox-light-medium
styles/base16/gruvbox-light-soft
styles/base16/hardcore
styles/base16/harmonic16-dark
styles/base16/harmonic16-light
styles/base16/heetch-dark
styles/base16/heetch-light
styles/base16/helios
styles/base16/hopscotch
styles/base16/horizon-dark
styles/base16/horizon-light
styles/base16/humanoid-dark
styles/base16/humanoid-light
styles/base16/ia-dark
styles/base16/ia-light
styles/base16/icy-dark
styles/base16/ir-black
styles/base16/isotope
styles/base16/kimber
styles/base16/london-tube
styles/base16/macintosh
styles/base16/marrakesh
styles/base16/materia
styles/base16/material
styles/base16/material-darker
styles/base16/material-lighter
styles/base16/material-palenight
styles/base16/material-vivid
styles/base16/mellow-purple
styles/base16/mexico-light
styles/base16/mocha
styles/base16/monokai
styles/base16/nebula
styles/base16/nord
styles/base16/nova
styles/base16/ocean
styles/base16/oceanicnext
styles/base16/one-light
styles/base16/onedark
styles/base16/outrun-dark
styles/base16/papercolor-dark
styles/base16/papercolor-light
styles/base16/paraiso
styles/base16/pasque
styles/base16/phd
styles/base16/pico
styles/base16/pop
styles/base16/porple
styles/base16/qualia
styles/base16/railscasts
styles/base16/rebecca
styles/base16/ros-pine
styles/base16/ros-pine-dawn
styles/base16/ros-pine-moon
styles/base16/sagelight
styles/base16/sandcastle
styles/base16/seti-ui
styles/base16/shapeshifter
styles/base16/silk-dark
styles/base16/silk-light
styles/base16/snazzy
styles/base16/solar-flare
styles/base16/solar-flare-light
styles/base16/solarized-dark
styles/base16/solarized-light
styles/base16/spacemacs
styles/base16/summercamp
styles/base16/summerfruit-dark
styles/base16/summerfruit-light
styles/base16/synth-midnight-terminal-dark
styles/base16/synth-midnight-terminal-light
styles/base16/tango
styles/base16/tender
styles/base16/tomorrow
styles/base16/tomorrow-night
styles/base16/twilight
styles/base16/unikitty-dark
styles/base16/unikitty-light
styles/base16/vulcan
styles/base16/windows-10
styles/base16/windows-10-light
styles/base16/windows-95
styles/base16/windows-95-light
styles/base16/windows-high-contrast
styles/base16/windows-high-contrast-light
styles/base16/windows-nt
styles/base16/windows-nt-light
styles/base16/woodland
styles/base16/xcode-dusk
styles/base16/zenburn
styles/brown-paper
styles/codepen-embed
styles/color-brewer
styles/dark
styles/default
styles/devibeans
styles/docco
styles/far
styles/felipec
styles/foundation
styles/github
styles/github-dark
styles/github-dark-dimmed
styles/gml
styles/googlecode
styles/gradient-dark
styles/gradient-light
styles/grayscale
styles/hybrid
styles/idea
styles/intellij-light
styles/ir-black
styles/isbl-editor-dark
styles/isbl-editor-light
styles/kimbie-dark
styles/kimbie-light
styles/lightfair
styles/lioshi
styles/magula
styles/mono-blue
styles/monokai
styles/monokai-sublime
styles/night-owl
styles/nnfx-dark
styles/nnfx-light
styles/nord
styles/obsidian
styles/panda-syntax-dark
styles/panda-syntax-light
styles/paraiso-dark
styles/paraiso-light
styles/pojoaque
styles/purebasic
styles/qtcreator-dark
styles/qtcreator-light
styles/rainbow
styles/routeros
styles/school-book
styles/shades-of-purple
styles/srcery
styles/stackoverflow-dark
styles/stackoverflow-light
styles/sunburst
styles/tokyo-night-dark
styles/tokyo-night-light
styles/tomorrow-night-blue
styles/tomorrow-night-bright
styles/vs
styles/vs2015
styles/xcode
styles/xt256