Coder Social home page Coder Social logo

pick's Introduction

pick

image PyPI PyPI

pick is a small python library to help you create curses based interactive selection list in the terminal.

Basic Multiselect

Installation

$ pip install pick

Usage

pick comes with a simple api:

>>> from pick import pick

>>> title = 'Please choose your favorite programming language: '
>>> options = ['Java', 'JavaScript', 'Python', 'PHP', 'C++', 'Erlang', 'Haskell']
>>> option, index = pick(options, title)
>>> print(option)
>>> print(index)

outputs:

>>> C++
>>> 4

pick multiselect example:

>>> from pick import pick

>>> title = 'Please choose your favorite programming language (press SPACE to mark, ENTER to continue): '
>>> options = ['Java', 'JavaScript', 'Python', 'PHP', 'C++', 'Erlang', 'Haskell']
>>> selected = pick(options, title, multiselect=True, min_selection_count=1)
>>> print(selected)

outputs:

>>> [('Java', 0), ('C++', 4)]

Options

  • options: a list of options to choose from
  • title: (optional) a title above options list
  • indicator: (optional) custom the selection indicator, defaults to *
  • default_index: (optional) set this if the default selected option is not the first one
  • multiselect: (optional), if set to True its possible to select multiple items by hitting SPACE
  • min_selection_count: (optional) for multi select feature to dictate a minimum of selected items before continuing
  • screen: (optional), if you are using pick within an existing curses application set this to your existing screen object. It is assumed this has initialised in the standard way (e.g. via curses.wrapper(), or curses.noecho(); curses.cbreak(); screen.kepad(True))
  • position: (optional), if you are using pick within an existing curses application use this to set the first position to write to. e.g., position=pick.Position(y=1, x=1)

Community Projects

pickpack: A fork of pick to select tree data.

pick's People

Contributors

aisk avatar cornelius-figgle avatar dependabot[bot] avatar dguo avatar eggsontoast1672 avatar expobrain avatar fcwheat avatar hartwork avatar iamalisalehi avatar jm66 avatar maxg87 avatar p0ns avatar remram44 avatar snail-coupe avatar verhovsky avatar wong2 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pick's Issues

_curses.error: addstr() returned ERR

Traceback (most recent call last):
File "extract.py", line 19, in
style, _ = pick(sorted(list(styles)), title)
File "/usr/local/lib/python2.7/dist-packages/pick/init.py", line 148, in pick
return picker.start()
File "/usr/local/lib/python2.7/dist-packages/pick/init.py", line 134, in start
return curses.wrapper(self._start)
File "/usr/lib/python2.7/curses/wrapper.py", line 43, in wrapper
return func(stdscr, _args, *_kwds)
File "/usr/local/lib/python2.7/dist-packages/pick/init.py", line 131, in _start
return self.run_loop()
File "/usr/local/lib/python2.7/dist-packages/pick/init.py", line 109, in run_loop
self.draw()
File "/usr/local/lib/python2.7/dist-packages/pick/init.py", line 102, in draw
self.screen.addstr(y, x, line)
_curses.error: addstr() returned ERR

changing row 102 from:
102 self.screen.addstr(y, x, line)
to:
102 self.screen.addstr(y - 1, x, line)

avoids the error.. but i'm not sure about what i'm really doing here..

might be related to:
#2

pick version:

โžœ /tmp sudo pip show pick

Metadata-Version: 2.0
Name: pick
Version: 0.6.0
Summary: pick an option in the terminal with a simple GUI
Home-page: https://github.com/wong2/pick
Author: wong2
Author-email: [email protected]
Installer: pip
License: MIT
Location: /usr/local/lib/python2.7/dist-packages
Requires:
Classifiers:
Development Status :: 4 - Beta
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Programming Language :: Python
Programming Language :: Python :: 2.6
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3.3
Programming Language :: Python :: 3.4
Programming Language :: Python :: 3.5

Several instances of picker

I got an issue with several instances of Picker class.
For example:

