a mini document editor
supports basic
and advanced
undo/redo
built-in patch dependency system
powered by Darcs
(Haskell Darcs)
see minidoc.h
for details
first we require a two template paramaters
T
the type to use for data,char_t
- a suitible string adapter,
adapter_t
MiniDoc_T
is provided as a common case for MiniDoc<char, StringAdapter::CharAdapter>
next, load a character stream const T*
and an optional length size_t
, the input will be copied
use sub_str
to copy a range of the output, best used for copying output in chunks, best used for large documents
use str
to copy the entire output, best used for small documents
use line
to copy the specified line of the output, best used for line-by-line output
use seek
and character
to obtain the character at the specified position
for insert
, replace
, and erase
operations, position 0 represents index 0, uses zero based index, just like a C array
the position and length are clamped to the bounds of the document (0 to length) in respect to all current modifications done to the document
append
appends to the end
of the document
doc: apple
append("ban")
doc: appleban
insert
appends to the specified position, use -1
to specify end of document
doc: apple
insert(-1, "ban")
doc: appleban
doc: apple
insert(1, "ban")
doc: abanpple
replace
replaces the text at the specified position
, with an optional length
(default length
is 1
), with the given text
doc: apple
replace(1, "ban")
doc: abanple
if given -1
for position
, the behaviour is the same as if append
, and length
is ignored
if given -1
for length
, length will be truncated to the remainder based on position
erase
erases the text at the specified position
, with a given length
doc: apple
erase(1, 3)
doc: ae
doc: apple
erase(1, -1)
doc: a
if given -1
for position
, nothing is done
if given -1
for length
, erases all text at and after position
seek
, seek_line*
, next
, previous
, has_next
, has_previous
, and cursor
can be used for manipulating and monitoring the text cursor inside the document
seek*
is clamped to the bounds of the document (0 to length/line) in respect to all current modifications done to the document
pass cursor
as a position
or a length
to implement various capabilities such as deleting text at the cursor (void backspace() { auto c = cursor(); if (c != 0) erase(c-1, c); }
) and others
print
prints detailed information about the current state
tag:
lines: 1
length: 1
cursor: 0
line start: 0
line end: 2
line length: 2
line: 0
column: 0
line str: a
line str size: 1
line str hex
0x000000: 61 a
character: 'a'
Undo Stack: 1 items in undo stack
undo #0 : Minidoc Command: content: "pple", content2: ""
Undo Stack: 0 items in redo stack
basic error reporting is provided via error()
and error(const std::string & message)
functions
an error will trigger a backtrace
to be collected at the current document line
as reported by line()
, starting with the most recent edit
to occur on that line
after the backtrace
has been collected it will then be printed
m.append("apples");
m.print();
m.error("expected ';' at end of file");
tag:
lines: 3
length: 24
cursor: 18
line start: 10
line end: 25
line length: 15
line: 2
column: 8
line str: occupiedapples
line str size: 14
line str hex
0x000000: 6f 63 63 75 70 69 65 64 occupied
0x000008: 61 70 70 6c 65 73 apples
character: 'a'
Undo Stack: 12 items in undo stack
undo #0 : Minidoc Command: content: "all\nwhere\noccupied", content2: "": { line 0, old lines 1, new lines 3 }
undo #1 : Minidoc Command: content: "the\nseats\n", content2: "", hunk: { line 1, old lines 1, new lines 3 }
undo #2 : Minidoc Command: content: "clean\n", content2: "", hunk: { line 2, old lines 1, new lines 2 }
undo #3 : Minidoc Command: content: "duly\n", content2: "", hunk: { line 5, old lines 1, new lines 2 }
undo #4 : Minidoc Command: content: "blue\n", content2: "", hunk: { line 3, old lines 1, new lines 2 }
undo #5 : Minidoc Command: content: "seats", content2: "tables", hunk: { line 4, old lines 1, new lines 1 }
undo #6 : InvertCommand: Minidoc Command: content: "seats", content2: "tables", hunk: { line 4, old lines 1, new lines 1 }
undo #7 : InvertCommand: Minidoc Command: content: "blue\n", content2: "", hunk: { line 3, old lines 2, new lines 1 }
undo #8 : InvertCommand: Minidoc Command: content: "duly\n", content2: "", hunk: { line 5, old lines 2, new lines 1 }
undo #9 : InvertCommand: Minidoc Command: content: "clean\n", content2: "", hunk: { line 2, old lines 2, new lines 1 }
undo #10 : InvertCommand: Minidoc Command: content: "the\nseats\n", content2: "", hunk: { line 1, old lines 3, new lines 1 }
undo #11 : Minidoc Command: content: "apples", content2: "", hunk: { line 2, old lines 1, new lines 1 }
Undo Stack: 0 items in redo stack
expected ';' at end of file
line 1, column 0 : "where\n"
at line 2, column 8 : "occupiedapples"
^
printing backtrace...
edit #12: before insert: "apples"
line 1, column 0 : "where\n"
at line 2, column 8 : "occupied"
^
edit #9: before erase: "duly\n"
line 2, column 0 : "clean\n"
at line 3, column 4 : "seats\n"
^
line 4, column 0 : "where\n"
edit #4: before insert: "duly\n"
line 4, column 0 : "where\n"
at line 5, column 0 : "occupied"
^
edit #1: before insert: "all\nwhere\noccupied"
at line 0, column 0 : ""
^
edit #0: ADD FILE
end of backtrace
we support both basic
and advanced
undo
set supports_redo
to specify if redo
should be tracked
set supports_advanced_undo
to toggle between basic
and advanced
undo
state
information is automatically saved upon every edit
operation
use undo
and redo
to iterate between saved states
the undo stack is displayed via print
Undo Stack: 7 items in undo stack
undo #0 : Minidoc Command: content: "A", content2: ""
undo #1 : Minidoc Command: content: "B", content2: ""
undo #2 : Minidoc Command: content: "C", content2: ""
undo #3 : InvertCommand: Minidoc Command: content: "C", content2: ""
undo #4 : InvertCommand: Minidoc Command: content: "B", content2: ""
undo #5 : InvertCommand: Minidoc Command: content: "A", content2: ""
undo #6 : Minidoc Command: content: "X", content2: ""
Undo Stack: 0 items in redo stack
in basic
mode, we mimic most/all modern editors:
any edit erases
the redo
stack
all redo states
are lost
if you undo
then edit
in advanced
mode, we go an extra step to fully preserve
the undo/redo
stack upon edit
any edit preserves
the redo
stack
all redo states
are preserved
if you undo
then edit
m.load("");
m.append("A");
// the current undo stack is as follows
// ""
// the current redo stack is as follows
//
m.append("B");
// the current undo stack is as follows
// "A" > ""
// the current redo stack is as follows
//
m.append("C");
// the current undo stack is as follows
// "AB" > "A" > ""
// the current redo stack is as follows
//
m.undoStack().undo();
// the current undo stack is as follows
// "AB" > "A" > ""
// the current redo stack is as follows
// "ABC"
m.undoStack().undo();
// the current undo stack is as follows
// "A" > ""
// the current redo stack is as follows
// "AB" > "ABC"
m.undoStack().undo();
// the current undo stack is as follows
// ""
// the current redo stack is as follows
// "A" > "AB" > "ABC"
// we are now at empty input
m.append("X");
// in basic, an edit would not be able to recover "A"
// due to the redo stack that contains A, AB, and ABC
// being erased
//
// the current undo stack is as follows
// ""
// the current redo stack is as follows
//
// in advance, an edit would preserve this information
//
// the current undo stack is as follows
// "" > "A" > "AB" > "ABC" > "AB" > "A" > ""
// the current redo stack is as follows
//
m.undoStack().undo();
// the current undo stack is as follows BASIC
// ""
// the current redo stack is as follows BASIC
// "X"
//
// the current undo stack is as follows ADVANCED
// "" > "A" > "AB" > "ABC" > "AB" > "A" > ""
// the current redo stack is as follows ADVANCED
// "X"