{"id":13398262,"url":"https://github.com/mooz/percol","last_synced_at":"2025-05-14T08:08:22.140Z","repository":{"id":40680453,"uuid":"1418453","full_name":"mooz/percol","owner":"mooz","description":"adds flavor of interactive filtering to the traditional pipe concept of UNIX shell","archived":false,"fork":false,"pushed_at":"2023-12-30T17:17:12.000Z","size":1162,"stargazers_count":3320,"open_issues_count":50,"forks_count":144,"subscribers_count":86,"default_branch":"master","last_synced_at":"2025-04-11T02:51:59.133Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mooz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2011-02-27T17:08:29.000Z","updated_at":"2025-04-07T07:23:14.000Z","dependencies_parsed_at":"2024-01-29T18:51:40.620Z","dependency_job_id":null,"html_url":"https://github.com/mooz/percol","commit_stats":{"total_commits":359,"total_committers":37,"mean_commits":9.702702702702704,"dds":"0.23119777158774368","last_synced_commit":"4b28037e328da3d0fe8165c11b800cbaddcb525e"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mooz%2Fpercol","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mooz%2Fpercol/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mooz%2Fpercol/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mooz%2Fpercol/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mooz","download_url":"https://codeload.github.com/mooz/percol/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253618003,"owners_count":21936900,"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":[],"created_at":"2024-07-30T19:00:21.302Z","updated_at":"2025-05-14T08:08:17.130Z","avatar_url":"https://github.com/mooz.png","language":"Python","readme":"# percol\n\n                                    __\n        ____  ___  ______________  / /\n       / __ \\/ _ \\/ ___/ ___/ __ \\/ /\n      / /_/ /  __/ /  / /__/ /_/ / /\n     / .___/\\___/_/   \\___/\\____/_/\n    /_/\n\npercol adds flavor of interactive selection to the traditional pipe concept on UNIX.\n\n- [What's this](#whats-this)\n  - [Features](#features)\n  - [Related projects](#related-projects)\n- [Installation](#installation)\n  - [PyPI](#pypi)\n  - [Manual](#manual)\n- [Usage](#usage)\n- [Example](#example)\n    - [Interactive pgrep / pkill](#interactive-pgrep--pkill)\n    - [zsh history search](#zsh-history-search)\n    - [tmux](#tmux)\n    - [Calling percol from Python](#calling-percol-from-python)\n- [Configuration](#configuration)\n    - [Customizing prompt](#customizing-prompt)\n        - [Dynamic prompt](#dynamic-prompt)\n        - [Custom format specifiers](#custom-format-specifiers)\n    - [Customizing styles](#customizing-styles)\n        - [Foreground Colors](#foreground-colors)\n        - [Background Color](#background-color)\n        - [Attributes](#attributes)\n- [Matching Method](#matching-method)\n    - [Migemo support](#migemo-support)\n        - [Dictionary settings](#dictionary-settings)\n        - [Minimum query length](#minimum-query-length)\n    - [Pinyin support](#pinyin-support)\n    - [Switching matching method dynamically](#switching-matching-method-dynamically)\n- [Tips](#tips)\n    - [Selecting multiple candidates](#selecting-multiple-candidates)\n    - [Z Shell support](#z-shell-support)\n\n## What's this\n\n![optimized](http://mooz.github.io/percol/percol_overview.gif)\n\npercol is an **interactive grep tool** in your terminal. percol\n\n1. receives input lines from `stdin` or a file,\n2. lists up the input lines,\n3. waits for your input that filter/select the line(s),\n4. and finally outputs the selected line(s) to `stdout`.\n\nSince percol just filters the input and output the result to stdout,\nit can be used in command-chains with `|` in your shell (**UNIX philosophy!**).\n\n### Features\n\n- **Efficient**: With **lazy loads** of input lines and **query caching**, percol handles huge inputs efficiently.\n- **Customizable**: Through configuration file (`rc.py`), percol's behavior including prompts, keymaps, and color schemes can be **heavily customizable**.\n  - See [configuration](https://github.com/mooz/percol#configuration) for details.\n- **Migemo support**: By supporting [C/Migemo](http://code.google.com/p/cmigemo/), **percol filters Japanese inputs blazingly fast**.\n  - See [matching method](https://github.com/mooz/percol#matching-method) for details.\n\n### Related projects\n\n- [canything by @keiji0](https://github.com/keiji0/canything)\n  - A seminal work in interactive grep tools.\n- [zaw by @nakamuray](https://github.com/zsh-users/zaw)\n  - A zsh-friendly interactive grep tool.\n- [peco by @lestrrat](https://github.com/lestrrat/peco)\n  - An interactive grep tool written in Go language.\n- [fzf by @junegunn](https://github.com/junegunn/fzf)\n  - An interactive grep tool written in Go language.\n\n## Installation\n\npercol currently supports only Python 2.x.\n\n### PyPI\n\n    $ sudo pip install percol\n\n### Manual\n\nFirst, clone percol repository and go into the directory.\n\n    $ git clone git://github.com/mooz/percol.git\n    $ cd percol\n\nThen, run a command below.\n\n    $ sudo python setup.py install\n\nIf you don't have a root permission (or don't wanna install percol with sudo), try next one.\n\n    $ python setup.py install --prefix=~/.local\n    $ export PATH=~/.local/bin:$PATH\n\n## Usage\n\nSpecifying a filename.\n\n    $ percol /var/log/syslog\n\nSpecifying a redirection.\n\n    $ ps aux | percol\n\n## Example\n\n### Interactive pgrep / pkill\n\nHere is an interactive version of pgrep,\n\n    $ ps aux | percol | awk '{ print $2 }'\n\nand here is an interactive version of pkill.\n\n    $ ps aux | percol | awk '{ print $2 }' | xargs kill\n\nFor zsh users, command versions are here (`ppkill` accepts options like `-9`).\n\n```sh\nfunction ppgrep() {\n    if [[ $1 == \"\" ]]; then\n        PERCOL=percol\n    else\n        PERCOL=\"percol --query $1\"\n    fi\n    ps aux | eval $PERCOL | awk '{ print $2 }'\n}\n\nfunction ppkill() {\n    if [[ $1 =~ \"^-\" ]]; then\n        QUERY=\"\"            # options only\n    else\n        QUERY=$1            # with a query\n        [[ $# \u003e 0 ]] \u0026\u0026 shift\n    fi\n    ppgrep $QUERY | xargs kill $*\n}\n```\n\n### zsh history search\n\nIn your `.zshrc`, put the lines below.\n\n```sh\nfunction exists { which $1 \u0026\u003e /dev/null }\n\nif exists percol; then\n    function percol_select_history() {\n        local tac\n        exists gtac \u0026\u0026 tac=\"gtac\" || { exists tac \u0026\u0026 tac=\"tac\" || { tac=\"tail -r\" } }\n        BUFFER=$(fc -l -n 1 | eval $tac | percol --query \"$LBUFFER\")\n        CURSOR=$#BUFFER         # move cursor\n        zle -R -c               # refresh\n    }\n\n    zle -N percol_select_history\n    bindkey '^R' percol_select_history\nfi\n```\n\nThen, you can display and search your zsh histories incrementally by pressing `Ctrl + r` key.\n\n### tmux\n\nHere are some examples of tmux and percol integration.\n\n    bind b split-window \"tmux lsw | percol --initial-index $(tmux lsw | awk '/active.$/ {print NR-1}') | cut -d':' -f 1 | tr -d '\\n' | xargs -0 tmux select-window -t\"\n    bind B split-window \"tmux ls | percol --initial-index $(tmux ls | awk \\\"/^$(tmux display-message -p '#{session_name}'):/ {print NR-1}\\\") | cut -d':' -f 1 | tr -d '\\n' | xargs -0 tmux switch-client -t\"\n\nBy putting above 2 settings into `tmux.conf`, you can select a tmux window with `${TMUX_PREFIX} b` keys and session with `${TMUX_PREFIX} B` keys.\n\nAttaching to running tmux sessions can also be made easier with percol with this function(tested to work in bash and zsh)\n\n```sh\nfunction pattach() {\n    if [[ $1 == \"\" ]]; then\n        PERCOL=percol\n    else\n        PERCOL=\"percol --query $1\"\n    fi\n\n    sessions=$(tmux ls)\n    [ $? -ne 0 ] \u0026\u0026 return\n\n    session=$(echo $sessions | eval $PERCOL | cut -d : -f 1)\n    if [[ -n \"$session\" ]]; then\n        tmux att -t $session\n    fi\n}\n```\n\n### Calling percol from Python\n\nEven though Percol is mainly designed as a UNIX command line tool, you can call it from your Python code like so:\n\n```python\nfrom cStringIO import StringIO\nfrom percol import Percol\nfrom percol.actions import no_output\n\ndef main(candidates):\n    si, so, se = StringIO(), StringIO(), StringIO()\n    with Percol(\n            actions=[no_output],\n            descriptors={'stdin': si, 'stdout': so, 'stderr': se},\n            candidates=iter(candidates)) as p:\n        p.loop()\n    results = p.model_candidate.get_selected_results_with_index()\n    return [r[0] for r in results]\n\nif __name__ == \"__main__\":\n    candidates = ['foo', 'bar', 'baz']\n    results = main(candidates)\n    print(\"You picked: {!r}\".format(results))\n```\n\n## Configuration\n\nConfiguration file for percol should be placed under `${HOME}/.percol.d/` and named `rc.py`.\n\nHere is an example `~/.percol.d/rc.py`.\n\n```python\n# X / _ / X\npercol.view.PROMPT  = ur\"\u003cbold\u003e\u003cyellow\u003eX / _ / X\u003c/yellow\u003e\u003c/bold\u003e %q\"\n\n# Emacs like\npercol.import_keymap({\n    \"C-h\" : lambda percol: percol.command.delete_backward_char(),\n    \"C-d\" : lambda percol: percol.command.delete_forward_char(),\n    \"C-k\" : lambda percol: percol.command.kill_end_of_line(),\n    \"C-y\" : lambda percol: percol.command.yank(),\n    \"C-t\" : lambda percol: percol.command.transpose_chars(),\n    \"C-a\" : lambda percol: percol.command.beginning_of_line(),\n    \"C-e\" : lambda percol: percol.command.end_of_line(),\n    \"C-b\" : lambda percol: percol.command.backward_char(),\n    \"C-f\" : lambda percol: percol.command.forward_char(),\n    \"M-f\" : lambda percol: percol.command.forward_word(),\n    \"M-b\" : lambda percol: percol.command.backward_word(),\n    \"M-d\" : lambda percol: percol.command.delete_forward_word(),\n    \"M-h\" : lambda percol: percol.command.delete_backward_word(),\n    \"C-n\" : lambda percol: percol.command.select_next(),\n    \"C-p\" : lambda percol: percol.command.select_previous(),\n    \"C-v\" : lambda percol: percol.command.select_next_page(),\n    \"M-v\" : lambda percol: percol.command.select_previous_page(),\n    \"M-\u003c\" : lambda percol: percol.command.select_top(),\n    \"M-\u003e\" : lambda percol: percol.command.select_bottom(),\n    \"C-m\" : lambda percol: percol.finish(),\n    \"C-j\" : lambda percol: percol.finish(),\n    \"C-g\" : lambda percol: percol.cancel(),\n})\n```\n\n### Customizing prompt\n\nIn percol, a prompt consists of two part: _PROMPT_ and _RPROMPT_, like zsh. As the following example shows, each part appearance can be customized by specifying a prompt format into `percol.view.PROMPT` and `percol.view.RPROMPT` respectively.\n\n```python\npercol.view.PROMPT = ur\"\u003cblue\u003eInput:\u003c/blue\u003e %q\"\npercol.view.RPROMPT = ur\"(%F) [%i/%I]\"\n```\n\nIn prompt formats, a character preceded by `%` indicates a _prompt format specifier_ and is expanded into a corresponding system value.\n\n- `%%`\n    - Display `%` itself\n- `%q`\n    - Display query and caret\n- `%Q`\n    - Display query without caret\n- `%n`\n    - Page number\n- `%N`\n    - Total page number\n- `%i`\n    - Current line number\n- `%I`\n    - Total line number\n- `%c`\n    - Caret position\n- `%k`\n    - Last input key\n\n#### Dynamic prompt\n\nBy changing percol.view.PROMPT into a getter, percol prompts becomes more fancy.\n\n```python\n# Change prompt in response to the status of case sensitivity\npercol.view.__class__.PROMPT = property(\n    lambda self:\n    ur\"\u003cbold\u003e\u003cblue\u003eQUERY \u003c/blue\u003e[a]:\u003c/bold\u003e %q\" if percol.model.finder.case_insensitive\n    else ur\"\u003cbold\u003e\u003cgreen\u003eQUERY \u003c/green\u003e[A]:\u003c/bold\u003e %q\"\n)\n```\n\n#### Custom format specifiers\n\n```python\n# Display finder name in RPROMPT\npercol.view.prompt_replacees[\"F\"] = lambda self, **args: self.model.finder.get_name()\npercol.view.RPROMPT = ur\"(%F) [%i/%I]\"\n```\n\n### Customizing styles\n\nFor now, styles of following 4 items can be customized in `rc.py`.\n\n```python\npercol.view.CANDIDATES_LINE_BASIC    = (\"on_default\", \"default\")\npercol.view.CANDIDATES_LINE_SELECTED = (\"underline\", \"on_yellow\", \"white\")\npercol.view.CANDIDATES_LINE_MARKED   = (\"bold\", \"on_cyan\", \"black\")\npercol.view.CANDIDATES_LINE_QUERY    = (\"yellow\", \"bold\")\n```\n\nEach RHS is a tuple of style specifiers listed below.\n\n#### Foreground Colors\n\n- `\"black\"`   for `curses.COLOR_BLACK`\n- `\"red\"`     for `curses.COLOR_RED`\n- `\"green\"`   for `curses.COLOR_GREEN`\n- `\"yellow\"`  for `curses.COLOR_YELLOW`\n- `\"blue\"`    for `curses.COLOR_BLUE`\n- `\"magenta\"` for `curses.COLOR_MAGENTA`\n- `\"cyan\"`    for `curses.COLOR_CYAN`\n- `\"white\"`   for `curses.COLOR_WHITE`\n\n#### Background Color\n\n- `\"on_black\"`   for `curses.COLOR_BLACK`\n- `\"on_red\"`     for `curses.COLOR_RED`\n- `\"on_green\"`   for `curses.COLOR_GREEN`\n- `\"on_yellow\"`  for `curses.COLOR_YELLOW`\n- `\"on_blue\"`    for `curses.COLOR_BLUE`\n- `\"on_magenta\"` for `curses.COLOR_MAGENTA`\n- `\"on_cyan\"`    for `curses.COLOR_CYAN`\n- `\"on_white\"`   for `curses.COLOR_WHITE`\n\n#### Attributes\n\n- `\"altcharset\"` for `curses.A_ALTCHARSET`\n- `\"blink\"`      for `curses.A_BLINK`\n- `\"bold\"`       for `curses.A_BOLD`\n- `\"dim\"`        for `curses.A_DIM`\n- `\"normal\"`     for `curses.A_NORMAL`\n- `\"standout\"`   for `curses.A_STANDOUT`\n- `\"underline\"`  for `curses.A_UNDERLINE`\n- `\"reverse\"`    for `curses.A_REVERSE`\n\n## Matching Method\n\nBy default, percol interprets input queries by users as **string**. If you prefer **regular expression**, try `--match-method` command line option.\n\n    $ percol --match-method regex\n\n### Migemo support\n\npercol supports **migemo** (http://0xcc.net/migemo/) matching, which allows us to search Japanese documents with ASCII characters.\n\n    $ percol --match-method migemo\n\nTo use this feature, you need to install C/Migemo (https://github.com/koron/cmigemo). In Ubuntu, it's simple:\n\n    $ sudo apt-get install cmigemo\n\nAfter that, by specifying a command line argument `--match-method migemo`, you can use migemo in percol.\n\nNOTE: This feature uses `python-cmigemo` package (https://github.com/mooz/python-cmigemo). Doing `pip install percol` also installs this package too.\n\n#### Dictionary settings\n\nBy default, percol assumes the path of a dictionary for migemo is `/usr/local/share/migemo/utf-8/migemo-dict`. If the dictionary is located in a different place, you should tell the location via `rc.py`.\n\nFor example, if the path of the dictionary is `/path/to/a/migemo-dict`, put lines below into your `rc.py`.\n\n```python\nfrom percol.finder import FinderMultiQueryMigemo\nFinderMultiQueryMigemo.dictionary_path = \"/path/to/a/migemo-dict\"\n```\n\n#### Minimum query length\n\nIf the query length is **too short**, migemo generates **very long** regular expression. To deal with this problem, percol does not pass a query if the length of the query is shorter than **2** and treat the query as raw regular expression.\n\nTo change this behavior, change the value of `FinderMultiQueryMigemo.minimum_query_length` like following settings.\n\n```python\nfrom percol.finder import FinderMultiQueryMigemo\nFinderMultiQueryMigemo.minimum_query_length = 1\n```\n\n### Pinyin support\n\nNow percol supports **pinyin** (http://en.wikipedia.org/wiki/Pinyin) for matching Chinese characters.\n\n    $ percol --match-method pinyin\n\nIn this matching method, first char of each Chinese character's pinyin sequence is used for matching.\nFor example, 'zw' matches '中文' (ZhongWen), '中午'(ZhongWu), '作为' (ZuoWei) etc.\n\nExtra package pinin(https://pypi.python.org/pypi/pinyin/0.2.5) needed.\n\n### Switching matching method dynamically\n\nMatching method can be switched dynamically (at run time) by executing `percol.command.specify_finder(FinderClass)` or `percol.command.toggle_finder(FinderClass)`. In addition, `percol.command.specify_case_sensitive(case_sensitive)` and `percol.command.toggle_case_sensitive()` change the matching status of case sensitivity.\n\n```python\nfrom percol.finder import FinderMultiQueryMigemo, FinderMultiQueryRegex\npercol.import_keymap({\n    \"M-c\" : lambda percol: percol.command.toggle_case_sensitive(),\n    \"M-m\" : lambda percol: percol.command.toggle_finder(FinderMultiQueryMigemo),\n    \"M-r\" : lambda percol: percol.command.toggle_finder(FinderMultiQueryRegex)\n})\n```\n\n## Tips\n\n### Selecting multiple candidates\n\nYou can select and let percol to output multiple candidates by `percol.command.toggle_mark_and_next()` (which is bound to `C-SPC` by default).\n\n`percol.command.mark_all()`, `percol.command.unmark_all()` and `percol.command.toggle_mark_all()` are useful to mark / unmark all candidates at once.\n\n## Z Shell support\n\nA zsh completing-function for percol is available in https://github.com/mooz/percol/blob/master/tools/zsh/_percol .\n","funding_links":[],"categories":["Python","Command-line Tools","资源列表","Command Line","\u003ca name=\"core\"\u003e\u003c/a\u003ecore","Command-Line Productivity","others","命令行工具","Command-line Tools [🔝](#readme)","\u003ca name=\"option-picker\"\u003e\u003c/a\u003eFuzzy finders and option pickers","Awesome Python"],"sub_categories":["命令行工具","Dependency Management","Command-line Tools"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmooz%2Fpercol","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmooz%2Fpercol","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmooz%2Fpercol/lists"}