Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pb/next #2

Merged
merged 7 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: CI

on:
pull_request:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: freckle/stack-action@v5
18 changes: 18 additions & 0 deletions .github/workflows/restyled.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Restyled

on:
pull_request:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
restyled:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: restyled-io/actions/setup@v4
- uses: restyled-io/actions/run@v4
with:
suggestions: true
1 change: 1 addition & 0 deletions .hlint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- ignore: {name: "Functor law"}
18 changes: 2 additions & 16 deletions .restyled.yaml
Original file line number Diff line number Diff line change
@@ -1,19 +1,5 @@
remote_files:
- url: https://raw.githubusercontent.com/pbrisbin/dotfiles/master/config/brittany/config.yaml
path: brittany.yaml
- url: https://raw.githubusercontent.com/pbrisbin/dotfiles/master/hlint.yaml
path: .hlint.yaml
- url: https://raw.githubusercontent.com/pbrisbin/dotfiles/master/stylish-haskell.yaml
path: .stylish-haskell.yaml

restylers_version: dev

restylers:
- fourmolu
- hlint
- stylish-haskell
- brittany
- prettier:
include:
- "**/*.yaml"
- "**/*.yml"
- "!stylish-haskell"
- "*"
2 changes: 0 additions & 2 deletions Setup.hs

This file was deleted.

39 changes: 18 additions & 21 deletions app/Main.hs
Original file line number Diff line number Diff line change
@@ -1,42 +1,39 @@
module Main
( main
)
( main
)
where

import RIO

import Data.Version (showVersion)
import Options.Applicative
import qualified Paths_whitespace as Pkg
import Paths_whitespace qualified as Pkg
import Whitespace

main :: IO ()
main = do
Options {..} <- execParser $ info (options <**> helper) fullDesc
opts <- execParser $ info (options <**> helper) fullDesc

runSimpleApp $ do
if oShowVersion
then logInfo $ "whitespace " <> fromString (showVersion Pkg.version)
else formatPaths oFormatOptions
runSimpleApp $ do
if opts.showVersion
then logInfo $ "whitespace " <> fromString (showVersion Pkg.version)
else formatPaths opts.formatOptions

data Options = Options
{ oShowVersion :: Bool
, oFormatOptions :: FormatOptions
}

-- brittany-disable-next-binding
{ showVersion :: Bool
, formatOptions :: FormatOptions
}

options :: Parser Options
options = Options
options =
Options
<$> switch (long "version" <> help "Show version")
<*> formatOptions

-- brittany-disable-next-binding

formatOptions :: Parser FormatOptions
formatOptions =
FormatOptions
<$> (not <$> switch (long "no-remove-spaces" <> help "Don't remove trailing spaces"))
<*> (not <$> switch (long "no-fix-newlines" <> help "Don't fix ending newlines"))
<*> switch (long "strict" <> help "Abort on exceptions")
<*> many (argument str (metavar "PATH" <> help "File to fix (inplace)"))
FormatOptions
<$> (not <$> switch (long "no-remove-spaces" <> help "Don't remove trailing spaces"))
<*> (not <$> switch (long "no-fix-newlines" <> help "Don't fix ending newlines"))
<*> switch (long "strict" <> help "Abort on exceptions")
<*> many (argument str (metavar "PATH" <> help "File to fix (inplace)"))
17 changes: 17 additions & 0 deletions fourmolu.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
indentation: 2
column-limit: 80 # ignored until v12 / ghc-9.6
function-arrows: leading
comma-style: leading # default
import-export-style: leading
indent-wheres: false # default
record-brace-space: true
newlines-between-decls: 1 # default
haddock-style: single-line
let-style: mixed
in-style: left-align
single-constraint-parens: never # ignored until v12 / ghc-9.6
unicode: never # default
respectful: true # default
fixities:
- "infix 4 `stringEqual`"
- "infixl 1 &"
47 changes: 21 additions & 26 deletions package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,40 @@ name: whitespace
version: 0.2.0.0
license: MIT

dependencies:
- base >= 4.11 && < 5
- rio # TODO

ghc-options:
- -Weverything
- -Wno-missing-import-lists
- -Wno-missing-kind-signatures
- -Wno-missing-poly-kind-signatures
- -Wno-missing-role-annotations
- -Wno-missing-safe-haskell-mode
- -Wno-unsafe

language: GHC2021

default-extensions:
- BangPatterns
- DataKinds
- DeriveAnyClass
- DeriveFoldable
- DeriveFunctor
- DeriveGeneric
- DeriveLift
- DeriveTraversable
- DerivingStrategies
- FlexibleContexts
- FlexibleInstances
- DerivingVia
- DuplicateRecordFields
- GADTs
- GeneralizedNewtypeDeriving
- LambdaCase
- MultiParamTypeClasses
- NoFieldSelectors
- NoImplicitPrelude
- NoMonomorphismRestriction
- NoPostfixOperators
- OverloadedRecordDot
- OverloadedStrings
- RankNTypes
- RecordWildCards
- ScopedTypeVariables
- StandaloneDeriving
- TypeApplications
- QuasiQuotes
- TypeFamilies

ghc-options: -Weverything
-Wno-unsafe
-Wno-missing-import-lists
-Wno-all-missed-specialisations