first = Picker(['First 1', 'First 2'], 'Select first').start()
print(first)
second = Picker(['Second 1', 'Second 2'], 'Select second').start()
print(second)

After running this code i can choose just option in first picker, but not in second one. Let's say that i'm choosing option "First 2" with index 1. After i pressed enter, process finished and i got output:

('First 2', 1)
('Second 1', 0)

Process finished with exit code 0

But i didn't choose option from second picker.

Is it possible in some way to make several choices (for example, i have to choose category of commands, then command in selected category)?

Let the user write-in a choice.

This is an awesome package.

What would it take to have an option to take user input if the right choice is not available?

kernel restart when "option, index = pick(options, title)"

I'm new to Python, i don't know why this code "option, index = pick(options, title)" make my kernel reboot. I've installed pick by "pip install pick" and i imported it correctly with "from pick import pick". I'm working on anaconda on win11.

This is the full code

from pick import pick

title = 'Please choose filter: '
options = ['trending', 'hot', 'created', 'promoted']
option, index = pick(options, title)

Breaking out of the menu that is displayed.

Great utility "pick". Just wondering how to exit out of the menu that is displayed if the user decides that they do not want to pick anything because what they are looking for isn't being listed... like a list of USB drives. I have even tried a "try/except" block.


try:
    title = 'Please choose Drive to write logs to ' + str(removable_volumes) + ': '
    value, index = pick(values, title, indicator='=>')
except KeyboardInterrupt as error:  # On ctrl-c from keyboard, flush buffer, close file, exit. Break loop.
    print("\n\nExiting due to user action...")

Thanks,
Bob

1.0.0 has been overwritten and broken

From the files list on PyPi it shows that the wheel file for python 3, 1.0.0. was uploaded 2021-12-04, which probably introduced the screen-parameter bug into older version, breaking installs also for people with locked version for older releases.

This should not happen, as it leads to a massive amount of confusion.

https://pypi.org/project/pick/1.0.0/#files

RFE: Document Pick methods

Would you please document the methods in Pick?

As it is currently, it is a guess game what the various methods actually do. Well, move_up() and move_down() can be guessed
correctly, but register_custom_handler(), get_option_lines(), get_lines() etc. might not be guessed easily.
I would to suggest to mark those methods as private if you don't want them to be used from outside.

Thanks by the way for writing the library.

Enter key on the numeric keypad ?

I'm very lucky to find this library, but i found the enter key on the numeric keypad cannot take effect. This code is 459.
Is it a feature? Maybe can make it optional or add a action key map

ValueError: not enough values to unpack (expected 2, got 1)

This is how im running the command:

