ui: editor: jump to current txn or error location (emacs, emacsclient, vi)

This commit is contained in:
Simon Michael 2016-06-19 14:52:55 -07:00
parent c79750bafd
commit 1d419eb7e6
7 changed files with 42 additions and 16 deletions

View File

@ -268,7 +268,7 @@ asHandle ui0@UIState{
EvKey (KChar c) [] | c `elem` ['h','?'] -> continue $ setMode Help ui
EvKey (KChar 'g') [] -> liftIO (uiReloadJournalIfChanged copts d j ui) >>= continue
EvKey (KChar 'a') [] -> suspendAndResume $ clearScreen >> setCursorPosition 0 0 >> add copts j >> uiReloadJournalIfChanged copts d j ui
EvKey (KChar 'E') [] -> suspendAndResume $ void (journalRunEditor endPos j) >> uiReloadJournalIfChanged copts d j ui
EvKey (KChar 'E') [] -> suspendAndResume $ void (runEditor endPos (journalFilePath j)) >> uiReloadJournalIfChanged copts d j ui
EvKey (KChar '0') [] -> continue $ regenerateScreens j d $ setDepth (Just 0) ui
EvKey (KChar '1') [] -> continue $ regenerateScreens j d $ setDepth (Just 1) ui
EvKey (KChar '2') [] -> continue $ regenerateScreens j d $ setDepth (Just 2) ui

View File

@ -29,9 +29,8 @@ endPos = Just (-1,Nothing)
-- | Try running the user's preferred text editor, or a default edit command,
-- on the main journal file, blocking until it exits, and returning the exit code;
-- or raise an error.
journalRunEditor :: Maybe TextPosition -> Journal -> IO ExitCode
journalRunEditor mpos j =
editorOpenPositionCommand mpos (journalFilePath j) >>= runCommand >>= waitForProcess
runEditor :: Maybe TextPosition -> FilePath -> IO ExitCode
runEditor mpos f = editorOpenPositionCommand mpos f >>= runCommand >>= waitForProcess
-- Get the basic shell command to start the user's preferred text editor.
-- This is the value of environment variable $HLEDGER_UI_EDITOR, or $EDITOR, or
@ -64,12 +63,15 @@ editorOpenPositionCommand mpos f = do
let f' = singleQuoteIfNeeded f
return $
case (identifyEditor cmd, mpos) of
(Emacs, Just (line,_)) | line < 0 -> cmd ++ " " ++ f' ++ " -f end-of-buffer"
(Emacs, Just (line,mcol)) | line >= 0 -> cmd ++ " " ++ posopt ++ " " ++ f'
where posopt = "+" ++ show line ++ maybe "" ((":"++).show) mcol
(Vi, Just (line,_)) -> cmd ++ " " ++ posopt ++ " " ++ f'
where posopt = "+" ++ if line >= 0 then show line else ""
_ -> cmd ++ " " ++ f'
(EmacsClient, Just (l,mc)) | l >= 0 -> cmd ++ " " ++ emacsposopt l mc ++ " " ++ f'
(EmacsClient, Just (l,mc)) | l < 0 -> cmd ++ " " ++ emacsposopt 999999999 mc ++ " " ++ f'
(Emacs, Just (l,mc)) | l >= 0 -> cmd ++ " " ++ emacsposopt l mc ++ " " ++ f'
(Emacs, Just (l,_)) | l < 0 -> cmd ++ " " ++ f' ++ " -f end-of-buffer"
(Vi, Just (l,_)) -> cmd ++ " " ++ viposopt l ++ " " ++ f'
_ -> cmd ++ " " ++ f'
where
emacsposopt l mc = "+" ++ show l ++ maybe "" ((":"++).show) mc
viposopt l = "+" ++ if l >= 0 then show l else ""
-- Identify which text editor is used in the basic editor command, if possible.
identifyEditor :: String -> EditorType

View File

@ -8,12 +8,13 @@ module Hledger.UI.ErrorScreen
)
where
import Brick
import Control.Monad
import Control.Monad.IO.Class (liftIO)
import Data.Monoid
import Data.Time.Calendar (Day)
import Graphics.Vty
import Brick
import Graphics.Vty hiding (char, string)-- (Event(..))
import Text.Parsec
import Hledger.Cli hiding (progname,prognameandversion,green)
import Hledger.UI.UIOptions
@ -61,7 +62,7 @@ esDraw _ = error "draw function called with wrong screen type, should not happen
esHandle :: UIState -> Event -> EventM (Next UIState)
esHandle ui@UIState{
aScreen=ErrorScreen{}
aScreen=ErrorScreen{..}
,aopts=UIOpts{cliopts_=copts}
,ajournal=j
,aMode=mode
@ -78,7 +79,11 @@ esHandle ui@UIState{
EvKey (KChar 'q') [] -> halt ui
EvKey KEsc [] -> continue $ resetScreens d ui
EvKey (KChar c) [] | c `elem` ['h','?'] -> continue $ setMode Help ui
EvKey (KChar 'E') [] -> suspendAndResume $ void (journalRunEditor endPos j) >> uiReloadJournalIfChanged copts d j (popScreen ui)
EvKey (KChar 'E') [] -> suspendAndResume $ void (runEditor pos f) >> uiReloadJournalIfChanged copts d j (popScreen ui)
where
(pos,f) = case parsewith hledgerparseerrorpositionp esError of
Right (f,l,c) -> (Just (l, Just c),f)
Left _ -> (endPos, journalFilePath j)
EvKey (KChar 'g') [] -> liftIO (uiReloadJournalIfChanged copts d j (popScreen ui)) >>= continue
-- (ej, _) <- liftIO $ journalReloadIfChanged copts d j
-- case ej of
@ -88,6 +93,17 @@ esHandle ui@UIState{
esHandle _ _ = error "event handler called with wrong screen type, should not happen"
-- | Parse the file name, line and column number from a hledger parse error message, if possible.
-- Temporary, we should keep the original parse error location. XXX
hledgerparseerrorpositionp = do
anyChar `manyTill` char '"'
f <- anyChar `manyTill` (oneOf ['"','\n'])
string " (line "
l <- read <$> many1 digit
string ", column "
c <- read <$> many1 digit
return (f, l, c)
-- If journal file(s) have changed, reload the journal and regenerate all screens.
-- This is here so it can reference the error screen.
uiReloadJournalIfChanged :: CliOpts -> Day -> Journal -> UIState -> IO UIState

View File

@ -250,7 +250,11 @@ rsHandle ui@UIState{
EvKey (KChar c) [] | c `elem` ['h','?'] -> continue $ setMode Help ui
EvKey (KChar 'g') [] -> liftIO (uiReloadJournalIfChanged copts d j ui) >>= continue
EvKey (KChar 'a') [] -> suspendAndResume $ clearScreen >> setCursorPosition 0 0 >> add copts j >> uiReloadJournalIfChanged copts d j ui
EvKey (KChar 'E') [] -> suspendAndResume $ void (journalRunEditor endPos j) >> uiReloadJournalIfChanged copts d j ui
EvKey (KChar 'E') [] -> suspendAndResume $ void (runEditor pos f) >> uiReloadJournalIfChanged copts d j ui
where
(pos,f) = case listSelectedElement rsList of
Nothing -> (endPos, journalFilePath j)
Just (_, RegisterScreenItem{rsItemTransaction=Transaction{tsourcepos=GenericSourcePos f l c}}) -> (Just (l, Just c),f)
EvKey (KChar 'F') [] -> scrollTop >> (continue $ regenerateScreens j d $ toggleFlat ui)
EvKey (KChar 'Z') [] -> scrollTop >> (continue $ regenerateScreens j d $ toggleEmpty ui)
EvKey (KChar 'C') [] -> scrollTop >> (continue $ regenerateScreens j d $ toggleCleared ui)

View File

@ -124,7 +124,9 @@ tsHandle ui@UIState{aScreen=s@TransactionScreen{tsTransaction=(i,t)
EvKey (KChar 'q') [] -> halt ui
EvKey KEsc [] -> continue $ resetScreens d ui
EvKey (KChar c) [] | c `elem` ['h','?'] -> continue $ setMode Help ui
EvKey (KChar 'E') [] -> suspendAndResume $ void (journalRunEditor endPos j) >> uiReloadJournalIfChanged copts d j ui
EvKey (KChar 'E') [] -> suspendAndResume $ void (runEditor pos f) >> uiReloadJournalIfChanged copts d j ui
where
(pos,f) = let GenericSourcePos f l c = tsourcepos t in (Just (l, Just c),f)
EvKey (KChar 'g') [] -> do
d <- liftIO getCurrentDay
(ej, _) <- liftIO $ journalReloadIfChanged copts d j

View File

@ -70,6 +70,7 @@ executable hledger-ui
, HUnit
, microlens >= 0.4 && < 0.5
, microlens-platform >= 0.2.3.1 && < 0.4
, parsec >= 3
, process >= 1.2
, safe >= 0.2
, split >= 0.1 && < 0.3

View File

@ -75,6 +75,7 @@ executables:
- HUnit
- microlens >= 0.4 && < 0.5
- microlens-platform >= 0.2.3.1 && < 0.4
- parsec >= 3
- process >= 1.2
- safe >= 0.2
- split >= 0.1 && < 0.3