dependencies:
- base >= 4.7 && < 5
- rio

library:
source-dirs: src
dependencies:
- bytestring

executables:
whitespace:
Expand Down
93 changes: 49 additions & 44 deletions src/Whitespace.hs
Original file line number Diff line number Diff line change
@@ -1,54 +1,59 @@
module Whitespace
( FormatOptions(..)
, formatPaths
, formatPath
, format

-- Exported for testing error-handling
, UnableToFormat(..)
)
( FormatOptions (..)
, formatPaths
, formatPath
, format
-- Exported for testing error-handling
, UnableToFormat (..)
)
where

import RIO

import RIO.Char (isSpace)
import qualified RIO.Text as T
import RIO.Text qualified as T

data FormatOptions = FormatOptions
{ foSpaces :: Bool -- ^ Trim trailing whitespace from lines?
, foNewlines :: Bool -- ^ Fix newlines at end of file?
, foStrict :: Bool -- ^ Halt on errors reading files?
, foPaths :: [FilePath] -- ^ Files to process
}
{ spaces :: Bool
-- ^ Trim trailing whitespace from lines?
, newlines :: Bool
-- ^ Fix newlines at end of file?
, strict :: Bool
-- ^ Halt on errors reading files?
, paths :: [FilePath]
-- ^ Files to process
}

formatPaths
:: (MonadUnliftIO m, MonadReader env m, HasLogFunc env)
=> FormatOptions
-> m ()
formatPaths opts = for_ (foPaths opts) $ \path ->
handleAny (handleErr (foStrict opts) path) $ formatPath opts path
:: (MonadUnliftIO m, MonadReader env m, HasLogFunc env)
=> FormatOptions
-> m ()
formatPaths opts = for_ opts.paths $ \path ->
handleAny (handleErr opts.strict path) $ formatPath opts path

data UnableToFormat
= UnableToFormatCRLF
| UnableToRead SomeException -- ^ Most likely non-Utf8
deriving stock Show
deriving anyclass Exception
= UnableToFormatCRLF
| -- | Most likely non-Utf8
UnableToRead SomeException
deriving stock (Show)
deriving anyclass (Exception)

formatPath :: MonadUnliftIO m => FormatOptions -> FilePath -> m ()
formatPath opts path = do
content <- readFileUtf8 path `catchAny` (throwIO . UnableToRead)
if isCRLF content
then throwIO UnableToFormatCRLF
else writeFileUtf8 path $ format opts content
content <- readFileUtf8 path `catchAny` (throwIO . UnableToRead)
if isCRLF content
then throwIO UnableToFormatCRLF
else writeFileUtf8 path $ format opts content

isCRLF :: Text -> Bool
isCRLF = ("\r\n" `T.isInfixOf`)

format :: FormatOptions -> Text -> Text
format opts t
| T.null t = t
| otherwise = onOpt foNewlines newlines $ onOpt foSpaces spaces t
where onOpt attr f = bool id f $ attr opts
| T.null t = t
| otherwise = onOpt (.newlines) newlines $ onOpt (.spaces) spaces t
where
onOpt attr f = bool id f $ attr opts

-- | Ensure a single trailing newline
newlines :: Text -> Text
Expand All @@ -62,20 +67,20 @@ eachLine :: (Text -> Text) -> Text -> Text
eachLine f = T.unlines . map f . T.lines

handleErr
:: (MonadIO m, MonadReader env m, HasLogFunc env, Display ex)
=> Bool
-> FilePath
-> ex
-> m ()
:: (MonadIO m, MonadReader env m, HasLogFunc env, Display ex)
=> Bool
-> FilePath
-> ex
-> m ()
handleErr strict path ex
| strict
= do
| strict =
do
logError
$ "Exception processing "
<> fromString path
<> ":"
<> display ex
<> ", aborting (disable strict mode to ignore)"
$ "Exception processing "
<> fromString path
<> ":"
<> display ex
<> ", aborting (disable strict mode to ignore)"
exitWith $ ExitFailure 1
| otherwise
= logWarn $ "Exception processing " <> fromString path <> ":" <> display ex
| otherwise =
logWarn $ "Exception processing " <> fromString path <> ":" <> display ex
4 changes: 1 addition & 3 deletions stack.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
resolver: lts-16.10
ghc-options:
"$locals": -fwrite-ide-info
resolver: lts-23.4
10 changes: 5 additions & 5 deletions stack.yaml.lock
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# This file was autogenerated by Stack.
# You should not edit this file by hand.
# For more information, please see the documentation at:
# https://docs.haskellstack.org/en/stable/lock_files
# https://docs.haskellstack.org/en/stable/topics/lock_files

packages: []
snapshots:
- completed:
size: 532383
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/16/10.yaml
sha256: 469d781ab6d2a4eceed6b31b6e4ec842dcd3cd1d11577972e86902603dce24df
original: lts-16.10
sha256: 0d61fd2be255f5c425cd92dbb4a78d1f70af2c138f3ec921e98b97ae182b044c
size: 679291
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/23/4.yaml
original: lts-23.4
2 changes: 1 addition & 1 deletion test/Spec.hs
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
{-# OPTIONS_GHC -Wno-missing-export-lists #-}
{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
{-# OPTIONS_GHC -Wno-missing-export-lists #-}
Loading