{"id":13841038,"url":"https://github.com/iostreamer-X/FuncShell","last_synced_at":"2025-07-11T10:30:58.258Z","repository":{"id":20304738,"uuid":"88839776","full_name":"iostreamer-X/FuncShell","owner":"iostreamer-X","description":"Improve your shell by making it functional through Haskell! (An update to Awkward)","archived":false,"fork":false,"pushed_at":"2022-01-27T20:04:32.000Z","size":32650,"stargazers_count":291,"open_issues_count":5,"forks_count":8,"subscribers_count":9,"default_branch":"master","last_synced_at":"2024-08-05T17:26:29.228Z","etag":null,"topics":["functional-programming","haskell","shell"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/iostreamer-X.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-04-20T08:26:01.000Z","updated_at":"2024-05-19T22:30:00.000Z","dependencies_parsed_at":"2022-08-02T22:00:37.576Z","dependency_job_id":null,"html_url":"https://github.com/iostreamer-X/FuncShell","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iostreamer-X%2FFuncShell","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iostreamer-X%2FFuncShell/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iostreamer-X%2FFuncShell/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iostreamer-X%2FFuncShell/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iostreamer-X","download_url":"https://codeload.github.com/iostreamer-X/FuncShell/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225713077,"owners_count":17512548,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["functional-programming","haskell","shell"],"created_at":"2024-08-04T17:01:01.837Z","updated_at":"2024-11-21T10:31:27.738Z","avatar_url":"https://github.com/iostreamer-X.png","language":"Haskell","funding_links":[],"categories":["Haskell","Haskell (3)"],"sub_categories":[],"readme":"# FuncShell\nImprove your shell by making it functional through Haskell! (An update to [Awkward](https://github.com/iostreamer-X/Awkward))\n\n![](/fsh.gif)\n\n## What is it?\nThis program is an alternative to 'awk' or at least tries to be, and lets you perform\n'awk' like operations through Haskell. So, if you know basic Haskell syntax, you are already set.\n\n## Why is it?\nAs an exercise, I wanted to update [Awkward](https://github.com/iostreamer-X/Awkward) but in Haskell. A few minutes with Awkward and you would notice its drawbacks.\n\nSince Awkward is a shell and that too a minimal at best, a lot of your customized shell's\nfunctionality is lost. Hence I decided to implemented FuncShell as an executable program and rely on pipes.\n\n## Philosophy\nfsh follows the same philosophy as Awkward. Output of most bash commands can be expressed as [[String]] or [String]\nand one can use standard Haskell functions to modify this data representation.\n\nAdditionally, Haskell's pattern matching works really well with this representation. And its\nlambda functions along with partially applied operator functions ((+3) or (++\" append\") etc) make the syntax clean.\n\n## How does it work?\nThe command output is relayed to the executable through pipes. That output looks like this:\n\n``` shell\n  PID TTY          TIME CMD\n13750 pts/14   00:00:00 bash\n25193 pts/14   00:00:03 node\n25271 pts/14   00:00:00 sh\n25272 pts/14   00:00:00 ps\n```\nThis is parsed, cleaned and converted to something like this:\n``` js\n[ [ \"PID\", \"TTY\", \"TIME\", \"CMD\" ],\n[ \"13750\", \"pts/14\", \"00:00:00\", \"bash\" ],\n[ \"25283\", \"pts/14\", \"00:00:00\", \"sh\" ],\n[ \"25284\", \"pts/14\", \"00:00:00\", \"ps\" ] ]\n```\n\nThe function you provide, let's say `filter (\\(pid:_) -\u003e read pid \u003e 9000)` is applied\nover this data structure. The headers are handled appropriately.\n\n## Installing\n\n```bash\nwget \"https://github.com/iostreamer-X/FuncShell/releases/download/0.1.0.1/fsh\" -O fsh \u0026\u0026 sudo chmod +x fsh \u0026\u0026 sudo mv fsh /usr/local/bin\n```\nYou might need to install `libgmp-dev` for this to work.\n\n## Usage\nAfter installing, you can use this program through `fsh`. I aliased it as ']',\nso my usages look like this.\n\n```bash\nla |] -p table 'filter (\\(_:_:_:_:_:month:_) -\u003e month == \"Oct\")'\n```\n\nThe program expects the input to be received through pipes, always.\n\nNext, it has a few flags.\nYou can use `-h` to get help, and `-p` to choose your parser.\n\n`fsh` **supports plugins**, which means you can install external modules through `cabal`(package manager, you can think of it as npm)\nand get them to work with `fsh`\n\nAnd finally, you are supposed to supply a haskell function. The function must take an input of type [[String]] and give an output of the same type.\n\nTo sum up, this is how this program is supposed to be used:\n\n`bash command |fsh flags 'haskell function'`\n\n## Parsers\nYou can use the `-p` flag to choose your parser, depending on the kind of output you are expecting from the command.\nFor example, `ls` gives a simple list, so the default parser is used and hence there is no need to specify anything.\nWhereas, the `ps` command outputs a table, hence you must specify the table parser through `-p table`.\n\nThe parsers mentioned above are built-in. You can also download and install external parsers. To do that you'd need `cabal`.\nOnce installed, `cabal update \u0026\u0026 cabal install fsh-csv` will install the csv parser.\n\nTo use it, do `echo \"a,b,c\\n1,2,3\" |] -p FSH_CSV 'myHaskellFunction'`\n\n# Plugins\n\nMaking plugins/external parsers is really easy and involves very little fuss. All you need to do is:\n\n- Make a library project(Using cabal or something else if you want).\n- Build a function named `run` with type signature `run :: String -\u003e String -\u003e IO ()`. The first argument is the function, and the second is command output\n- Publish to hackage\n- Rejoice!\n\nI use `hint` to import `run` from your module and use it as a local function.\n\nHere is the implementation of [TableParser](https://github.com/iostreamer-X/FuncShell/blob/master/src/TableParser.hs) to give you an idea. I used this as a base to\nmake the csv parser.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiostreamer-X%2FFuncShell","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fiostreamer-X%2FFuncShell","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiostreamer-X%2FFuncShell/lists"}