Install
-------
If you don’t have `docker <https://docs.docker.com/get-docker>`__
installed, install Redis and start server
::
% sudo apt-get install -y redis-server
or
% brew install redis
% brew services start redis
Install with ``pip``
::
% pip3 install chloop
..
Optionally install ipython with ``pip3 install ipython`` to enable
``:ipython`` colon command on a GetCharLoop instance. Also
``pip3 install pdbpp`` for an improved debug experience when using
``:pdb`` colon command.
Usage
-----
The ``GetCharLoop`` class is provided by the ``chloop`` package. Calling
an **instance** of this class starts a REPL session, which the user can
end by pressing ``Ctrl`` + ``d`` or ``Ctrl`` + ``c``.
See the **Example** section below.
The **first** character you type at the REPL prompt is significant.
The colon
^^^^^^^^^
Hitting the ``:`` key at the prompt will allow you to enter a command
and any arguments you need to pass to that command.
- ``:docstrings`` to view docstrings of methods defined on the class
- ``:errors`` to view colon commands that raised exceptions
- ``:history`` view colon commands issued
- ``:pdb`` to start a pdb session (debugging/inspection)
- ``:ipython`` to start ipython shell
- ``:shortcuts`` to view hotkey shortcuts
Any methods added to your sub-class of ``GetCharLoop`` are callable as
**colon commands**, as long as they do not start with an underscore
(``_``). Methods should **only accept ``*args``**, if anything.
For any methods/commands that should not be logged to the history,
append the method name to the end of the ``self._DONT_LOG_CMDS`` list.
The dash
^^^^^^^^
Hitting the ``-`` key at the prompt will allow you to type a note.
The question mark
^^^^^^^^^^^^^^^^^
Hitting the ``?`` key at the prompt will display the class docstring(s)
and the startup message.
Other keys
^^^^^^^^^^
Hitting any other key at the prompt will do one of the following:
- call a **registered shortcut function** bound to the key (use
``:shortcuts`` command to see what is available)
- display the character and its integer ordinal
A hotkey can be bound to any callable object that accepts no arguments.
Use ``functools.partial`` (if necessary) to create a callable
accepting no arguments.
Adding hotkeys (simple)
- call the ``_add_hotkey`` method on your instance of ``GetCharLoop``
(or sub-class) with the following args
- ``ch``: character hotkey
- ``func``: callable object that accepts no arguments
- ``help_string``: a string containing short help text for hotkey
Adding hotkeys (when using callables on ``self``)
- call the ``self._chfunc_dict_update`` method in the ``__init__``
method of your subclass with a list of tuples or a dict.
- the keys of the dict (or first items in list of tuples) are the
hotkey characters
- the values of the dict (or second items in list of tuples) are
2-item tuples
- 1st item is a **callable** that accepts no arguments
- 2nd item is a short help string
..
Note: when passing a dict, the items will be inserted in the
alphabetical order of the help string.
Basic example
-------------
::
% python3 -c 'from chloop import GetCharLoop; GetCharLoop()()'
> :docstrings
======================================================================
Loop forever, receiving character input from user and performing actions
- ^d or ^c to break the loop
- ':' to enter a command (and any arguments)
- the name of the command should be monkeypatched on the GetCharLoop
instance, or be a defined method on a GetCharLoop sub-class
- the function bound to `:command` should accept `*args` only
- '-' to receive an input line from user (a note)
- '?' to show the class docstring(s) and the startup message
.:: docstrings ::.
Print/return the docstrings of methods defined on this class
.:: errors ::.
Print/return any colon commands that raised exceptions (w/ traceback)
.:: history ::.
Print/return colon commands used
.:: ipython ::.
Start ipython shell. To continue back to the input loop, use 'ctrl + d'
.:: pdb ::.
Start pdb (debugger). To continue back to the input loop, use 'c'
.:: shortcuts ::.
Print/return any hotkey shortcuts defined on this class
> :pdb
[10] > /tmp/ch/venv/lib/python3.5/site-packages/chloop/__init__.py(90)__call__()
-> continue
(Pdb++) l
85 cmd = user_input.split()[0]
86 args = user_input.split()[1:]
87
88 if cmd == 'pdb':
89 import pdb; pdb.set_trace()
90 -> continue
91
92 if cmd == 'ipython':
93 from IPython import embed; embed()
94 continue
95
(Pdb++) self._collection
Collection('chloop-log', 'default', index_fields='cmd,status,error_type', json_fields='args,value')
(Pdb++) self._collection.keyspace
[]
(Pdb++) c
> :ipython
Python 3.5.1+ (default, Mar 30 2016, 22:46:26)
Type "copyright", "credits" or "license" for more information.
IPython 5.2.2 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: self._collection
Out[1]: Collection('chloop-log', 'default', index_fields='cmd,status,error_type', json_fields='args,value')
In [2]: self.shortcuts
Out[2]: <bound method GetCharLoop.shortcuts of <chloop.GetCharLoop object at 0x7f9f8ff5f5f8>>
In [3]: self.docstrings
Out[3]: <bound method GetCharLoop.docstrings of <chloop.GetCharLoop object at 0x7f9f8ff5f5f8>>
In [4]:
Do you really want to exit ([y]/n)? y
> :shortcuts
> - there are no shortcuts defined by default
>
Sub-class example
-----------------
- Import ``GetCharLoop`` and sub-class it
- Initialize the sub-class and call it
..
Save the following to ``mine.py``
::
from functools import partial
from chloop import GetCharLoop
class Mine(GetCharLoop):
"""A sub-class of GetCharLoop"""
def __init__(self, *args, **kwargs):
# Process any extra/custom kwargs here and set some attributes
self._mything = kwargs.pop('mything', 'some default value')
super(Mine, self).__init__(*args, **kwargs)
# Add some single-key shorcuts that call methods on `self`
self._chfunc_dict_update([
('h', (self.history,
'display recent command history')),
('e', (self.errors,
'display recent errors')),
])
def somefunc(self, *args):
"""Joins the args passed to it into a string"""
args_as_one = ' '.join(args)
print(repr(args_as_one))
return args_as_one
def lame(self):
"""raise exception"""
return 1/0
if __name__ == '__main__':
m = Mine(prompt='\nmyprompt> ')
m._add_hotkey('a', lambda: print('hello'), 'say hello')
m()
Interact with the REPL
^^^^^^^^^^^^^^^^^^^^^^
Assuming the above code is in a file called ``mine.py``
::
% python mine.py
myprompt> :somefunc here are some args
u'here are some args'
myprompt> :shortcuts
'e' -- display recent errors
'h' -- display recent command history
'a' -- say hello
myprompt> a
hello
myprompt> :lame
======================================================================
Traceback (most recent call last):
File "/home/ken/chloop/chloop/__init__.py", line 232, in __call__
value = cmd_func()
File "main.py", line 33, in lame
return 1/0
ZeroDivisionError: integer division or modulo by zero
cmd: u'lame'
args: []
myprompt> :pdb
...
myprompt> e
(errors output)
myprompt> - here is a note
myprompt> - here is another note
myprompt>
Raw data
{
"_id": null,
"home_page": "https://github.com/kenjyco/chloop",
"name": "chloop",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "repl,redis,cli,command-line,command,history,kenjyco",
"author": "Ken",
"author_email": "kenjyco@gmail.com",
"download_url": "https://github.com/kenjyco/chloop/tarball/v0.2.23",
"platform": null,
"description": "Install\n-------\n\nIf you don\u2019t have `docker <https://docs.docker.com/get-docker>`__\ninstalled, install Redis and start server\n\n::\n\n % sudo apt-get install -y redis-server\n\n or\n\n % brew install redis\n % brew services start redis\n\nInstall with ``pip``\n\n::\n\n % pip3 install chloop\n\n..\n\n Optionally install ipython with ``pip3 install ipython`` to enable\n ``:ipython`` colon command on a GetCharLoop instance. Also\n ``pip3 install pdbpp`` for an improved debug experience when using\n ``:pdb`` colon command.\n\nUsage\n-----\n\nThe ``GetCharLoop`` class is provided by the ``chloop`` package. Calling\nan **instance** of this class starts a REPL session, which the user can\nend by pressing ``Ctrl`` + ``d`` or ``Ctrl`` + ``c``.\n\n See the **Example** section below.\n\nThe **first** character you type at the REPL prompt is significant.\n\nThe colon\n^^^^^^^^^\n\nHitting the ``:`` key at the prompt will allow you to enter a command\nand any arguments you need to pass to that command.\n\n- ``:docstrings`` to view docstrings of methods defined on the class\n- ``:errors`` to view colon commands that raised exceptions\n- ``:history`` view colon commands issued\n- ``:pdb`` to start a pdb session (debugging/inspection)\n- ``:ipython`` to start ipython shell\n- ``:shortcuts`` to view hotkey shortcuts\n\nAny methods added to your sub-class of ``GetCharLoop`` are callable as\n**colon commands**, as long as they do not start with an underscore\n(``_``). Methods should **only accept ``*args``**, if anything.\n\nFor any methods/commands that should not be logged to the history,\nappend the method name to the end of the ``self._DONT_LOG_CMDS`` list.\n\nThe dash\n^^^^^^^^\n\nHitting the ``-`` key at the prompt will allow you to type a note.\n\nThe question mark\n^^^^^^^^^^^^^^^^^\n\nHitting the ``?`` key at the prompt will display the class docstring(s)\nand the startup message.\n\nOther keys\n^^^^^^^^^^\n\nHitting any other key at the prompt will do one of the following:\n\n- call a **registered shortcut function** bound to the key (use\n ``:shortcuts`` command to see what is available)\n- display the character and its integer ordinal\n\nA hotkey can be bound to any callable object that accepts no arguments.\n\n Use ``functools.partial`` (if necessary) to create a callable\n accepting no arguments.\n\nAdding hotkeys (simple)\n\n- call the ``_add_hotkey`` method on your instance of ``GetCharLoop``\n (or sub-class) with the following args\n\n - ``ch``: character hotkey\n - ``func``: callable object that accepts no arguments\n - ``help_string``: a string containing short help text for hotkey\n\nAdding hotkeys (when using callables on ``self``)\n\n- call the ``self._chfunc_dict_update`` method in the ``__init__``\n method of your subclass with a list of tuples or a dict.\n\n - the keys of the dict (or first items in list of tuples) are the\n hotkey characters\n - the values of the dict (or second items in list of tuples) are\n 2-item tuples\n\n - 1st item is a **callable** that accepts no arguments\n - 2nd item is a short help string\n\n ..\n\n Note: when passing a dict, the items will be inserted in the\n alphabetical order of the help string.\n\nBasic example\n-------------\n\n::\n\n % python3 -c 'from chloop import GetCharLoop; GetCharLoop()()'\n\n > :docstrings\n ======================================================================\n Loop forever, receiving character input from user and performing actions\n\n - ^d or ^c to break the loop\n - ':' to enter a command (and any arguments)\n - the name of the command should be monkeypatched on the GetCharLoop\n instance, or be a defined method on a GetCharLoop sub-class\n - the function bound to `:command` should accept `*args` only\n - '-' to receive an input line from user (a note)\n - '?' to show the class docstring(s) and the startup message\n\n .:: docstrings ::.\n Print/return the docstrings of methods defined on this class\n\n .:: errors ::.\n Print/return any colon commands that raised exceptions (w/ traceback)\n\n .:: history ::.\n Print/return colon commands used\n\n .:: ipython ::.\n Start ipython shell. To continue back to the input loop, use 'ctrl + d'\n\n .:: pdb ::.\n Start pdb (debugger). To continue back to the input loop, use 'c'\n\n .:: shortcuts ::.\n Print/return any hotkey shortcuts defined on this class\n\n\n\n > :pdb\n [10] > /tmp/ch/venv/lib/python3.5/site-packages/chloop/__init__.py(90)__call__()\n -> continue\n (Pdb++) l\n 85 cmd = user_input.split()[0]\n 86 args = user_input.split()[1:]\n 87\n 88 if cmd == 'pdb':\n 89 import pdb; pdb.set_trace()\n 90 -> continue\n 91\n 92 if cmd == 'ipython':\n 93 from IPython import embed; embed()\n 94 continue\n 95\n (Pdb++) self._collection\n Collection('chloop-log', 'default', index_fields='cmd,status,error_type', json_fields='args,value')\n (Pdb++) self._collection.keyspace\n []\n (Pdb++) c\n\n > :ipython\n Python 3.5.1+ (default, Mar 30 2016, 22:46:26)\n Type \"copyright\", \"credits\" or \"license\" for more information.\n\n IPython 5.2.2 -- An enhanced Interactive Python.\n ? -> Introduction and overview of IPython's features.\n %quickref -> Quick reference.\n help -> Python's own help system.\n object? -> Details about 'object', use 'object??' for extra details.\n\n\n In [1]: self._collection\n Out[1]: Collection('chloop-log', 'default', index_fields='cmd,status,error_type', json_fields='args,value')\n\n In [2]: self.shortcuts\n Out[2]: <bound method GetCharLoop.shortcuts of <chloop.GetCharLoop object at 0x7f9f8ff5f5f8>>\n\n In [3]: self.docstrings\n Out[3]: <bound method GetCharLoop.docstrings of <chloop.GetCharLoop object at 0x7f9f8ff5f5f8>>\n\n In [4]:\n Do you really want to exit ([y]/n)? y\n\n\n > :shortcuts\n\n\n > - there are no shortcuts defined by default\n\n >\n\nSub-class example\n-----------------\n\n- Import ``GetCharLoop`` and sub-class it\n- Initialize the sub-class and call it\n\n..\n\n Save the following to ``mine.py``\n\n::\n\n from functools import partial\n from chloop import GetCharLoop\n\n\n class Mine(GetCharLoop):\n \"\"\"A sub-class of GetCharLoop\"\"\"\n def __init__(self, *args, **kwargs):\n # Process any extra/custom kwargs here and set some attributes\n self._mything = kwargs.pop('mything', 'some default value')\n\n super(Mine, self).__init__(*args, **kwargs)\n\n # Add some single-key shorcuts that call methods on `self`\n self._chfunc_dict_update([\n ('h', (self.history,\n 'display recent command history')),\n ('e', (self.errors,\n 'display recent errors')),\n ])\n\n\n def somefunc(self, *args):\n \"\"\"Joins the args passed to it into a string\"\"\"\n args_as_one = ' '.join(args)\n print(repr(args_as_one))\n return args_as_one\n\n def lame(self):\n \"\"\"raise exception\"\"\"\n return 1/0\n\n\n if __name__ == '__main__':\n m = Mine(prompt='\\nmyprompt> ')\n m._add_hotkey('a', lambda: print('hello'), 'say hello')\n m()\n\nInteract with the REPL\n^^^^^^^^^^^^^^^^^^^^^^\n\n Assuming the above code is in a file called ``mine.py``\n\n::\n\n % python mine.py\n\n myprompt> :somefunc here are some args\n u'here are some args'\n\n myprompt> :shortcuts\n 'e' -- display recent errors\n 'h' -- display recent command history\n 'a' -- say hello\n\n myprompt> a\n hello\n\n myprompt> :lame\n ======================================================================\n Traceback (most recent call last):\n File \"/home/ken/chloop/chloop/__init__.py\", line 232, in __call__\n value = cmd_func()\n File \"main.py\", line 33, in lame\n return 1/0\n ZeroDivisionError: integer division or modulo by zero\n\n cmd: u'lame'\n args: []\n\n myprompt> :pdb\n ...\n\n myprompt> e\n (errors output)\n\n myprompt> - here is a note\n\n myprompt> - here is another note\n\n myprompt>\n\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A Redis-backed REPL that saves command history, output, & errors",
"version": "0.2.23",
"project_urls": {
"Download": "https://github.com/kenjyco/chloop/tarball/v0.2.23",
"Homepage": "https://github.com/kenjyco/chloop"
},
"split_keywords": [
"repl",
"redis",
"cli",
"command-line",
"command",
"history",
"kenjyco"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "9b5a130bc593ca18cc365d4a001a750b71da0ef611403e55db229cdb1cc14d54",
"md5": "afc095455d3451e0647807643c604e43",
"sha256": "85f4d7e8db5c361550c16d7d7ec5ffe71204c690f9957a51be523512af1e4ec4"
},
"downloads": -1,
"filename": "chloop-0.2.23-py3-none-any.whl",
"has_sig": false,
"md5_digest": "afc095455d3451e0647807643c604e43",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 8315,
"upload_time": "2023-07-10T04:57:59",
"upload_time_iso_8601": "2023-07-10T04:57:59.865361Z",
"url": "https://files.pythonhosted.org/packages/9b/5a/130bc593ca18cc365d4a001a750b71da0ef611403e55db229cdb1cc14d54/chloop-0.2.23-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-07-10 04:57:59",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "kenjyco",
"github_project": "chloop",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "bg-helper",
"specs": []
},
{
"name": "click",
"specs": [
[
">=",
"6.0"
]
]
},
{
"name": "fs-helper",
"specs": []
},
{
"name": "redis-helper",
"specs": []
}
],
"lcname": "chloop"
}