option, index = pick(options, title='Batch Processing Helper & Wizards', indicator='=>', multiselect=False)
However I get the error in the title (ValueError: not enough values to unpack (expected 2, got 1). I installed it using pip install pick.

When I return one value and print it I get the following:
[('\tOpen Input Folder', 0)]
(From selecting the first option)

Im running on an M1 mac within Anaconda environment, if that makes any difference.

Pick options which match the amount of terminal lines will hide the title text when picking options.

It seems like when he number of pick options given are close to or match the number of options which could be displayed, it doesn't properly show the title text.

Example snippet (should reliably reproduce):

import os
from pick import pick

s = os.get_terminal_size()
options = [str(i) for i in range(s.lines - 1)]
pick(options, "Some\ntitle\nwith\na\nfew\nlinebreaks")

Gif:
WindowsTerminal_bFudYuKigh

Tested on: Windows 10 and WSL Ubuntu, both in Windows Terminal

Pick for trees - Pull request?

So... I needed pick for tree structures. So I made the necessary changes. And then I made some more.

It was supposed to be just a small pull request, but it turned into a project of its own, so here is my question: would you like me to make my fork into a pull request?

I've released it as its own package for now, because I needed it up for the project that originated it all, but I'll be happy to contribute upstream! I just don't know if it's too far from the original scope of your project at this point.

In any case, thank you so much for this picker! Your code saved me a lot of trouble and time.

KeyError exception using multi_select, options_map_func and OrderedDict

mydict is a collections.OrderedDict.

def get_option(option):
    return f'{getattr(option, "Name")} | {getattr(option, "Hash")}'
title = 'Please choose (press SPACE to mark, ENTER to continue): '
options, index = pick(mydict, title, multi_select=True, min_selection_count=1, options_map_func=get_option)
Traceback (most recent call last): 
  File "./run.py", line 46, in <module>
    main()
  File "./run.py", line 43, in main
    options, index = pick(mydict, title, multi_select=True, min_selection_count=1, options_map_func=get_option)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pick/__init__.py", line 191, in pick
    return picker.start()
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pick/__init__.py", line 177, in start
    return curses.wrapper(self._start)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/curses/__init__.py", line 94, in wrapper
    return func(stdscr, *args, **kwds)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pick/__init__.py", line 174, in _start
    return self.run_loop()
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pick/__init__.py", line 154, in run_loop
    return self.get_selected()
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pick/__init__.py", line 76, in get_selected
    return_tuples.append((self.options[selected], selected))
KeyError: 0

Script Crashes when Opened via CMD

i made a small script to add extentions to my project.

it works perfectly in vs code but crashes in CMD.

here is my code

from pick import pick
import os
from os import listdir
from os.path import isfile, join
try:
    title = "ColdOS Extentions"
    options = [f for f in listdir("Extentions/") if isfile(join("Extentions/", f))]
    selection = pick(options, title, indicator='=>', default_index=0)
    assert len(selection) == 1
    option, index = selection[0]
    os.system("python Extentions/" + option)
except Exception as e:
    print(e)

Broken dependency in version 1.1.1

This version requires dataclasses which is not declared as a dependency.

This breaks all existing installations, if they update to this latest version.

Getting redirection is not supported error

Here is my code:

def getsavedplayer():
	playerfile = open("players.txt", "r")
	lines = playerfile.read().split(',')
	playerfile.close()
	filelength = len(lines)
	del lines[filelength - 1]
	title = 'Please choose the summoner to load in: '
	option, index = pick(lines, title)
	print(option)
	print(index)

The user can store names in a text file, then I want them to be able to get them into a variable. So I make the text file into a list, which is lines, however I cannot get pick to work with them.

Thanks in advance!

Add color to choices.

Either I am incapable of adding color to the choices or it isn't possible, I don't know.
I would appreciate a solution or make this an enhancement

Multiselect ?

Hello !
Is it possible to select more than one element (given the doc, no), is it in the scope of this package ?
Thanks

Filter options as you type

It would be nice if you could filter your options on the fly by typing.
For example, if my list of options is:

  • b
  • ab
  • a

And I want to select the options that start with an 'a', I could simply press the a button, the list would filter everything else out, and select both options.

Option to not return the index

I'm using multi_select=True to chose from a long list of strings and I don't care about the index.

Right now I have to add a small list comprehension after every call to pick

chosen = pick(['a', 'b'], multi_select=True)
chosen = [val for val, index in chosen]

it would be nicer if it could be an option instead of a whole line of code.

Also, I expected multi_select to be spelled without the underscore: multiselect=True.

Anyway to not do screen clear?

I'm trying to offer a helpful description rendered with rich and then having options on how to proceed at the bottom with pick

Long lists issue

I have an issue with pick while passing a long list, here is an example you can try it:

from pick import pick

title = 'Select: '
options = ['foo.bar1.baz', 'foo.bar2.baz', 'foo.bar3.baz', 'foo.bar4.baz', 'foo.bar5.baz', 'foo.bar6.baz', 'foo.bar7.baz','foo.bar8.baz', 'foo.bar9.baz', 'foo.bar10.baz','foo.bar11.baz', 'foo.bar12.baz', 'foo.bar13.baz', 'foo.bar14.baz', 'foo.bar15.baz', 'foo.bar16.baz', 'foo.bar17.baz','foo.bar18.baz', 'foo.bar19.baz', 'foo.bar20.baz','foo.bar21.baz', 'foo.bar22.baz', 'foo.bar23.baz', 'foo.bar24.baz', 'foo.bar25.baz', 'foo.bar26.baz', 'foo.bar27.baz','foo.bar28.baz', 'foo.bar29.baz', 'foo.bar30.baz','foo.bar31.baz', 'foo.bar32.baz', 'foo.bar33.baz', 'foo.bar34.baz', 'foo.bar35.baz', 'foo.bar36.baz', 'foo.bar37.baz','foo.bar38.baz', 'foo.bar39.baz', 'foo.bar40.baz','foo.bar41.baz', 'foo.bar42.baz', 'foo.bar43.baz', 'foo.bar44.baz', 'foo.bar45.baz', 'foo.bar46.baz', 'foo.bar47.baz','foo.bar48.baz', 'foo.bar49.baz', 'foo.bar50.baz','foo.bar51.baz', 'foo.bar52.baz', 'foo.bar53.baz', 'foo.bar54.baz', 'foo.bar55.baz', 'foo.bar56.baz', 'foo.bar57.baz','foo.bar58.baz', 'foo.bar59.baz', 'foo.bar60.baz']
option, index = pick(options, title)

the result will be:

Traceback (most recent call last):
  File "pick_test.py", line 5, in <module>
    option, index = pick(options, title)
  File "/usr/lib/python2.7/site-packages/pick/__init__.py", line 109, in pick
    return picker.start()
  File "/usr/lib/python2.7/site-packages/pick/__init__.py", line 73, in start
    return curses.wrapper(self.run_loop)
  File "/usr/lib64/python2.7/curses/wrapper.py", line 43, in wrapper
    return func(stdscr, *args, **kwds)
  File "/usr/lib/python2.7/site-packages/pick/__init__.py", line 84, in run_loop
    self.draw()
  File "/usr/lib/python2.7/site-packages/pick/__init__.py", line 67, in draw
    self.screen.addstr(y, x, line)
_curses.error: addstr() returned ERR

SegFault on Ubuntu 18.04

I'm getting a Segmentation Fault when I'm trying to use this module on Ubuntu 18.04. On both Python 2.7 and also 3.6:

Python 2.7.15rc1 (default, Apr 15 2018, 21:51:34) 
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pick
>>> pick.pick(['abc'])
Segmentation fault (core dumped)
Python 3.6.6 (default, Sep 12 2018, 18:26:19) 
[GCC 8.0.1 20180414 (experimental) [trunk revision 259383]] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pick
>>> pick.pick(['abc'])
Segmentation fault (core dumped)

This system is up2date with all the system packages, as of 2018.09.24.

scripts using pick hang if passed arguments via xargs

The following script will hang if anything is passed via xargs:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import pick
pick.pick(['a','b'], 'choose:')

Example:
python3 test.py a b c d
works fine.
echo a b c d | xargs python3 test.py
will show the expected choice menu, but not respond to any inputs.

Windows not working

I am using the latest Windows 10 Pro version and when I run a script using pick it won't let me switch between the choices. It always stays on the first option. On Linux everything works fine.

pick(options, title) doesn't return a tuple anymore, but an array of tuples

Description

The function pick(options, title) doesn't return a tuple, but an array of tuples.

Steps to reproduce

I run the code given in example:

from pick import pick

title = "Please choose your favorite programming language: "
options = ["Java", "JavaScript", "Python", "PHP", "C++", "Erlang", "Haskell"]
option, index = pick(options, title)
print(option)
print(index)

Expected

Variables options and index are filled.

Actual result

Exception has occurred: ValueError
not enough values to unpack (expected 2, got 1)

In debug mode, the function returns:

[('Python', 2)]

Suggestion

Since there is a "multiselect" option, I understand why it returns an array, but it breaks legacy scripts.
I'ld suggest to return an array of tuples ony when multiselect=True.

Additional informations

Python version: 3.10.5
Pick version: 1.3.0

Support for disabled list entries?

I have a use-case for pick where i want to display say items 1..8, but two of them, 3 and 6 are not viable options, but 'known' to the underlying system. The user shouldn't be able to select the not viable items, as that would make them expect that action is taken, whereas that is not the case, because it's not possible to do so. I want to be able to visualize that fact that these items are 'known' and not simply leave them out as the user wouldn't be able to differentiate between unknown and disabled items.

I can imagine two different ways to visually represent that.
I think option 1 is preferable, considering lists can be longer than a screen is high, making option 2 non-straight-forward to grasp):

  1. Keep the list and its ordering as provided to the pick function, visually differentiating the disabled from the enabled options (different color, prefix, something like that).
    Disabled options are skipped when navigating the list

  2. Presenting enabled and disabled items in two separate lists.

