Skip to content

Commit

Permalink
Rename project to ShMonad
Browse files Browse the repository at this point in the history
  • Loading branch information
matthunz committed Jun 16, 2024
1 parent a277341 commit 33ab125
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 38 deletions.
25 changes: 13 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# ShMonad

![Demo](https://github.com/matthunz/prompt/blob/main/demo.png?raw=true)

A shell prompt with infinite customization.
Expand All @@ -12,11 +14,11 @@ A shell prompt with infinite customization.
By default the CLI will follow the [XDG](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) specification
and use `$XDG_CONFIG_HOME` for configuration files.

If the path does not yet exist you can start by creating a `prompt` directory in your configuration path.
If the path does not yet exist you can start by creating a `shmonad` directory in your configuration path.
For example:
```sh
mkdir -p ~/.config/prompt
cd ~/.config/prompt
mkdir -p ~/.config/shmonad
cd ~/.config/shmonad
```

You can then create a new `config.hs` file, which will be the entrypoint of your configuration.
Expand All @@ -36,9 +38,9 @@ main = do
```

### Cloning from source
In your `prompt` configuration directory, you can now clone the latest source code.
In your `shmonad` configuration directory, you can now clone the latest source code.
```sh
git clone https://github.com/matthunz/prompt
git clone https://github.com/matthunz/shmonad
```

### Building
Expand All @@ -47,29 +49,28 @@ First create a new [stack](https://docs.haskellstack.org/en/stable/) project in
stack init
```

Then edit your `stack.yml` to include the `prompt` source code.
Then edit your `stack.yml` to include the `shmonad` source code.
```yml
resolver:
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/25.yaml

packages:
- prompt
- shmonad
```
Finally, you can install the CLI with:
```
stack install
```

### Adding the prompt to your shell
### Adding ShMonad to your shell
In your `.zshrc` add
```sh
eval "$(prompt init)"
eval "$(shmonad init)"
```

## Usage
You can recompile your configuration by running:
```
prompt --recompile
```

shmonad recompile
```
4 changes: 2 additions & 2 deletions app/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ main = run =<< execParser opts
(fullDesc <> progDesc "Shell prompt")

appName :: String
appName = "prompt"
appName = "shmonad"

run :: Args -> IO ()
run (Args Default) = runPrompt
Expand Down Expand Up @@ -74,7 +74,7 @@ runRecompile = do
configDir <- getUserConfigDir ""

let binPath = dataDir </> appName
let appConfigDir = configDir </> "prompt"
let appConfigDir = configDir </> appName

result <-
try
Expand Down
42 changes: 21 additions & 21 deletions app/Prompt.hs → app/ShMonad.hs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{-# LANGUAGE GADTs #-}

module Prompt
module ShMonad
( backgroundColor,
textColor,
currentDirectoryModule,
gitBranchModule,
userModule,
run,
shmonad,
Segment (..),
path,
segment,
Expand All @@ -29,43 +29,43 @@ import System.Exit (ExitCode (ExitSuccess))
import System.FilePath (takeFileName)
import System.Process (readProcessWithExitCode)

newtype Prompt a = Prompt {unPrompt :: IO (Maybe a)}
newtype ShMonad a = Prompt {unPrompt :: IO (Maybe a)}

instance Functor Prompt where
instance Functor ShMonad where
fmap f (Prompt a) = Prompt (fmap (fmap f) a)

instance Applicative Prompt where
instance Applicative ShMonad where
pure a = Prompt . pure $ Just a
(Prompt f) <*> (Prompt a) = Prompt (liftM2 (<*>) f a)

instance Monad Prompt where
instance Monad ShMonad where
return = pure
(Prompt a) >>= f = Prompt $ do
maybeValue <- a
case maybeValue of
Nothing -> return Nothing
Just value -> unPrompt (f value)

instance (Monoid a) => Semigroup (Prompt a) where
instance (Monoid a) => Semigroup (ShMonad a) where
(<>) (Prompt a) (Prompt b) =
Prompt
( do
results <- mapConcurrently id [a, b]
return (Just (mconcat (map (fromMaybe mempty) results)))
)

textModule :: String -> Prompt String
textModule :: String -> ShMonad String
textModule s = Prompt (pure $ Just s)

currentDirectoryModule :: Prompt String
currentDirectoryModule :: ShMonad String
currentDirectoryModule =
let f = do
currentDir <- getCurrentDirectory
let lastPart = takeFileName currentDir
return $ Just lastPart
in Prompt f

gitBranchModule :: Prompt String
gitBranchModule :: ShMonad String
gitBranchModule =
let f = do
result <- try (readProcessWithExitCode "git" ["rev-parse", "--abbrev-ref", "HEAD"] "") :: IO (Either SomeException (ExitCode, String, String))
Expand All @@ -80,7 +80,7 @@ gitBranchModule =
else Nothing
in Prompt f

userModule :: Prompt String
userModule :: ShMonad String
userModule =
let f = do
result <- try (getEnv "USER") :: IO (Either SomeException String)
Expand All @@ -89,45 +89,45 @@ userModule =
Right name -> Just name
in Prompt f

run :: Prompt String -> IO ()
run (Prompt f) = f >>= \s -> putStr (fromMaybe "" s)
shmonad :: ShMonad String -> IO ()
shmonad (Prompt f) = f >>= \s -> putStr (fromMaybe "" s)

textColor :: ColorIntensity -> Color -> Prompt String -> Prompt String
textColor :: ColorIntensity -> Color -> ShMonad String -> ShMonad String
textColor intensity color m =
textModule ("%{" ++ setSGRCode [SetColor Foreground intensity color] ++ "%}")
<> m
<> textModule ("%{" ++ setSGRCode [Reset] ++ "%}")

backgroundColor :: ColorIntensity -> Color -> Prompt String -> Prompt String
backgroundColor :: ColorIntensity -> Color -> ShMonad String -> ShMonad String
backgroundColor intensity color m =
textModule ("%{" ++ setSGRCode [SetColor Background intensity color] ++ "%}")
<> m
<> textModule ("%{" ++ setSGRCode [Reset] ++ "%}")

timeModule :: Prompt String
timeModule :: ShMonad String
timeModule =
let f = do
time <- getCurrentTime
let timeStr = formatTime defaultTimeLocale "%H:%M:%S" time
return $ Just timeStr
in Prompt f

data Segment = Segment ColorIntensity Color (Prompt String)
data Segment = Segment ColorIntensity Color (ShMonad String)

segment :: ColorIntensity -> Color -> Prompt String -> Prompt [Segment]
segment :: ColorIntensity -> Color -> ShMonad String -> ShMonad [Segment]
segment intensity color prompt = pure [Segment intensity color prompt]

path :: Prompt [Segment] -> Prompt String
path :: ShMonad [Segment] -> ShMonad String
path p = p >>= \segments -> pathHelper segments True

pathHelper :: [Segment] -> Bool -> Prompt String
pathHelper :: [Segment] -> Bool -> ShMonad String
pathHelper ((Segment intensity color prompt) : segments) isFirst =
let f (Segment nextIntensity nextColor _) = (nextIntensity, nextColor)
next = fmap f (safeHead segments)
in pathSegment intensity color isFirst next prompt <> pathHelper segments False
pathHelper _ _ = Prompt (pure Nothing)

pathSegment :: ColorIntensity -> Color -> Bool -> Maybe (ColorIntensity, Color) -> Prompt String -> Prompt String
pathSegment :: ColorIntensity -> Color -> Bool -> Maybe (ColorIntensity, Color) -> ShMonad String -> ShMonad String
pathSegment intensity color isFirst next m =
( if isFirst
then textColor intensity color (textModule "\xE0B6")
Expand Down
6 changes: 3 additions & 3 deletions prompt.cabal → shmonad.cabal
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
cabal-version: 3.0
name: prompt
name: shmonad
version: 0.1.0.0
build-type: Simple
extra-doc-files: CHANGELOG.md

executable prompt
executable shmonad
main-is: Main.hs
hs-source-dirs: app
default-language: Haskell2010
Expand All @@ -22,7 +22,7 @@ executable prompt

library
exposed-modules:
Prompt
ShMonad
hs-source-dirs: app
default-language: Haskell2010
build-depends:
Expand Down

0 comments on commit 33ab125

Please sign in to comment.