CodeMirror-Record

CodeMirror-Record

It is a project for recording and playing back activities in the CodeMirror 5 editor and the surrounding environment. You can try this project on the online demo page.

NOTE: The latest CodeMirror (version 6.x) is not yet supported by this library. We are still working on it.

Local Demo

After cloning this repository, follow the steps below to run the local demo in the directory.

  1. Solve dependencies by running npm install.
  2. Use npm run build to build the project.
  3. Use npm run serve to start a node server that hosts the local demo of the project.
  4. If a page is not automatically loaded in your browser you could visit http://localhost:8080/demo/ manually in your browser.
  5. Coding in the editor on the left. All changes will be recorded and synced. Then you can play the records in the editor on the right.

API

The project provides APIs for code recording and playback organized in the Recorder and Player sections.

Recorder

Initialize a recorder

We can pass a CodeMirror instance recordCodeMirror into the constructor CodeRecord as a parameter to create an instance of CodeRecorder. By calling the listen function, we can start listening the operations in the CodeMirror editor indicated by recordCodeMirror.

// recordCodeMirror is a CodeMirror instance.
const codeRecorder = new CodeRecord(recordCodeMirror);
codeRecorder.listen();

Record extra activities

The function recordExtraActivity can be used to record any activity that is not happened in the CodeMirror editor. The parameter can be anything that can be played by the extraActivityHandler function in the player.

// moreActivities is some external value we would like to record
codeRecorder.recordExtraActivity(moreActivities);

Get record result string

After a series of operations inside and outside the editor, an array describing all operations can be obtained by calling getRecords.

let records = '';
records = codeRecorder.getRecords();

Player

Initialize a player

We can pass a CodeMirror instance playCodeMirror into the constructor CodePlay as a parameter to create an instance of CodePlayer.

// playCodeMirror is a CodeMirror instance.
const codePlayer = new CodePlay(playCodeMirror);

You may add an object of extra setting options as the second parameter of CodePlay constructor. The supported options are as follows.

Option Name Meaning Default
maxDelay The maximum pause supported by the player (in millisecond). The pause with time length longer than the value of this option will be replaced with this value. Only non-negative values will be adopted. -1
autoplay The player will play recorded operations immediately after being added to the recorder if the value of this option is true. false
autofocus The editor will be focused whenever recorded operations play if the value of this option is true. false
speed The multiples of playing speed in the player that decides how fast the player playback the operations. 1
extraActivityHandler The callback function for dealing with extra activities recorded. When it is null, the recorded extra activities will be skipped. null
extraActivityReverter The callback function for reverting extra activities recorded. When it is null, the recorded extra activities will be skipped reverting. null
Example

The following options make the player automatically play added records without calling the play function. And the maximum delay before each operation will be no longer than 3000ms. The operations will be played back at 0.8 times speed.

// playCodeMirror is a CodeMirror instance.
const codePlayer = new CodePlay(playCodeMirror, {
  maxDelay: 3000,
  autoplay: true,
  autofocus: true,
  speed: 0.8,
  extraActivityHandler: (activityRecorded) => {
    console.log(activityRecorded);
  },
  extraActivityReverter: (activityRecorded) => {
    console.log(activityRecorded);
  }
});

Player methods

Set options after initialization

You can change the value of player options after initialization. The value of options, including maxDelay, autoplay, autofocus, speed, extraActivityHandler and extraActivityReverter, can be changed by calling the following functions.

codePlayer.setMaxDelay(3000);
codePlayer.setAutoplay(true);
codePlayer.setAutofocus(true);
codePlayer.setSpeed(2.5);
codePlayer.setExtraActivityHandler((activityRecorded) => {
  console.log(activityRecorded);
});
codePlayer.setExtraActivityReverter((activityRecorded) => {
  console.log(activityRecorded);
});
Clear and re-initialize the player instance

Clear all operations and status on the player instance.

codePlayer.clear();

All options set will not be changed.

Add recorded operations

Add records array of operation objects provided by codeRecorder.

codePlayer.addOperations(records);
Play added operations

Focus on the player editor and play the added operations.

codePlayer.play();

You can also call play to resume playing after pause is called.

Pause

Pause the operations being played in the player editor.

codePlayer.pause();
Seek

Seek to a given time position on the timeline of the player (in millisecond).

let seekTime = 10102;
codePlayer.seek(seekTime);
Get player status

Get the status of the player. If there is any recorded operation being played, the value is PLAY. Otherwise, the value is PAUSE.

let seekTime = 10102;
codePlayer.seek(seekTime);
Get current time position

Get the current time position on the timeline of the player (in millisecond).

codePlayer.getCurrentTime();
Get duration

Get the total time duration of recorded operations, in milliseconds.

codePlayer.getDuration();

Player events

You may listen to player events or remove listeners as you wish using on and off. The following events are supported:

Event Explanation
play The player starts to play operations
pause The player pauses/stops playing
seek seek method is called
end All the operations played
clear clear method is called

We currently don’t emit any parameters in the events. If you have any related needs, please submit an issue and let us know

Example
codePlayer.on('play', () => {
  console.log('play event triggered');
});

codePlayer.on('pause', () => {
  console.log('pause event triggered');
});

codePlayer.on('seek', () => {
  console.log('seek event triggered');
});

codePlayer.on('end', () => {
  console.log('end event triggered');
});

codePlayer.on('clear', () => {
  console.log('clear event triggered');
});

Data Explanation

Each manipulation of operations is saved as an object.

General Format

The record of data is a list of objects corresponding to operations. Each of the object has the following format:

How to judge whether the operations are continuous?

What are the meanings of abbreviations of operations?

Abbreviation Full Name Meaning
c *compose Input with IME
d +delete Deletion
i +input Insertion
k markText Mark on Text
l select Selection of Text
m *mouse Mouse Activities
n *rename Rename
o +move Cursor Movement
p paste Paste Text
r drag Drag Text
s setValue Initialize Text
x cut Cut Text
e extra Extra External Activity