Osisi

Posted on by Mandla Mbuli

Osisi

I use osisi to configure my machines. This started of as just using a dot file manager then used home-manager then I wrote it in Haskell, then rewrote it in Rust then rewrote it in Haskell again and that is the current version.

Osisi vs home-manager

home-manager is probably better because of nix. I can come back 3 years later and still get a script running. Osisi is better because, well, I don’t need a lot. It does what it needs well enough and I feel in control.

What is osisi?

Right now, it is a way for me to reduce amount of time it takes me to setup an EndeavourOS install. The dream is to eventually use ArchLinux. It was also a way for me to learn Haskell (and briefly Rust).

It has a concept of a Parcel which is a way for me to declare how something installed, configured and updated. I wanted to be able to easily copy bash commands into but also have the type safety thinking provided Haskell.

Parcel

I decided I have 3 actions I want Install (ParcelInstall), update (ParcelUpdate) and configure (ParcelConfig). I have a problem with certain parcels that might need root privileges in order to configure. I currently solve this by detecting if osisi is being run with root privileges and then doing actions (ParcelRootConfig) that need root privileges. A Parcel then has a ParcelName and a list of ParcelActions

This then leads to the following code:

type ParcelName = Text

data ParcelAction where
  ParcelInstall :: Install -> ParcelAction
  ParcelUpdate :: Commands -> ParcelAction
  ParcelConfig :: Config -> ParcelAction
  ParcelRootConfig :: Config -> ParcelAction

data Parcel where
  Parcel :: ParcelName -> [ParcelAction] -> Parcel

Example of how it is used:

parcel :: Parcel
parcel =
  Parcel
    "neovim"
    [ ParcelConfig config
    , ParcelUpdate update
    , ParcelInstall install
    ]

Install

install :: Install
install = Install packages []
  where
    packages =
      [ "neovim"
      , "ctags"
      , "python-jsbeautifier"
      , "yamllint"
      , "shfmt"
      , "texlive-meta"
      , "python-pynvim"
      , "npm"
      , "tree-sitter-cli"
      , "emacs" -- for orgmode
      , "pandoc" -- for orgmode
      , "luarocks"
      , "markdownlint-cli2"
      ]

Commands

update :: Commands
update = command "nvim +PackerClean +PackerUpdate +TSUpdate +qall"

or for Haskell

update :: Commands
update =
  command "~/.ghcup/bin/cabal update"
    <> command "~/.ghcup/bin/stack update"
    <> command "ghcup upgrade"

Config

config :: Config
config =
  Config "$DOTS/neovim/" "$XDG_CONFIG/nvim/" $
    copy "lua/"
      <> copy "after/"
      <> copy "init.lua"
      <> zshGroup
        "neovim"
        ( alias "vi" "nvim"
            <> alias "vim" "nvim"
            <> emptyline
            <> export "MANPAGER" "'nvim +Man!'"
            <> export "MANWIDTH" "999"
        )