1
0
Fork 0
mirror of https://github.com/malob/prefmanager.git synced 2024-12-14 11:57:49 +00:00

Initial commit

This commit is contained in:
Malo Bourgon 2020-01-28 16:51:26 -08:00
commit 86cf3dd056
14 changed files with 343 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
.stack-work/
defaults-manager.cabal
*~

3
ChangeLog.md Normal file
View file

@ -0,0 +1,3 @@
# Changelog for defaults-manager
## Unreleased changes

30
LICENSE Normal file
View file

@ -0,0 +1,30 @@
Copyright Author name here (c) 2020
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Author name here nor the names of other
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

1
README.md Normal file
View file

@ -0,0 +1 @@
# defaults-manager

2
Setup.hs Normal file
View file

@ -0,0 +1,2 @@
import Distribution.Simple
main = defaultMain

40
app/Main.hs Normal file
View file

@ -0,0 +1,40 @@
module Main where
import Control.Monad ( join )
import Data.Coerce ( coerce )
import qualified Data.Set as S
import Options.Applicative
import Defaults
-- | Main
main :: IO ()
main = join $ execParser opts
-- | App argument parser
opts :: ParserInfo (IO ())
opts = info
(commands <**> helper)
(fullDesc <> header "macOS Preferences Manager - a utility for working with macOS preferences")
-- | App CLI commands
commands :: Parser (IO ())
commands = hsubparser
(command "watch"
(info
( watch . S.fromList <$> some
(Domain <$> strArgument
( metavar "DOMAIN..."
<> completer (listIOCompleter $ fmap coerce . S.toList <$> domains)
<> help "Domain(s) that will be watched"
)
)
<|> flag' (watch =<< domains)
( long "all"
<> short 'a'
<> help "Watch all domains including NSGlobalDomain"
)
)
(progDesc "Watch domain(s) for changes")
)
)

2
default.nix Normal file
View file

@ -0,0 +1,2 @@
{ nixpkgs ? import <nixpkgs> {}}:
nixpkgs.pkgs.haskell.packages.ghc865.callPackage ./prefmanager.nix { }

50
package.yaml Normal file
View file

@ -0,0 +1,50 @@
name: prefmanager
version: 0.1.0.0
github: malob/prefmanager
author: Malo Bourgon
maintainer: mbourgon@gmail.com
copyright: 2020 Malo Bourgon
license: BSD3
synopsis: A CLI utility for managing macOS preferences
category: CLI
extra-source-files:
- README.md
description: Please see the README on GitHub at <https://github.com/malob/prefmanager#readme>
dependencies:
- base >= 4.7 && < 5
- async
- containers
- diffmap
- hxt
- optparse-applicative
- plist
- pretty-show
- process
library:
source-dirs: src
executables:
prefmanager:
main: Main.hs
source-dirs: app
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
dependencies:
- prefmanager
tests:
prefmanager-test:
main: Spec.hs
source-dirs: test
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
dependencies:
- prefmanager

87
prefmanager.cabal Normal file
View file

@ -0,0 +1,87 @@
cabal-version: 1.12
-- This file has been generated from package.yaml by hpack version 0.33.0.
--
-- see: https://github.com/sol/hpack
--
-- hash: 1af3ad98cee7d7fc142970a5965d8baebd3604edff043fae4c2b5d15e4cde1dc
name: prefmanager
version: 0.1.0.0
synopsis: A CLI utility for managing macOS preferences
description: Please see the README on GitHub at <https://github.com/malob/prefmanager#readme>
category: CLI
homepage: https://github.com/malob/prefmanager#readme
bug-reports: https://github.com/malob/prefmanager/issues
author: Malo Bourgon
maintainer: mbourgon@gmail.com
copyright: 2020 Malo Bourgon
license: BSD3
license-file: LICENSE
build-type: Simple
extra-source-files:
README.md
source-repository head
type: git
location: https://github.com/malob/prefmanager
library
exposed-modules:
Defaults
other-modules:
Paths_prefmanager
hs-source-dirs:
src
build-depends:
async
, base >=4.7 && <5
, containers
, diffmap
, hxt
, optparse-applicative
, plist
, pretty-show
, process
default-language: Haskell2010
executable prefmanager
main-is: Main.hs
other-modules:
Paths_prefmanager
hs-source-dirs:
app
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends:
async
, base >=4.7 && <5
, containers
, diffmap
, hxt
, optparse-applicative
, plist
, prefmanager
, pretty-show
, process
default-language: Haskell2010
test-suite prefmanager-test
type: exitcode-stdio-1.0
main-is: Spec.hs
other-modules:
Paths_prefmanager
hs-source-dirs:
test
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends:
async
, base >=4.7 && <5
, containers
, diffmap
, hxt
, optparse-applicative
, plist
, prefmanager
, pretty-show
, process
default-language: Haskell2010

