Metadata-Version: 2.1
Name: chloop
Version: 0.2.22
Summary: A Redis-backed REPL that saves command history, output, & errors
Home-page: https://github.com/kenjyco/chloop
Download-URL: https://github.com/kenjyco/chloop/tarball/v0.2.22
Author: Ken
Author-email: kenjyco@gmail.com
License: MIT
Keywords: repl,redis,cli,command-line,command,history,kenjyco
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Terminals
License-File: LICENSE.txt
Requires-Dist: bg-helper
Requires-Dist: click (>=6.0)
Requires-Dist: fs-helper
Requires-Dist: redis-helper

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>


