{"id":17649980,"url":"https://github.com/hrs/fuzz","last_synced_at":"2025-07-22T10:39:42.759Z","repository":{"id":56847908,"uuid":"122815477","full_name":"hrs/fuzz","owner":"hrs","description":"Interactively select Ruby objects with rofi, dmenu, and friends!","archived":false,"fork":false,"pushed_at":"2021-10-26T15:32:36.000Z","size":52,"stargazers_count":13,"open_issues_count":1,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-05-07T03:45:09.065Z","etag":null,"topics":["dmenu","peco","pick","rofi","ruby","scripting","selecta"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hrs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-02-25T07:40:07.000Z","updated_at":"2023-12-29T20:55:03.000Z","dependencies_parsed_at":"2022-09-22T14:25:58.190Z","dependency_job_id":null,"html_url":"https://github.com/hrs/fuzz","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hrs%2Ffuzz","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hrs%2Ffuzz/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hrs%2Ffuzz/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hrs%2Ffuzz/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hrs","download_url":"https://codeload.github.com/hrs/fuzz/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252810273,"owners_count":21807759,"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":["dmenu","peco","pick","rofi","ruby","scripting","selecta"],"created_at":"2024-10-23T11:34:29.983Z","updated_at":"2025-05-07T03:45:19.865Z","avatar_url":"https://github.com/hrs.png","language":"Ruby","readme":"## Fuzz: A Ruby wrapper around interactive filtering tools\n\n[![Build Status](https://travis-ci.org/hrs/fuzz.svg?branch=master)](https://travis-ci.org/hrs/fuzz)\n[![Maintainability](https://api.codeclimate.com/v1/badges/326b820a889742177ec2/maintainability)](https://codeclimate.com/github/hrs/fuzz/maintainability)\n[![Coverage Status](https://coveralls.io/repos/github/hrs/fuzz/badge.svg?branch=master)](https://coveralls.io/github/hrs/fuzz?branch=master)\n[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](http://www.gnu.org/licenses/gpl-3.0)\n\nI often write scripts in which a user needs to choose one of a number of\npossibilities: maybe they need to select a directory, or a file, or an action,\nor just an arbitrary object.\n\n[rofi][] and [dmenu][] are really cool tools for that! They provide a visual way\nfor a user to use fuzzy searching to choose among a selection of strings.\n[pick][], [peco][], and [selecta][] provide similar services on the command line.\n\nUnfortunately, though, these tools do *just* choose between strings. But my\nscripts would often be a lot simpler if the user were able to select arbitrary\nRuby objects. Fuzz manages the translation between lists of strings that can be\nselected through these visual pickers and the associated collection of Ruby\nobjects, which makes it a bit easier to write interactive and OOP-friendly Ruby\nscripts.\n\n[rofi]: https://github.com/DaveDavenport/rofi\n[dmenu]: https://tools.suckless.org/dmenu\n[pick]: https://github.com/calleerlandsson/pick\n[peco]: https://github.com/peco/peco\n[selecta]: https://github.com/garybernhardt/selecta\n\n### For example\n\nThere are more [interesting examples in the wiki][], but here's a simple one to\nget started.\n\n[interesting examples in the wiki]: https://github.com/hrs/fuzz/wiki\n\nI'm a fan of the excellent [RubyTapas screencasts][], and I'd like a script to\nlet me interactively search through their titles to pick one to play. Here's a\nway I could do that:\n\n```ruby\nrequire \"fuzz\"\n\n# Instantiate some File objects:\nepisodes = Dir.glob(\"~/ruby_tapas_episodes/*\")\n\n# Have the user pick one with rofi:\nchoice = Fuzz::Selector.new(episodes).pick\n\n# Play the selected file with VLC:\nsystem(\"vlc \\\"#{ choice.path }\\\"\")\n```\n\nThe call to `#pick` will call `#to_s` on every episode, display the results\nthrough `rofi` (the default picker), get the user's choice, and use that to\nreturn the corresponding object.\n\n[RubyTapas screencasts]: https://www.rubytapas.com/\n\n### Caching selections\n\nIf you run your script frequently you may find that you often make the same\nselections. It's convenient to have those selections appear near the top of the\nlist.\n\nFuzz can maintain a script-specific record of your previous selections and\norder your options from most to least popular. Just include an optional `:cache`\nargument when creating a `Fuzz::Selector`:\n\n```ruby\nFuzz::Selector.new(\n  some_objects,\n  cache: Fuzz::Cache.new(\"~/.cache/fuzz/my_script_cache\"),\n)\n```\n\nYou'll want to use a different file for each script. Using the same cache file\nfor different scripts will probably yield weird results.\n\nI think `~/.cache/fuzz/` is a nice directory for your personal script caches,\nand it complies with the [XDG Base Directory Specification][], but you can keep\n'em wherever you'd like.\n\n[XDG Base Directory Specification]: https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html\n\n### Supplying a default value\n\nIf the user enters a string that doesn't correspond to an object,\n`Fuzz::Selector#pick` will normally return `nil`.\n\nHowever, you can manually specify a default return value with the `default:`\noption:\n\n```ruby\nFuzz::Selector.new(\n  [1, 2, 3],\n  default: 42,\n).pick # =\u003e returns 42 if the user picks a value other than 1, 2, or 3\n```\n\n### Choosing a different picker\n\nFuzz ships with support for numerous fuzzy-matching tools, which it calls\n\"pickers.\" The `Fuzz::Selector` constructor takes an optional `picker:` argument\nto pick a picker.\n\n| Executable | Creating an instance             |\n|------------|----------------------------------|\n| `dmenu`    | `Fuzz::DmenuPicker.new`          |\n| `peco`     | `Fuzz::PecoPicker.new`           |\n| `pick`     | `Fuzz::PickPicker.new`           |\n| `rofi`     | `Fuzz::RofiPicker.new` (default) |\n| `selecta`  | `Fuzz::SelectaPicker.new`        |\n\nFor example, to use `dmenu` as your picker:\n\n```ruby\nFuzz::Selector.new(\n  some_objects,\n  picker: Fuzz::DmenuPicker.new,\n)\n```\n\nIf the executable associated with your chosen picker can't be found (perhaps\nit's not installed, or not in your `$PATH`), `Fuzz::Selector#pick` will raise a\n`Fuzz::MissingExecutableError`.\n\n### Extending `fuzz` with new pickers\n\nIt's possible to extend `fuzz` to use a picker of your choice. The object\nsupplied to `picker:` must implement a `#pick` method, which should take an\narray of strings and return a string.\n\nHere's a simple example with a silly picker that always chooses the first\noption:\n\n```ruby\ndef PickFirst\n  def pick(choices)\n    choices.first\n  end\nend\n\nselector = Fuzz::Selector.new(\n  [1, 2, 3, 4, 5],\n  picker: PickFirst.new,\n)\n\nselector.pick # =\u003e 1\n```\n\nYour custom pickers will probably be more interactive than this! =)\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem \"fuzz\"\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install fuzz\n\n### Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies. Then, run\n`rake spec` to run the tests. You can also run `bin/console` for an interactive\nprompt that will allow you to experiment.\n\nTo install this gem onto your local machine, run `bundle exec rake install`. To\nrelease a new version, update the version number in `version.rb`, and then run\n`bundle exec rake release`, which will create a git tag for the version, push\ngit commits and tags, and push the `.gem` file to\n[rubygems.org](https://rubygems.org).\n\n### Contributing\n\nBug reports and pull requests are welcome on GitHub at\nhttps://github.com/hrs/fuzz. This project is intended to be a safe, welcoming\nspace for collaboration, and contributors are expected to adhere to the\n[Contributor Covenant](http://contributor-covenant.org) code of conduct.\n\n### Code of Conduct\n\nEveryone interacting in the Fuzz project’s codebases, issue trackers, chat rooms\nand mailing lists is expected to follow the [code of\nconduct](https://github.com/hrs/fuzz/blob/master/CODE_OF_CONDUCT.md).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhrs%2Ffuzz","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhrs%2Ffuzz","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhrs%2Ffuzz/lists"}