A necessary implication is that items passed to pick() must be tuples, indicating for each item whether it is enabled or disabled.

No module named '_curses'

When I try to import ("from pick import pick")
I get an error that reads:
"ModuleNotFoundError: No module named '_curses' "

I just started programming, so maybe its an error on my part, but I'm not sure.

Pip install may be broken?

Hey, I like the idea but I think there may be some issues with the pip installation. Pip successfully completes the install but from pick import pick is returning ImportError: No module named 'pick'. I'm using Python 3.4 via Anaconda.

Cloning the repo, the test passes and when running Python from the repo directory, I'm able to import pick. Note that I can't run the basic.py example from the example folder, but it works when moved to the base directory.

So I'm fairly sure it must be an issue with the pip installer. I'm not all that familiar with python packaging otherwise I'd look into it more myself. Thanks for the repo and sorry in advance if I've missed something obvious.

pip show pick

---
Metadata-Version: 2.0
Name: pick
Version: 0.3.0
Summary: pick an option in the terminal with a simple GUI
Home-page: https://github.com/wong2/pick
Author: wong2
Author-email: [email protected]
License: MIT
Location: /home/liam/anaconda3/lib/python3.4/site-packages
Requires: 
/pick-0.3.0.dist-info> ls
DESCRIPTION.rst  METADATA  metadata.json  pbr.json  RECORD  top_level.txt  WHEEL