27
prefmanager.nix Normal file
View file

@ -0,0 +1,27 @@
{ mkDerivation, async, base, containers, diffmap, hpack, hxt
, optparse-applicative, plist, pretty-show, process, stdenv
}:
mkDerivation {
pname = "prefmanager";
version = "0.1.0.0";
src = ./.;
isLibrary = true;
isExecutable = true;
libraryHaskellDepends = [
async base containers diffmap hxt optparse-applicative plist
pretty-show process
];
libraryToolDepends = [ hpack ];
executableHaskellDepends = [
async base containers diffmap hxt optparse-applicative plist
pretty-show process
];
testHaskellDepends = [
async base containers diffmap hxt optparse-applicative plist
pretty-show process
];
prePatch = "hpack";
homepage = "https://github.com/malob/prefmanager#readme";
description = "A CLI utility for managing macOS preferences";
license = stdenv.lib.licenses.bsd3;
}

62
src/Defaults.hs Normal file
View file

@ -0,0 +1,62 @@
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE ViewPatterns #-}
module Defaults where
import Control.Concurrent.Async ( mapConcurrently )
import Data.Coerce ( coerce )
import Data.List ( delete )
import Data.Map ( Map(..) )
import qualified Data.Map as M
import Data.Map.Delta
import Data.Maybe
import Data.Set ( Set(..) )
import qualified Data.Set as S
import Text.Show.Pretty
import Text.XML.Plist
import Text.XML.HXT.Core
import System.Process ( shell
, readCreateProcess
)
newtype Domain = Domain String deriving (Eq, Ord, Show)
-- | Convenience function for running macOS @defaults@ command.
defaultsCmd :: String -> IO String
defaultsCmd s = readCreateProcess (shell $ "defaults " <> s) ""
-- | Convenience function for parsing Plist strings
parsePlist :: String -> IO PlObject
parsePlist = readPlistFromString [withValidate no, withSubstDTDEntities no]
-- | Gets list of domains by running @defaults domains@ and adds @NSGlobalDomain@ to the 'Set'.
domains :: IO (Set Domain)
domains
= S.fromList
. (Domain "NSGlobalDomain" :)
. fmap (Domain . delete ',')
. words
<$> defaultsCmd "domains"
-- | Runs @defaults export [domain] -@ and parses the output.
export :: Domain -> IO (Map String PlObject)
export (coerce -> d)
= M.fromList
. fromJust
. fromPlDict
<$> (defaultsCmd ("export " <> d <> " -") >>= parsePlist)
-- | Runs 'export' on the 'Set' of provided domains
exports :: Set Domain -> IO (Map Domain (Map String PlObject))
exports = (M.fromList <$>) . mapConcurrently (\d -> (d,) <$> export d) . S.toList
-- | Watches a 'Set' of domains for changes.
watch :: Set Domain -> IO ()
watch ds = exports ds >>= go where
go old = do
new <- exports ds
let plDiffs
= M.filter (not . null)
. toDelta
. (\(DeltaUnit o n) -> diff o n)
<$> toDelta (diff old new)
(if null plDiffs then pure () else pPrint plDiffs) *> go new

8
stack.yaml Normal file
View file

@ -0,0 +1,8 @@
resolver: lts-14.21
packages:
- .
extra-deps:
- plist-0.0.6
- diffmap-0.1.0.0

26
stack.yaml.lock Normal file
View file

@ -0,0 +1,26 @@
# 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
packages:
- completed:
hackage: plist-0.0.6@sha256:2c25ca88b99581ef0fe44f9d7dc636f24026603624be9c43631d2b03752886b3,1702
pantry-tree:
size: 463
sha256: 92af2902f8f62e95ec57a5671267e2882cbe5092eaa36fce82172bbdb768cd7f
original:
hackage: plist-0.0.6
- completed:
hackage: diffmap-0.1.0.0@sha256:27ea8c315b5dbfb243b2c3b61eab2164534e1d02887a05392dda65995cd36c3e,727
pantry-tree:
size: 264
sha256: 76ea9b9ad91d113addadf58cb19e289e84347ab667aa5c7feed0a1ccfa4ed613
original:
hackage: diffmap-0.1.0.0
snapshots:
- completed:
size: 524162
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/14/21.yaml
sha256: 9a55dd75853718f2bbbe951872b36a3b7802fcd71796e0f25b8664f24e34c666
original: lts-14.21

2
test/Spec.hs Normal file
View file

@ -0,0 +1,2 @@
main :: IO ()
main = putStrLn "Test suite not yet implemented"