packages feed

WEditor 0.2.0.1 → 0.2.0.2

raw patch · 8 files changed

+128/−107 lines, 8 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- WEditor.Base.Editor: type EditorAction c = forall a. FixedFontEditor a c => a -> a
- WEditor.Base.Viewer: type ViewerAction c = forall a. FixedFontViewer a c => a -> a
- WEditor.Document: type ViewerAction c = forall a. FixedFontViewer a c => a -> a
+ WEditor.Base.Editor: type EditorAction c = forall e. FixedFontEditor e c => e -> e
+ WEditor.Base.Viewer: type ViewerAction c = forall v. FixedFontViewer v c => v -> v
+ WEditor.Document: type EditorAction c = forall e. FixedFontEditor e c => e -> e
+ WEditor.Document: type ViewerAction c = forall v. FixedFontViewer v c => v -> v
- WEditor.Base.Editor: breakPara :: FixedFontEditor a c => a -> EditDirection -> a
+ WEditor.Base.Editor: breakPara :: FixedFontEditor e c => e -> EditDirection -> e
- WEditor.Base.Editor: class FixedFontEditor a c | a -> c
+ WEditor.Base.Editor: class FixedFontEditor e c | e -> c
- WEditor.Base.Editor: editText :: FixedFontEditor a c => a -> EditAction c -> EditDirection -> a
+ WEditor.Base.Editor: editText :: FixedFontEditor e c => e -> EditAction c -> EditDirection -> e
- WEditor.Base.Editor: exportData :: FixedFontEditor a c => a -> [UnparsedPara c]
+ WEditor.Base.Editor: exportData :: FixedFontEditor e c => e -> [UnparsedPara c]
- WEditor.Base.Editor: getCursor :: FixedFontEditor a c => a -> (Int, Int)
+ WEditor.Base.Editor: getCursor :: FixedFontEditor e c => e -> (Int, Int)
- WEditor.Base.Editor: getEditPoint :: FixedFontEditor a c => a -> (Int, Int)
+ WEditor.Base.Editor: getEditPoint :: FixedFontEditor e c => e -> (Int, Int)
- WEditor.Base.Editor: getParaCount :: FixedFontEditor a c => a -> Int
+ WEditor.Base.Editor: getParaCount :: FixedFontEditor e c => e -> Int
- WEditor.Base.Editor: getParaSize :: FixedFontEditor a c => a -> Int
+ WEditor.Base.Editor: getParaSize :: FixedFontEditor e c => e -> Int
- WEditor.Base.Editor: moveCursor :: FixedFontEditor a c => a -> MoveDirection -> a
+ WEditor.Base.Editor: moveCursor :: FixedFontEditor e c => e -> MoveDirection -> e
- WEditor.Base.Editor: setEditPoint :: FixedFontEditor a c => a -> (Int, Int) -> a
+ WEditor.Base.Editor: setEditPoint :: FixedFontEditor e c => e -> (Int, Int) -> e
- WEditor.Base.Parser: breakLines :: FixedFontParser a c => a -> [c] -> [VisibleLine c (BreakType a)]
+ WEditor.Base.Parser: breakLines :: FixedFontParser p c => p -> [c] -> [VisibleLine c (BreakType p)]
- WEditor.Base.Parser: class FixedFontParser a c | a -> c where {
+ WEditor.Base.Parser: class FixedFontParser p c | p -> c where {
- WEditor.Base.Parser: emptyLine :: FixedFontParser a c => a -> VisibleLine c (BreakType a)
+ WEditor.Base.Parser: emptyLine :: FixedFontParser p c => p -> VisibleLine c (BreakType p)
- WEditor.Base.Parser: renderLine :: FixedFontParser a c => a -> VisibleLine c (BreakType a) -> [c]
+ WEditor.Base.Parser: renderLine :: FixedFontParser p c => p -> VisibleLine c (BreakType p) -> [c]
- WEditor.Base.Parser: setLineWidth :: FixedFontParser a c => a -> Int -> a
+ WEditor.Base.Parser: setLineWidth :: FixedFontParser p c => p -> Int -> p
- WEditor.Base.Parser: splitLine :: FixedFontParser a c => a -> Int -> VisibleLine c (BreakType a) -> (VisibleLine c (BreakType a), VisibleLine c (BreakType a))
+ WEditor.Base.Parser: splitLine :: FixedFontParser p c => p -> Int -> VisibleLine c (BreakType p) -> (VisibleLine c (BreakType p), VisibleLine c (BreakType p))
- WEditor.Base.Parser: tweakCursor :: FixedFontParser a c => a -> VisibleLine c (BreakType a) -> Int -> Int
+ WEditor.Base.Parser: tweakCursor :: FixedFontParser p c => p -> VisibleLine c (BreakType p) -> Int -> Int
- WEditor.Base.Parser: type family BreakType a :: *;
+ WEditor.Base.Parser: type family BreakType p :: *;
- WEditor.Base.Viewer: class FixedFontViewer a c | a -> c
+ WEditor.Base.Viewer: class FixedFontViewer v c | v -> c
- WEditor.Base.Viewer: getViewSize :: FixedFontViewer a c => a -> (Int, Int)
+ WEditor.Base.Viewer: getViewSize :: FixedFontViewer v c => v -> (Int, Int)
- WEditor.Base.Viewer: getVisible :: FixedFontViewer a c => a -> [[c]]
+ WEditor.Base.Viewer: getVisible :: FixedFontViewer v c => v -> [[c]]
- WEditor.Base.Viewer: setViewSize :: FixedFontViewer a c => a -> (Int, Int) -> a
+ WEditor.Base.Viewer: setViewSize :: FixedFontViewer v c => v -> (Int, Int) -> v
- WEditor.Base.Viewer: updateView :: FixedFontViewer a c => a -> ViewAction -> a
+ WEditor.Base.Viewer: updateView :: FixedFontViewer v c => v -> ViewAction -> v
- WEditor.Document: breakPara :: FixedFontEditor a c => a -> EditDirection -> a
+ WEditor.Document: breakPara :: FixedFontEditor e c => e -> EditDirection -> e
- WEditor.Document: class FixedFontEditor a c | a -> c
+ WEditor.Document: class FixedFontEditor e c | e -> c
- WEditor.Document: class FixedFontParser a c | a -> c
+ WEditor.Document: class FixedFontParser p c | p -> c
- WEditor.Document: class FixedFontViewer a c | a -> c
+ WEditor.Document: class FixedFontViewer v c | v -> c
- WEditor.Document: editText :: FixedFontEditor a c => a -> EditAction c -> EditDirection -> a
+ WEditor.Document: editText :: FixedFontEditor e c => e -> EditAction c -> EditDirection -> e
- WEditor.Document: exportData :: FixedFontEditor a c => a -> [UnparsedPara c]
+ WEditor.Document: exportData :: FixedFontEditor e c => e -> [UnparsedPara c]
- WEditor.Document: getCursor :: FixedFontEditor a c => a -> (Int, Int)
+ WEditor.Document: getCursor :: FixedFontEditor e c => e -> (Int, Int)
- WEditor.Document: getEditPoint :: FixedFontEditor a c => a -> (Int, Int)
+ WEditor.Document: getEditPoint :: FixedFontEditor e c => e -> (Int, Int)
- WEditor.Document: getParaCount :: FixedFontEditor a c => a -> Int
+ WEditor.Document: getParaCount :: FixedFontEditor e c => e -> Int
- WEditor.Document: getParaSize :: FixedFontEditor a c => a -> Int
+ WEditor.Document: getParaSize :: FixedFontEditor e c => e -> Int
- WEditor.Document: getViewSize :: FixedFontViewer a c => a -> (Int, Int)
+ WEditor.Document: getViewSize :: FixedFontViewer v c => v -> (Int, Int)
- WEditor.Document: getVisible :: FixedFontViewer a c => a -> [[c]]
+ WEditor.Document: getVisible :: FixedFontViewer v c => v -> [[c]]
- WEditor.Document: moveCursor :: FixedFontEditor a c => a -> MoveDirection -> a
+ WEditor.Document: moveCursor :: FixedFontEditor e c => e -> MoveDirection -> e
- WEditor.Document: setEditPoint :: FixedFontEditor a c => a -> (Int, Int) -> a
+ WEditor.Document: setEditPoint :: FixedFontEditor e c => e -> (Int, Int) -> e
- WEditor.Document: setViewSize :: FixedFontViewer a c => a -> (Int, Int) -> a
+ WEditor.Document: setViewSize :: FixedFontViewer v c => v -> (Int, Int) -> v
- WEditor.Document: updateView :: FixedFontViewer a c => a -> ViewAction -> a
+ WEditor.Document: updateView :: FixedFontViewer v c => v -> ViewAction -> v
- WEditor.LineWrap: appendHyphen :: WordSplitter a c => a -> [c] -> [c]
+ WEditor.LineWrap: appendHyphen :: WordSplitter s c => s -> [c] -> [c]
- WEditor.LineWrap: breakWords :: (Show a, WordSplitter a c) => a -> BreakWords c
+ WEditor.LineWrap: breakWords :: (Show s, WordSplitter s c) => s -> BreakWords c
- WEditor.LineWrap: class WordSplitter a c | a -> c
+ WEditor.LineWrap: class WordSplitter s c | s -> c
- WEditor.LineWrap: isWhitespace :: WordSplitter a c => a -> c -> Bool
+ WEditor.LineWrap: isWhitespace :: WordSplitter s c => s -> c -> Bool
- WEditor.LineWrap: isWordChar :: WordSplitter a c => a -> c -> Bool
+ WEditor.LineWrap: isWordChar :: WordSplitter s c => s -> c -> Bool
- WEditor.LineWrap: splitWord :: WordSplitter a c => a -> Int -> Int -> [c] -> Maybe [Int]
+ WEditor.LineWrap: splitWord :: WordSplitter s c => s -> Int -> Int -> [c] -> Maybe [Int]

Files

WEditor.cabal view
@@ -1,5 +1,5 @@ name:                WEditor-version:             0.2.0.1+version:             0.2.0.2 synopsis:            Generic text-editor logic for use with fixed-width fonts.  description:@@ -12,6 +12,9 @@   * Customizable line-wrapping policies and word-hyphenation policies.   * Automatic management of a dynamically-sized viewable area.   * Support for novel character types.+  .+  Also see @<http://hackage.haskell.org/package/WEditorHyphen WEditorHyphen>@+  for  language-specific hyphenation rules.  homepage:            https://github.com/ta0kira/wrapping-editor license:             Apache-2.0
WEditor/Base/Editor.hs view
@@ -49,29 +49,32 @@   -- | Generic text editor for fixed-width fonts.-class FixedFontEditor a c | a -> c where+--+--     * @e@: Editor type providing the operations.+--     * @c@: Character type.+class FixedFontEditor e c | e -> c where   -- | Apply an edit action.-  editText :: a -> EditAction c -> EditDirection -> a+  editText :: e -> EditAction c -> EditDirection -> e   -- | Break the current paragraph at the cursor.-  breakPara :: a -> EditDirection -> a-  -- | Apply a cursor movement.-  moveCursor :: a -> MoveDirection -> a-  -- | Get the (row,col) cursor position relative to the viewport.-  getCursor :: a -> (Int,Int)-  -- | Get the absolute (paragraph,char) edit position.+  breakPara :: e -> EditDirection -> e+  -- | Apply e cursor movement.+  moveCursor :: e -> MoveDirection -> e+  -- | Get the @(row,col)@ cursor position relative to the viewport.+  getCursor :: e -> (Int,Int)+  -- | Get the absolute @(paragraph,char)@ edit position.   --   --   The position can be restored after cursor movements by calling   --   'setEditPoint'; however, calling 'editText' or 'breakPara' invalidates   --   this position.-  getEditPoint :: a -> (Int,Int)-  -- | Set the absolute (paragraph,char) edit position.-  setEditPoint :: a -> (Int,Int) -> a+  getEditPoint :: e -> (Int,Int)+  -- | Set the absolute @(paragraph,char)@ edit position.+  setEditPoint :: e -> (Int,Int) -> e   -- | Get the number of characters in the current paragraph.-  getParaSize :: a -> Int+  getParaSize :: e -> Int   -- | Get the number of paragraphs in the document.-  getParaCount :: a -> Int+  getParaCount :: e -> Int   -- | Export the modified data.-  exportData :: a -> [UnparsedPara c]+  exportData :: e -> [UnparsedPara c]  -- | Actions that modify data. data EditAction c =@@ -98,17 +101,17 @@     deriving (Eq,Show)  -- | Any action that updates a 'FixedFontEditor'.-type EditorAction c = forall a. FixedFontEditor a c => a -> a+type EditorAction c = forall e. FixedFontEditor e c => e -> e --- | Action for the Backspace key.+-- | Action for the @Backspace@ key. editorBackspaceAction :: EditorAction c editorBackspaceAction e = editText e DeleteText EditBefore --- | Action for the Delete key.+-- | Action for the @Delete@ key. editorDeleteAction :: EditorAction c editorDeleteAction e = editText e DeleteText EditAfter --- | Action for the Enter key.+-- | Action for the @Enter@ key. editorEnterAction :: EditorAction c editorEnterAction e = breakPara e EditBefore @@ -140,18 +143,18 @@ editorRightAction :: EditorAction c editorRightAction e = moveCursor e MoveNext --- | Action for the Home key.+-- | Action for the @Home@ key. editorHomeAction :: EditorAction c editorHomeAction e = moveCursor e MoveHome --- | Action for the End key.+-- | Action for the @End@ key. editorEndAction :: EditorAction c editorEndAction e = moveCursor e MoveEnd --- | Action for the PageUp key.+-- | Action for the @PageUp@ key. editorPageUpAction :: EditorAction c editorPageUpAction e = moveCursor e MovePageUp --- | Action for the PageDown key.+-- | Action for the @PageDown@ key. editorPageDownAction :: EditorAction c editorPageDownAction e = moveCursor e MovePageDown
WEditor/Base/Parser.hs view
@@ -32,33 +32,41 @@   -- | Line parser for fixed-width fonts.-class FixedFontParser a c | a -> c where+--+--     * @p@: Parser type providing the operations.+--     * @c@: Character type.+class FixedFontParser p c | p -> c where   -- | Type used to differentiate between line-break types.-  type BreakType a :: *+  type BreakType p :: *   -- | Change the max line width used for parsing. A width of zero must result   --   in breakLines skipping line breaks.-  setLineWidth :: a -> Int -> a+  setLineWidth :: p -> Int -> p   -- | Break the sequence into lines.   --   --   The following must hold for all possible inputs to a 'FixedFontParser'-  --   `p`:+  --   @p@:   ---  --   prop> concat (map vlText (breakLines p line)) == line+  --   prop> concat (map vlText (breakLines p l)) == l   --   --   Implement 'renderLine' and 'tweakCursor' to make visual adjustments (such   --   as adding hyphens or indentation) if necessary.-  breakLines :: a -> [c] -> [VisibleLine c (BreakType a)]+  breakLines :: p -> [c] -> [VisibleLine c (BreakType p)]   -- | A place-holder line for empty paragraphs.-  emptyLine :: a -> VisibleLine c (BreakType a)+  emptyLine :: p -> VisibleLine c (BreakType p)   -- | Render the line for viewing. Implement 'tweakCursor' if 'renderLine'   --   changes the positions of any characters on the line.-  renderLine :: a -> VisibleLine c (BreakType a) -> [c]+  renderLine :: p -> VisibleLine c (BreakType p) -> [c]   -- | Adjust the horizontal cursor position.-  tweakCursor :: a -> VisibleLine c (BreakType a) -> Int -> Int+  tweakCursor :: p -> VisibleLine c (BreakType p) -> Int -> Int   tweakCursor _ _ = id   -- | Split the line to create a paragraph break.-  splitLine :: a+  --+  --   The following must hold for all possible inputs to a 'FixedFontParser'+  --   @p@:+  --+  --   prop> let (b,t) = splitLine p n l in vlText l == vlText b ++ vlText t+  splitLine :: p             -> Int                           -- ^ Index to split at.-            -> VisibleLine c (BreakType a)   -- ^ Line to split.-            -> (VisibleLine c (BreakType a),-                VisibleLine c (BreakType a)) -- ^ End of original paragraph and beginning of next paragraph.+            -> VisibleLine c (BreakType p)   -- ^ Line to split.+            -> (VisibleLine c (BreakType p),+                VisibleLine c (BreakType p)) -- ^ New lines at @(bottom,top)@ of previous/next paragraphs.
WEditor/Base/Viewer.hs view
@@ -35,17 +35,20 @@   -- | Generic editor viewport for fixed-width fonts.-class FixedFontViewer a c | a -> c where-  -- | Set the (width,height) size of the viewport. A width < 0 must disable-  --   line wrapping, and a height < 0 must disable vertical bounding.-  setViewSize :: a -> (Int,Int) -> a-  -- | Get the (width,height) size of the viewport.-  getViewSize :: a -> (Int,Int)+--+--     * @v@: Viewer type providing the operations.+--     * @c@: Character type.+class FixedFontViewer v c | v -> c where+  -- | Set the @(width,height)@ size of the viewport. Setting either to @<=0@+  --   disables bounding in that dimension.+  setViewSize :: v -> (Int,Int) -> v+  -- | Get the @(width,height)@ size of the viewport.+  getViewSize :: v -> (Int,Int)   -- | Get the visible lines in the viewport. This does not need to completely   --   fill the viewport area, but it must not exceed it.-  getVisible :: a -> [[c]]+  getVisible :: v -> [[c]]   -- | Apply a view change.-  updateView :: a -> ViewAction -> a+  updateView :: v -> ViewAction -> v  -- | Actions that modify the view without affecting editing. data ViewAction =@@ -54,7 +57,7 @@     deriving (Eq,Show)  -- | Any action that updates a 'FixedFontViewer'.-type ViewerAction c = forall a. FixedFontViewer a c => a -> a+type ViewerAction c = forall v. FixedFontViewer v c => v -> v  -- | Action to resize the viewport. viewerResizeAction :: (Int,Int) -> ViewerAction c@@ -68,5 +71,6 @@ viewerShiftDownAction :: Int -> ViewerAction c viewerShiftDownAction n v = updateView v (ShiftVertical n) +-- | Action to attempt to fill the viewport. viewerFillAction :: ViewerAction c viewerFillAction v = updateView v FillView
WEditor/Document.hs view
@@ -169,33 +169,31 @@ resizeHeight h da@(EditingDocument bs e as w _ k c p) =   (EditingDocument bs e as w h offset c p) where     offset-      | h < 1 = paraLinesBefore da+      | h < 1     = length $ catLinesBefore $ getBeforeLines e:bs       | otherwise = boundOffset h $ min (paraLinesBefore da) k  paraLinesBefore :: EditingDocument c -> Int-paraLinesBefore (EditingDocument bs e _ _ _ _ _ _) = total where-  total = countLinesBefore bs'+paraLinesBefore (EditingDocument bs e _ _ h _ _ _) = total where+  total = countLinesBefore h bs'   bs' = getBeforeLines e:bs  paraLinesAfter :: EditingDocument c -> Int-paraLinesAfter (EditingDocument _ e as _ _ _ _ _) = total where-  total = countLinesAfter as'+paraLinesAfter (EditingDocument _ e as _ h _ _ _) = total where+  total = countLinesAfter h as'   as' = getAfterLines e:as  getVisibleLines :: EditingDocument c -> [[c]] getVisibleLines (EditingDocument bs e as _ h k _ p) = visible where   visible = map (renderLine p) $ bs2 ++ [e2] ++ as2-  bs2 = takeLinesBefore getBefore before+  bs2+    | h < 1     = reverse $ catLinesBefore before+    | otherwise = reverse $ take (boundOffset h k) $ catLinesBefore before   e2 = getCurrentLine e-  as2 = takeLinesAfter getAfter after+  as2+    | h < 1     = catLinesAfter after+    | otherwise = take (h-length bs2-1) $ catLinesAfter after   before = getBeforeLines e:bs   after = getAfterLines e:as-  getBefore-    | h < 1 = countLinesBefore before-    | otherwise = boundOffset h k-  getAfter-    | h < 1 = countLinesAfter after-    | otherwise = h-length bs2-1  moveDocCursor :: MoveDirection -> EditingDocument c -> EditingDocument c moveDocCursor d da@(EditingDocument bs e as w h k c p) = revised where
WEditor/Internal/Para.hs view
@@ -28,6 +28,8 @@   appendToPara,   atParaBack,   atParaFront,+  catLinesAfter,+  catLinesBefore,   countLinesAfter,   countLinesBefore,   editPara,@@ -50,8 +52,6 @@   setParaCursorChar,   setParaEditChar,   splitPara,-  takeLinesAfter,-  takeLinesBefore,   unparsePara,   unparseParaAfter,   unparseParaBefore,@@ -148,19 +148,17 @@ getAfterLines :: EditingPara c b -> VisibleParaAfter c b getAfterLines = VisibleParaAfter . epAfter -takeLinesBefore :: Int -> [VisibleParaBefore c b] -> [VisibleLine c b]-takeLinesBefore n = reverse . take n . concat . map vpbLines+catLinesBefore :: [VisibleParaBefore c b] -> [VisibleLine c b]+catLinesBefore = concat . map vpbLines -takeLinesAfter :: Int -> [VisibleParaAfter c b] -> [VisibleLine c b]-takeLinesAfter n = take n . concat . map vpaLines+catLinesAfter :: [VisibleParaAfter c b] -> [VisibleLine c b]+catLinesAfter = concat . map vpaLines --- TODO: Add an upper bound, to avoid unnecessary traversal.-countLinesBefore :: [VisibleParaBefore c b] -> Int-countLinesBefore = length . concat . map vpbLines+countLinesBefore :: Int -> [VisibleParaBefore c b] -> Int+countLinesBefore n = length . take n . catLinesBefore --- TODO: Add an upper bound, to avoid unnecessary traversal.-countLinesAfter :: [VisibleParaAfter c b] -> Int-countLinesAfter = length . concat . map vpaLines+countLinesAfter :: Int -> [VisibleParaAfter c b] -> Int+countLinesAfter n = length . take n . catLinesAfter  getParaCursorLine :: EditingPara c b -> Int getParaCursorLine = length . epBefore
WEditor/LineWrap.hs view
@@ -68,7 +68,10 @@ instance WordSplitter (NoSplit c) c  -- | Word-splitting operations for use with 'BreakWords'.-class WordSplitter a c | a -> c where+--+--     * @s@: Splitter type providing the operations.+--     * @c@: Character type.+class WordSplitter s c | s -> c where   -- | Determine where to break a word.   --   --   * The splitter can refuse to process the word by returning 'Nothing'.@@ -84,28 +87,28 @@   --          line being parsed.   --       3. All remaining segments are put on separate lines between the   --          current and next lines.-  splitWord :: a+  splitWord :: s             -> Int         -- ^ Space available on the first line.             -> Int         -- ^ Space available on new lines.             -> [c]         -- ^ The word to break.             -> Maybe [Int] -- ^ List of segment sizes.   splitWord _ _ _ _ = Nothing   -- | Predicate for characters that should be treated as a part of a word.-  isWordChar :: a -> c -> Bool+  isWordChar :: s -> c -> Bool   isWordChar _ _ = False   -- | Predicate for detecting whitespace between words.-  isWhitespace :: a -> c -> Bool+  isWhitespace :: s -> c -> Bool   isWhitespace _ _ = False   -- | Append the canonical hyphen character to show word breaks.-  appendHyphen :: a -> [c] -> [c]+  appendHyphen :: s -> [c] -> [c]   appendHyphen _ = id  -- | Wrapping policy that breaks lines based on words. Use 'breakWords' to --   construct a new value.-data BreakWords c = forall a. (Show a, WordSplitter a c) => BreakWords Int a+data BreakWords c = forall s. (Show s, WordSplitter s c) => BreakWords Int s  -- | Wrapping policy that breaks lines based on words.-breakWords :: (Show a, WordSplitter a c) => a -> BreakWords c+breakWords :: (Show s, WordSplitter s c) => s -> BreakWords c breakWords = BreakWords 0  data NoHyphen c = NoHyphen deriving (Show)@@ -174,7 +177,7 @@     total = length cs   tweakCursor _ (VisibleLine HyphenatedWord cs) = id -breakAllLines :: WordSplitter a c => Int -> a -> [c] -> [VisibleLine c LineBreak]+breakAllLines :: WordSplitter s c => Int -> s -> [c] -> [VisibleLine c LineBreak] breakAllLines _ _ [] = [VisibleLine lineBreakEnd []] breakAllLines w s cs   | w < 1 = [VisibleLine lineBreakEnd cs]
test/TestDocument.hs view
@@ -39,30 +39,30 @@        id),     ("default view at top", checkEditView        "original-long.txt"-       "default-view.txt"+       "default-view.txt" (0,0)        id),     ("zero width skips wrapping", checkEditView        "original-long.txt"-       "no-wrap-view.txt" $+       "no-wrap-view.txt" (0,0) $        viewerResizeAction (0,snd defaultView)),     ("zero height skips truncation", checkEditView        "original-long.txt"-       "no-bound-view.txt" $+       "no-bound-view.txt" (0,4) $        composeActions [            viewerResizeAction (fst defaultView,0),            repeatAction 4 editorDownAction          ]),     ("move cursor below bottom", checkEditView        "original-long.txt"-       "below-view.txt" $+       "below-view.txt" (0,9) $        repeatAction 15 editorDownAction),     ("scroll below end of doc", checkEditView        "original-long.txt"-       "below-bottom-view.txt" $+       "below-bottom-view.txt" (10,0) $        repeatAction 100 editorDownAction),     ("page down puts edit at top and preserves cursor", checkEditView        "original-long.txt"-       "page-down-view.txt" $+       "page-down-view.txt" (7,0) $        composeActions [            repeatAction 4 editorRightAction,            editorPageDownAction,@@ -70,7 +70,7 @@          ]),     ("page up puts edit at top and preserves cursor", checkEditView        "original-long.txt"-       "page-up-view.txt" $+       "page-up-view.txt" (7,0) $        composeActions [            repeatAction 4 editorRightAction,            repeatAction 15 editorDownAction,@@ -79,7 +79,7 @@          ]),     ("fill view ignores already full", checkEditView        "original-long.txt"-       "fill-noop-view.txt" $+       "fill-noop-view.txt" (0,4) $        composeActions [            editorPageDownAction,            repeatAction 4 editorDownAction,@@ -87,7 +87,7 @@          ]),     ("fill view with short text", checkEditView        "original-short.txt"-       "fill-short-view.txt" $+       "fill-short-view.txt" (2,5) $        composeActions [            editorPageDownAction,            -- Manually shift the view up by one line.@@ -97,7 +97,7 @@          ]),     ("fill view starting past end", checkEditView        "original-long.txt"-       "fill-end-view.txt" $+       "fill-end-view.txt" (10,7) $        composeActions [            repeatAction 5 editorPageDownAction,            repeatAction 2 editorUpAction,@@ -105,7 +105,7 @@          ]),     ("shift view up within bounds", checkEditView        "original-long.txt"-       "shift-up-bounded-view.txt" $+       "shift-up-bounded-view.txt" (0,8) $        composeActions [            editorPageDownAction,            repeatAction 4 editorDownAction,@@ -113,22 +113,22 @@          ]),     ("shift view down within bounds", checkEditView        "original-long.txt"-       "shift-down-bounded-view.txt" $+       "shift-down-bounded-view.txt" (0,4) $        composeActions [            editorPageDownAction,-           repeatAction 4 editorDownAction,+           repeatAction 8 editorDownAction,            viewerShiftDownAction 4          ]),     ("shift view up past doc front", checkEditView        "original-long.txt"-       "shift-up-unbounded-view.txt" $+       "shift-up-unbounded-view.txt" (0,4) $        composeActions [            repeatAction 4 editorDownAction,            viewerShiftUpAction 4          ]),     ("shift view down past doc back", checkEditView        "original-long.txt"-       "shift-down-unbounded-view.txt" $+       "shift-down-unbounded-view.txt" (10,0) $        composeActions [            repeatAction 5 editorPageDownAction,            repeatAction 4 editorUpAction,@@ -136,14 +136,14 @@          ]),     ("move previous at doc front", checkEditView        "original-long.txt"-       "insert-front-view.txt" $+       "insert-front-view.txt" (3,0) $        composeActions [            editorLeftAction,            editorAppendAction "XYZ"          ]),     ("move next at doc back", checkEditView        "original-long.txt"-       "insert-back-view.txt" $+       "insert-back-view.txt" (13,9) $        composeActions [            -- 43 total lines after wrapping => down 42 then to end of line.            repeatAction 43 editorDownAction,@@ -152,7 +152,7 @@          ]),     ("insert in middle view", checkEditView        "original-long.txt"-       "insert-middle-view.txt" $+       "insert-middle-view.txt" (10,4) $        composeActions [            repeatAction 15 editorDownAction,            repeatAction 5 editorUpAction,@@ -161,7 +161,7 @@          ]),     ("line position preserved when passing short lines", checkEditView        "original-long.txt"-       "insert-middle-view.txt" $+       "insert-middle-view.txt" (10,4) $        composeActions [            repeatAction 7 editorRightAction,            -- This traverses past empty lines after the line position is set.@@ -180,7 +180,7 @@          ]),     ("delete in middle view", checkEditView        "original-long.txt"-       "delete-middle-view.txt" $+       "delete-middle-view.txt" (4,4) $        composeActions [            repeatAction 15 editorDownAction,            repeatAction 5 editorUpAction,@@ -198,14 +198,14 @@          ]),     ("join with previous", checkEditView        "original-long.txt"-       "join-prev-view.txt" $+       "join-prev-view.txt" (8,8) $        composeActions [            repeatAction 9 editorDownAction,            editorBackspaceAction          ]),     ("join with next", checkEditView        "original-long.txt"-       "join-next-view.txt" $+       "join-next-view.txt" (8,8) $        composeActions [            repeatAction 9 editorDownAction,            editorLeftAction,@@ -213,7 +213,7 @@          ]),     ("break in middle before", checkEditView        "original-long.txt"-       "break-before-view.txt" $+       "break-before-view.txt" (3,5) $        composeActions [            repeatAction 15 editorDownAction,            repeatAction 5 editorUpAction,@@ -223,7 +223,7 @@          ]),     ("break in middle after", checkEditView        "original-long.txt"-       "break-after-view.txt" $+       "break-after-view.txt" (7,4) $        composeActions [            repeatAction 15 editorDownAction,            repeatAction 5 editorUpAction,@@ -233,7 +233,7 @@          ]),     ("resize smaller preserves line offset and cursor", checkEditView        "original-long.txt"-       "resize-smaller-view.txt" $+       "resize-smaller-view.txt" (5,4) $        composeActions [            repeatAction 15 editorDownAction,            repeatAction 5 editorUpAction,@@ -243,14 +243,14 @@          ]),     ("resize smaller truncates offset", checkEditView        "original-long.txt"-       "resize-truncate-view.txt" $+       "resize-truncate-view.txt" (0,9) $        composeActions [            repeatAction 9 editorDownAction,            editorInsertAction "XYZ"          ]),     ("resize larger preserves line offset and cursor", checkEditView        "original-long.txt"-       "resize-larger-view.txt" $+       "resize-larger-view.txt" (23,4) $        composeActions [            repeatAction 15 editorDownAction,            repeatAction 5 editorUpAction,@@ -425,11 +425,15 @@   let restored = joinParas $ exportData edit   checkCondition ("\n" ++ restored) (restored == view) -checkEditView fx fy f = do+checkEditView fx fy c f = do   edit <- fmap (f . loadDoc breakExact) $ readFile (testFilesRoot </> fx)   view <- fmap (map trimSpace . lines)  $ readFile (testFilesRoot </> fy)   let restored = map trimSpace $ getVisible edit-  checkCondition ("\n" ++ unlines restored) (restored == view)+  let cursor = getCursor edit+  checkConditions [+      ("Cursor: " ++ show cursor,cursor == c),+      ("View:\n" ++ unlines restored,restored == view)+    ]  checkEditCursor b fx c e f = do   edit <- fmap (f . loadDoc b) $ readFile (testFilesRoot </> fx)