Support for initial selection?

Hi, thanks for sharing pick as software libre! ๐Ÿ™

In my scenario I need to pre-select some options, primarily for multi-select mode. What I currently do at git-delete-merged-branches is this:

from pick import Picker

class _PickerWithPreselection(Picker):
    def __init__(self, options, initial_selection=None, **kwargs):
        super().__init__(options, **kwargs)
        if initial_selection is not None:
            self.all_selected = sorted(
                set(i for i in initial_selection if isinstance(i, int) and 0 <= i < len(options)))
            if self.all_selected and kwargs.get('default_index') is None:
                self.index = self.all_selected[0]

Is that something you'd want to integrate with pick?

Best, Sebastian

Choose color for written text

Hello,

I used your code to build a SSH bastion to connect to all my servers. Very useful though, thanks :)
I would like to know how could it be possible to make color of options configurable in the list...
Here I would like to write available hosts in green, and offline hosts in red for example.
I checked in the config_curses def in your code, it's told @todo make colors configurable
Will you add the functionnality soon ?
Else, do you have a link with documentation to explain how to do this ?
Thanks :)

Trouble running it on MacOS using PyCharm

I tried running it on MacOS using PyCharm, tried to replicate your example:

from pick import pick
title = 'Please choose your favorite programming language: '
options = ['Java', 'JavaScript', 'Python', 'PHP', 'C++', 'Erlang', 'Haskell']
option, index = pick(options, title, indicator='=>', default_index=2)
print(option, index)

I keep getting the _curses.error: nocbreak() returned ERR exception. I tried the solution here still no luck. Is there any chance I can have this working on PyCharm output console instead of a Terminal?

Text Near The CLI

Hello, I Wonder If There's Any Way To Write Text With print("text here <--") Or Any Other Way?
I Want The Output To Look Like This:

Blah Blah Blah
Ok, Now Please Answer My Question:

  • Yes
  • No
  • I Dont Know

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.