Skip to content

Commit 8ddb508

Browse files
committed
Print line violations only under --verbose flag
Alleviates agda#48 but a proper performance fix would be better.
1 parent 37220b7 commit 8ddb508

File tree

3 files changed

+57
-33
lines changed

3 files changed

+57
-33
lines changed

FixWhitespace.hs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import System.IO ( IOMode(WriteMode), hPutStr, hPut
2121
import Text.Read ( readMaybe )
2222

2323
import Data.Text.FixWhitespace ( CheckResult(CheckOK, CheckViolation, CheckIOError), checkFile, displayLineError
24-
, TabSize, defaultTabSize )
24+
, TabSize, Verbose, defaultTabSize )
2525

2626
import ParseConfig ( Config(Config), parseConfig )
2727
import qualified Paths_fix_whitespace as PFW ( version )
@@ -37,8 +37,6 @@ data Mode
3737
| Check -- ^ Check if there are any whitespace issues.
3838
deriving (Show, Eq)
3939

40-
type Verbose = Bool
41-
4240
data Options = Options
4341
{ optVerbose :: Verbose
4442
-- ^ Display the location of a file being checked or not.
@@ -203,28 +201,33 @@ main = do
203201

204202
fix :: Mode -> Verbose -> TabSize -> FilePath -> IO Bool
205203
fix mode verbose tabSize f =
206-
checkFile tabSize f >>= \case
204+
checkFile tabSize verbose f >>= \case
207205

208206
CheckOK -> do
209207
when verbose $
210208
putStrLn $ "[ Checked ] " ++ f
211209
return False
212210

213-
CheckViolation s vs -> do
214-
hPutStrLn stderr $
215-
"[ Violation " ++
216-
(if mode == Fix then "fixed" else "detected") ++
217-
" ] " ++ f ++
218-
(if mode == Fix then "" else
219-
":\n" ++ (unlines $ map (Text.unpack . displayLineError f) vs))
220-
211+
CheckViolation s vs -> do
212+
hPutStrLn stderr (msg vs)
221213
when (mode == Fix) $
222214
withFile f WriteMode $ \h -> do
223215
hSetEncoding h utf8
224216
Text.hPutStr h s
225217
return True
226218

219+
227220
CheckIOError _e -> do
228221
hPutStrLn stderr $
229222
"[ Read error ] " ++ f
230223
return False
224+
225+
where
226+
msg vs
227+
| mode == Fix =
228+
"[ Violation fixed ] " ++ f
229+
230+
| otherwise =
231+
"[ Violation detected ] " ++ f ++
232+
(if not verbose then "" else
233+
":\n" ++ unlines (map (Text.unpack . displayLineError f) vs))

src/Data/Text/FixWhitespace.hs

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ module Data.Text.FixWhitespace
77
, LineError(..)
88
, displayLineError
99
, transform
10+
, transformWithLog
1011
, TabSize
12+
, Verbose
1113
, defaultTabSize
1214
)
1315
where
@@ -23,12 +25,13 @@ import qualified Data.Text.IO as Text {- Strict IO -}
2325

2426
import System.IO ( IOMode(ReadMode), hSetEncoding, utf8, withFile )
2527

26-
import Data.List.Extra.Drop ( dropWhileEnd1 )
28+
import Data.List.Extra.Drop ( dropWhileEnd1, dropWhile1 )
2729

30+
type Verbose = Bool
2831
type TabSize = Int
2932

3033
-- | Default tab size.
31-
34+
--
3235
defaultTabSize :: TabSize
3336
defaultTabSize = 8
3437

@@ -51,27 +54,42 @@ data LineError = LineError Int Text
5154
-- | Check a file against the whitespace policy,
5255
-- returning a fix if violations occurred.
5356
--
54-
checkFile :: TabSize -> FilePath -> IO CheckResult
55-
checkFile tabSize f =
57+
checkFile :: TabSize -> Verbose -> FilePath -> IO CheckResult
58+
checkFile tabSize verbose f =
5659
handle (\ (e :: IOException) -> return $ CheckIOError e) $
5760
withFile f ReadMode $ \ h -> do
5861
hSetEncoding h utf8
5962
s <- Text.hGetContents h
60-
let (s', lvs) = transform tabSize s
63+
let (s', lvs)
64+
| verbose = transformWithLog tabSize s
65+
| otherwise = (transform tabSize s, [])
6166
return $ if s' == s then CheckOK else CheckViolation s' lvs
6267

68+
transform
69+
:: TabSize -- ^ Expand tab characters to so many spaces. Keep tabs if @<= 0@.
70+
-> Text -- ^ Text before transformation.
71+
-> Text -- ^ Text after transformation.
72+
transform tabSize =
73+
Text.unlines .
74+
removeFinalEmptyLinesExceptOne .
75+
map (removeTrailingWhitespace . convertTabs tabSize) .
76+
Text.lines
77+
where
78+
removeFinalEmptyLinesExceptOne =
79+
reverse . dropWhile1 Text.null . reverse
80+
6381
-- | The transformation monad: maintains info about lines that
64-
-- violate the rules.
82+
-- violate the rules. Used in the verbose mode to build a log.
6583
--
6684
type TransformM = Writer [LineError]
6785

6886
-- | Transforms the contents of a file.
6987
--
70-
transform
88+
transformWithLog
7189
:: TabSize -- ^ Expand tab characters to so many spaces. Keep tabs if @<= 0@.
7290
-> Text -- ^ Text before transformation.
7391
-> (Text, [LineError]) -- ^ Text after transformation and violating lines if any.
74-
transform tabSize =
92+
transformWithLog tabSize =
7593
runWriter .
7694
fmap Text.unlines .
7795
fixAllViolations .
@@ -82,7 +100,7 @@ transform tabSize =
82100
fixAllViolations =
83101
removeFinalEmptyLinesExceptOne
84102
<=<
85-
mapM (fixLineWith $ removeTrailingWhitespace . convertTabs)
103+
mapM (fixLineWith $ removeTrailingWhitespace . convertTabs tabSize)
86104

87105
removeFinalEmptyLinesExceptOne :: [Text] -> TransformM [Text]
88106
removeFinalEmptyLinesExceptOne ls
@@ -96,9 +114,6 @@ transform tabSize =
96114
lenLs' = length ls'
97115
els = replicate (lenLs - lenLs') ""
98116

99-
removeTrailingWhitespace =
100-
Text.dropWhileEnd $ \ c -> generalCategory c `elem` [Space,Format] || c == '\t'
101-
102117
fixLineWith :: (Text -> Text) -> (Int, Text) -> TransformM Text
103118
fixLineWith fixer (i, l)
104119
| l == l' = pure l
@@ -108,16 +123,22 @@ transform tabSize =
108123
where
109124
l' = fixer l
110125

111-
convertTabs = if tabSize <= 0 then id else
112-
Text.pack . reverse . fst . foldl convertOne ([], 0) . Text.unpack
126+
removeTrailingWhitespace :: Text -> Text
127+
removeTrailingWhitespace =
128+
Text.dropWhileEnd $ \ c -> generalCategory c `elem` [Space,Format] || c == '\t'
113129

114-
convertOne (a, p) '\t' = (addSpaces n a, p + n)
115-
where
116-
n = tabSize - p `mod` tabSize -- Here, tabSize > 0 is guaranteed
117-
convertOne (a, p) c = (c:a, p+1)
130+
convertTabs :: TabSize -> Text -> Text
131+
convertTabs tabSize = if tabSize <= 0 then id else
132+
Text.pack . reverse . fst . foldl (convertOne tabSize) ([], 0) . Text.unpack
133+
134+
convertOne :: TabSize -> (String, Int) -> Char -> (String, Int)
135+
convertOne tabSize (a, p) '\t' = (addSpaces n a, p + n)
136+
where
137+
n = tabSize - p `mod` tabSize -- Here, tabSize > 0 is guaranteed
138+
convertOne _tabSize (a, p) c = (c:a, p+1)
118139

119-
addSpaces :: Int -> String -> String
120-
addSpaces n = (replicate n ' ' ++)
140+
addSpaces :: Int -> String -> String
141+
addSpaces n = (replicate n ' ' ++)
121142

122143
-- | Print a erroneous line with 'visibleSpaces'.
123144
--

test/Golden.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ goldenTests = do
3434

3535
goldenValue :: FilePath -> IO ByteString
3636
goldenValue file = do
37-
checkFile defaultTabSize file >>= \case
37+
checkFile defaultTabSize {-verbose: -}True file >>= \case
3838

3939
CheckIOError e ->
4040
ioError e

0 commit comments

Comments
 (0)