Performed a large refactoring
Performed an extensive refactoring on the entire application for the sake of code-cleanliness. - Refactored out of an ad-hoc Imperative paradigm into more of a functional/declarative paradigm. IMO, this makes the application signifcantly easier to understand. - Moved away from `argparse` and into `docopt` for argument parsing - Version bump to 2.0.0 - Performed extensive refactoring on the setup.py script. Script should install to the system more cleanly now. - Made minor formatting changes to the --list flag output - Updated the README Squashed commit of the following: commit e5681bd536aa0220cdeb7884cc248db55be408c9 Author: Chris Lane <chris@chris-allen-lane.com> Date: Sat Apr 26 23:30:21 2014 -0400 Fixed many bugs Everything seems to work now, I think. commit 764ec5950cee958eb1b8333ddfcb6bcd45c28429 Author: Chris Lane <chris@chris-allen-lane.com> Date: Sat Apr 26 21:51:31 2014 -0400 Restructuring for the sake of setup.py Seem to finally have a working install script commit 5a866c23857b77ec65070dd8023cd734f2b7c242 Author: Chris Lane <chris@chris-allen-lane.com> Date: Sat Apr 26 18:01:11 2014 -0400 Nits commit a79954ba5b33d992fa6a32abffb33b161d624e3d Author: Chris Lane <chris@chris-allen-lane.com> Date: Sat Apr 26 17:53:03 2014 -0400 Implemented search commit b570a897e9a12c15affe1a72628deae31836dee2 Author: Chris Lane <chris@chris-allen-lane.com> Date: Sat Apr 26 17:11:27 2014 -0400 Nits commit 1a8d85b44457f1b2131b3e8475c5270b5d0899e3 Author: Chris Lane <chris@chris-allen-lane.com> Date: Sat Apr 26 17:02:22 2014 -0400 Still refactoring across files Trying to make the program structure clearer commit 34dffd6462e492e81ea558e2009a71051b7663c9 Author: Chris Lane <chris@chris-allen-lane.com> Date: Sat Apr 26 16:40:37 2014 -0400 Breaking app into several files This is for the sake of code-cleanliness commit 4825d678ff5f9817ccbf727ef71e5dea15ff2586 Author: Chris Lane <chris@chris-allen-lane.com> Date: Sat Apr 26 15:55:19 2014 -0400 Got syntax highlighting working commit c37d7a626d451bfca3d4a072eb9fed604085170f Author: Chris Lane <chris@chris-allen-lane.com> Date: Sat Apr 26 15:29:22 2014 -0400 Reduced verbosity of function names commit 8e626045186b37dce2480f5af1994ddfa8db79b5 Author: Chris Lane <chris@chris-allen-lane.com> Date: Sat Apr 26 15:24:41 2014 -0400 Refactored argument passing Fewer arguments now need to be passed throughout the app. commit 807ba814650010b3dd1b59d27400b3fb4fcfede7 Author: Chris Lane <chris@chris-allen-lane.com> Date: Sat Apr 26 11:40:05 2014 -0400 Working through the refactor commit e34e6540d4f8cd727e98aac68289d515a02d5fe6 Author: Chris Lane <chris@chris-allen-lane.com> Date: Thu Apr 24 20:00:10 2014 -0400 Got a basic end-to-end refactor working Have re-implemented just the most basic functionality in the "cheat2" file.
This commit is contained in:
1 parent
c03cca9298
commit
f46698b656
105 files changed
+337
-388
No files matched your search
@@ -7,7 +7,7 @@ remember.
|
||||
|
||||

|
||||
|
||||
`cheat` depends only on python.
|
||||
`cheat` depends only on `python` and `pip`.
|
||||
|
||||
|
||||
Examples
|
||||
@@ -15,9 +15,7 @@ Examples
|
||||
The next time you're forced to disarm a nuclear weapon without consulting
|
||||
Google, you may run:
|
||||
|
||||
```sh
|
||||
cheat tar
|
||||
```
|
||||
cheat tar
|
||||
|
||||
You will be presented with a cheatsheet resembling:
|
||||
|
||||
@@ -38,7 +36,7 @@ tar -xjvf /path/to/foo.tgz
|
||||
tar -cjvf /path/to/foo.tgz /path/to/foo/
|
||||
```
|
||||
|
||||
To see what cheatsheets are availble, run `cheat` with no arguments.
|
||||
To see what cheatsheets are availble, run `cheat -l`.
|
||||
|
||||
Note that, while `cheat` was designed primarily for *nix system administrators,
|
||||
it is agnostic as to what content it stores. If you would like to use `cheat`
|
||||
@@ -47,38 +45,14 @@ to store notes on your favorite cookie recipes, feel free.
|
||||
|
||||
Installing
|
||||
==========
|
||||
First install the required python dependencies with:
|
||||
|
||||
### Installing for all users (requires root)
|
||||
sudo pip install docopt pygments
|
||||
|
||||
Clone this repository and `cd` into it, then run
|
||||
Then, clone this repository, `cd` into it, and run:
|
||||
|
||||
sudo python setup.py install
|
||||
|
||||
### Installing in your home directory
|
||||
|
||||
Clone this repository and `cd` into it, then run
|
||||
|
||||
mkdir -p ~/bin
|
||||
cp cheat ~/bin
|
||||
mkdir ~/.cheat
|
||||
cp cheatsheets/* ~/.cheat
|
||||
|
||||
### Testing
|
||||
|
||||
After installing for all users or in your home directory, try `cheat tar` for instance.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
In case you got an error such as:
|
||||
> ImportError: No module named argparse
|
||||
|
||||
You're probably using python < 2.7 and you need to manually install the argparse module.
|
||||
You can do this easily with pip:
|
||||
```bash
|
||||
sudo apt-get install python-pip
|
||||
sudo pip install argparse
|
||||
```
|
||||
Other methods: https://pypi.python.org/pypi/argparse
|
||||
|
||||
Modifying Cheatsheets
|
||||
=====================
|
||||
@@ -118,15 +92,11 @@ Setting a CHEATPATH
|
||||
You can additionally instruct `cheat` to look for cheatsheets in other
|
||||
directories by exporting a `CHEATPATH` environment variable:
|
||||
|
||||
```bash
|
||||
export CHEATPATH=/path/to/my/cheats
|
||||
```
|
||||
export CHEATPATH=/path/to/my/cheats
|
||||
|
||||
You may, of course, append multiple directories to your `CHEATPATH`:
|
||||
|
||||
```bash
|
||||
export CHEATPATH=$CHEATPATH:/path/to/more/cheats
|
||||
```
|
||||
export CHEATPATH=$CHEATPATH:/path/to/more/cheats
|
||||
|
||||
You may view which directories are on your `CHEATPATH` with `cheat -d`.
|
||||
|
||||
@@ -135,18 +105,14 @@ Enabling Syntax Highlighting
|
||||
`cheat` can apply syntax highlighting to your cheatsheets if so desired. To
|
||||
enable this feature, set a `CHEATCOLORS` environment variable:
|
||||
|
||||
```bash
|
||||
export CHEATCOLORS=true
|
||||
```
|
||||
export CHEATCOLORS=true
|
||||
|
||||
Creating/Editing Cheatsheets
|
||||
----------------------------
|
||||
Provided that you have an `EDITOR` environment variable set, you may create new
|
||||
cheatsheets via:
|
||||
|
||||
```bash
|
||||
cheat -e foo
|
||||
```
|
||||
cheat -e foo
|
||||
|
||||
If the 'foo' cheatsheet already exists, it will be opened for editing.
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""cheat
|
||||
|
||||
Usage:
|
||||
cheat <cheatsheet>
|
||||
cheat -e <cheatsheet>
|
||||
cheat -s <keyword>
|
||||
cheat -l
|
||||
cheat -d
|
||||
cheat -v
|
||||
|
||||
cheat allows you to create and view interactive cheatsheets on the
|
||||
command-line. It was designed to help remind *nix system
|
||||
administrators of options for commands that they use frequently,
|
||||
but not frequently enough to remember.
|
||||
|
||||
Examples:
|
||||
To look up 'tar':
|
||||
cheat tar
|
||||
|
||||
To create or edit the cheatsheet for 'foo':
|
||||
cheat -e foo
|
||||
|
||||
Options:
|
||||
-d --directories List directories on CHEATPATH
|
||||
-e --edit Edit cheatsheet
|
||||
-l --list List cheatsheets
|
||||
-s --search Search cheatsheets for <keyword>
|
||||
-v --version Print the version number
|
||||
"""
|
||||
|
||||
# require the dependencies
|
||||
from cheat import *
|
||||
from cheat.utils import *
|
||||
from docopt import docopt
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# parse the command-line options
|
||||
options = docopt(__doc__, version='cheat 2.0.0')
|
||||
|
||||
# list directories
|
||||
if options['--directories']:
|
||||
print("\n".join(sheets.paths()))
|
||||
|
||||
# list cheatsheets
|
||||
elif options['--list']:
|
||||
print(sheets.list())
|
||||
|
||||
# create/edit cheatsheet
|
||||
elif options['--edit']:
|
||||
sheet.create_or_edit(options['<cheatsheet>'])
|
||||
|
||||
# search among the cheatsheets
|
||||
elif options['--search']:
|
||||
print(colorize(sheets.search(options['<keyword>'])))
|
||||
|
||||
# print the cheatsheet
|
||||
else:
|
||||
print(colorize(sheet.read(options['<cheatsheet>'])))
|
||||
@@ -1,320 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
cheat.py -- cheat allows you to create and view interactive cheatsheets on the
|
||||
command-line. It was designed to help remind *nix system
|
||||
administrators of options for commands that they use frequently,
|
||||
but not frequently enough to remember.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import subprocess
|
||||
from textwrap import dedent
|
||||
|
||||
DEFAULT_CHEAT_DIR = (os.environ.get('DEFAULT_CHEAT_DIR') or
|
||||
os.path.join(os.path.expanduser('~'), '.cheat'))
|
||||
USE_PYGMENTS = False
|
||||
|
||||
# NOTE remove this check if it is confirmed to work on windows
|
||||
if os.name == 'posix' and 'CHEATCOLORS' in os.environ:
|
||||
try:
|
||||
from pygments import highlight
|
||||
from pygments.util import ClassNotFound
|
||||
from pygments.lexers import get_lexer_for_filename, TextLexer
|
||||
from pygments.formatters import TerminalFormatter
|
||||
USE_PYGMENTS = True
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
def pretty_print(filename):
|
||||
"""Applies syntax highlighting to a cheatsheet and writes it to stdout"""
|
||||
try:
|
||||
if os.path.splitext(filename)[1]:
|
||||
lexer = get_lexer_for_filename(filename)
|
||||
else:
|
||||
# shell is a sensible default when there is no extension
|
||||
lexer = get_lexer_for_filename(filename + '.sh')
|
||||
|
||||
except ClassNotFound:
|
||||
lexer = TextLexer()
|
||||
|
||||
with open(filename) as istream:
|
||||
code = istream.read()
|
||||
|
||||
fmt = TerminalFormatter()
|
||||
highlight(code, lexer, fmt, sys.stdout)
|
||||
|
||||
|
||||
class CheatSheets(object):
|
||||
"""Cheatsheets database class."""
|
||||
dirs = None
|
||||
sheets = None
|
||||
|
||||
def __init__(self):
|
||||
self.dirs = self.__cheat_directories()
|
||||
# verify that we have at least one cheat directory
|
||||
if not self.dirs:
|
||||
error_msg = ('The {default} dir does not exist'
|
||||
' or the CHEATPATH var is not set.')
|
||||
print >> sys.stderr, error_msg.format(default=DEFAULT_CHEAT_DIR)
|
||||
exit(1)
|
||||
self.sheets = self.__cheat_files()
|
||||
|
||||
def __cheat_directories(self):
|
||||
"""Assembles a list of directories containing cheatsheets."""
|
||||
default_directories = [DEFAULT_CHEAT_DIR]
|
||||
try:
|
||||
import cheatsheets
|
||||
default_directories.append(cheatsheets.cheat_dir)
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
default = [default_dir for default_dir in default_directories
|
||||
if os.path.isdir(default_dir)]
|
||||
|
||||
if 'CHEATPATH' in os.environ and os.environ['CHEATPATH']:
|
||||
return [path for path in os.environ['CHEATPATH'].split(os.pathsep)
|
||||
if os.path.isdir(path)] + default
|
||||
else:
|
||||
return default
|
||||
|
||||
def __cheat_files(self):
|
||||
"""
|
||||
Assembles a dictionary of cheatsheets found in the above directories.
|
||||
"""
|
||||
cheats = {}
|
||||
for cheat_dir in reversed(self.dirs):
|
||||
cheats.update(dict([(cheat, cheat_dir)
|
||||
for cheat in os.listdir(cheat_dir)
|
||||
if not cheat.startswith('.')
|
||||
and not cheat.startswith('__')]))
|
||||
return cheats
|
||||
|
||||
def edit(self, cheat):
|
||||
"""Creates or edits a cheatsheet"""
|
||||
|
||||
# Assert that the EDITOR environment variable is set and that at least
|
||||
# 3 arguments have been given
|
||||
if 'EDITOR' not in os.environ:
|
||||
print >> sys.stderr, ('In order to create/edit a cheatsheet you '
|
||||
'must set your EDITOR environment variable '
|
||||
'to your favorite editor\'s path.')
|
||||
exit(1)
|
||||
elif os.environ['EDITOR'] == "":
|
||||
print >> sys.stderr, ('Your EDITOR environment variable is set '
|
||||
'to nothing, in order to create/edit a '
|
||||
'cheatsheet your must set it to a valid '
|
||||
'editor\'s path.')
|
||||
exit(1)
|
||||
else:
|
||||
editor = os.environ['EDITOR'].split()
|
||||
|
||||
# if the cheatsheet already exists, open it for editing
|
||||
try:
|
||||
if cheat in self.sheets:
|
||||
sheet_path = os.path.join(self.sheets[cheat], cheat)
|
||||
if os.access(sheet_path, os.W_OK):
|
||||
subprocess.call(editor + [sheet_path])
|
||||
else:
|
||||
print >> sys.stderr, ("Sheet '%s' [%s] is not editable."
|
||||
% (cheat, sheet_path))
|
||||
print ('Do you want to '
|
||||
'copy it to your user cheatsheets directory [%s] '
|
||||
'before editing?\nKeep in mind that your sheet '
|
||||
'will always be used before system-wide one.'
|
||||
% DEFAULT_CHEAT_DIR)
|
||||
awn = raw_input('[y/n] ')
|
||||
if awn != 'y':
|
||||
print ('Ok, if you want to edit system-wide sheet, '
|
||||
'please try `cheat -e <cheatsheet>` '
|
||||
'again with sudo.')
|
||||
exit(1)
|
||||
import shutil
|
||||
|
||||
# attempt to copy the cheatsheet to DEFAULT_CHEAT_DIR
|
||||
try:
|
||||
new_sheet = os.path.join(DEFAULT_CHEAT_DIR, cheat)
|
||||
shutil.copy(sheet_path, new_sheet)
|
||||
subprocess.call(editor + [new_sheet])
|
||||
|
||||
# fail gracefully if the cheatsheet cannot be copied. This
|
||||
# can happen if DEFAULT_CHEAT_DIR does not exist
|
||||
except IOError:
|
||||
print ('Could not copy cheatsheet for editing.')
|
||||
exit(1)
|
||||
|
||||
# otherwise, create it
|
||||
else:
|
||||
import cheatsheets as cs
|
||||
# Attempt to write the new cheatsheet to the user's ~/.cheat
|
||||
# dir if it exists. If it does not exist, attempt to create it.
|
||||
if os.access(DEFAULT_CHEAT_DIR, os.W_OK) or os.makedirs(DEFAULT_CHEAT_DIR):
|
||||
subprocess.call(editor
|
||||
+ [os.path.join(DEFAULT_CHEAT_DIR, cheat)])
|
||||
|
||||
# If the directory cannot be created, write to the python
|
||||
# package directory, though that will likely require the use
|
||||
# of sudo
|
||||
else:
|
||||
if os.access(sheet_path, os.W_OK):
|
||||
subprocess.call(editor
|
||||
+ [os.path.join(cs.cheat_dir, cheat)])
|
||||
else:
|
||||
error_msg = ("Couldn't create '%s' cheatsheet.\n"
|
||||
"Please retry usig sudo." % cheat)
|
||||
print >> sys.stderr, error_msg
|
||||
exit(1)
|
||||
except OSError as errno:
|
||||
print >> sys.stderr, ("Could not launch `%s` as your editor : %s"
|
||||
% (editor[0], errno.strerror))
|
||||
exit(1)
|
||||
|
||||
def list(self):
|
||||
"""Lists the cheatsheets that are currently available"""
|
||||
max_command = max([len(x) for x in self.sheets.keys()]) + 3
|
||||
return ('\n'.join(sorted(['%s [%s]' % (key.ljust(max_command), value)
|
||||
for key, value in self.sheets.items()])))
|
||||
|
||||
def __parse_cheat_command_block(self, cheat):
|
||||
"""Parse text blocks inside specified sheet file"""
|
||||
block = ""
|
||||
path = os.path.join(self.sheets[cheat], cheat)
|
||||
with open(path) as cheat_fp:
|
||||
for line in cheat_fp.readlines():
|
||||
if line == '\n':
|
||||
if block:
|
||||
yield block
|
||||
block = ""
|
||||
else:
|
||||
block += line
|
||||
if block:
|
||||
yield block
|
||||
|
||||
def search(self, term):
|
||||
"""Search for a term in sheetcheats"""
|
||||
for cheat in self.sheets.keys():
|
||||
output = ''
|
||||
for block in self.__parse_cheat_command_block(cheat):
|
||||
if term in block:
|
||||
if not output:
|
||||
output = cheat + ":\n"
|
||||
output += ''.join([" " + line + '\n' for line
|
||||
in block.split('\n')])
|
||||
if output:
|
||||
sys.stdout.write(output);
|
||||
|
||||
|
||||
# Custom action for argparse
|
||||
class ListDirectories(argparse.Action):
|
||||
"""List cheat directories and exit"""
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
print("\n".join(sheets.dirs))
|
||||
parser.exit()
|
||||
|
||||
|
||||
class ListCheatsheets(argparse.Action):
|
||||
"""List cheatsheets and exit"""
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
print(sheets.list());
|
||||
parser.exit()
|
||||
|
||||
|
||||
class EditSheet(argparse.Action):
|
||||
"""If the user wants to edit a cheatsheet"""
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
sheets.edit(values[0])
|
||||
parser.exit()
|
||||
|
||||
|
||||
class SearchSheet(argparse.Action):
|
||||
"""If the user wants to search a term inside all cheatsheets"""
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
sheets.search(values[0])
|
||||
parser.exit()
|
||||
|
||||
|
||||
def main():
|
||||
"""Main execution function"""
|
||||
global sheets
|
||||
sheets = CheatSheets()
|
||||
|
||||
desc = dedent('''
|
||||
cheat allows you to create and view interactive cheatsheets on the
|
||||
command-line. It was designed to help remind *nix system
|
||||
administrators of options for commands that they use frequently,
|
||||
but not frequently enough to remember.''').strip()
|
||||
|
||||
epi = dedent('''
|
||||
Examples:
|
||||
|
||||
To look up 'tar':
|
||||
cheat tar
|
||||
|
||||
To create or edit the cheatsheet for 'foo':
|
||||
cheat -e foo
|
||||
|
||||
To list the directories on the CHEATPATH
|
||||
cheat -d
|
||||
|
||||
To list the available cheatsheets:
|
||||
cheat -l
|
||||
''').strip()
|
||||
|
||||
parser = argparse.ArgumentParser(prog='cheat',
|
||||
description=desc, epilog=epi,
|
||||
formatter_class=argparse.
|
||||
RawDescriptionHelpFormatter)
|
||||
parser_group = parser.add_mutually_exclusive_group()
|
||||
parser_group.add_argument('sheet', metavar='cheatsheet',
|
||||
action='store', type=str, nargs='?',
|
||||
help='Look at <cheatseet>')
|
||||
parser_group.add_argument('-e', '--edit', metavar='cheatsheet',
|
||||
action=EditSheet, type=str, nargs=1,
|
||||
help='Edit <cheatsheet>')
|
||||
parser_group.add_argument('-s', '--search', metavar='term',
|
||||
action=SearchSheet, type=str, nargs=1,
|
||||
help='Search <term> inside all cheatsheets')
|
||||
parser_group.add_argument('-l', '--list',
|
||||
action=ListCheatsheets, nargs=0,
|
||||
help='List all available cheatsheets')
|
||||
parser_group.add_argument('-d', '--cheat-directories',
|
||||
action=ListDirectories, nargs=0,
|
||||
help='List all current cheat dirs')
|
||||
args = parser.parse_args()
|
||||
sheet = args.sheet
|
||||
|
||||
# Print the cheatsheet if it exists
|
||||
if not sheet or sheet in ['help', 'cheat']:
|
||||
parser.print_help()
|
||||
elif sheet in sheets.sheets:
|
||||
filename = os.path.join(sheets.sheets[sheet], sheet)
|
||||
if USE_PYGMENTS:
|
||||
pretty_print(filename)
|
||||
else:
|
||||
with open(filename) as istream:
|
||||
for line in istream:
|
||||
sys.stdout.write(line)
|
||||
|
||||
# if it does not, say so
|
||||
else:
|
||||
print >> sys.stderr, ('No cheatsheet found for %s.' % sheet)
|
||||
exit(1)
|
||||
exit()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,3 @@
|
||||
import sheet
|
||||
import sheets
|
||||
import utils
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,4 @@
|
||||
import os
|
||||
|
||||
def sheets_dir():
|
||||
return os.path.split(__file__)
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,94 @@
|
||||
from cheat import sheets
|
||||
from cheat import utils
|
||||
from cheat.utils import *
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
|
||||
def copy(current_sheet_path, new_sheet_path):
|
||||
""" Copies a sheet to a new path """
|
||||
|
||||
# attempt to copy the sheet to DEFAULT_CHEAT_DIR
|
||||
try:
|
||||
shutil.copy(current_sheet_path, new_sheet_path)
|
||||
|
||||
# fail gracefully if the cheatsheet cannot be copied. This can happen if
|
||||
# DEFAULT_CHEAT_DIR does not exist
|
||||
except IOError:
|
||||
die ('Could not copy cheatsheet for editing.')
|
||||
|
||||
|
||||
def create_or_edit(sheet):
|
||||
""" Creates or edits a cheatsheet """
|
||||
|
||||
# if the cheatsheet does not exist
|
||||
if not exists(sheet):
|
||||
create(sheet)
|
||||
|
||||
# if the cheatsheet exists and is writeable...
|
||||
elif exists(sheet) and is_writable(sheet):
|
||||
edit(sheet)
|
||||
|
||||
# if the cheatsheet exists but is not writable...
|
||||
elif exists(sheet) and not is_writable(sheet):
|
||||
# ... ask the user if we should copy the cheatsheet to her home directory for editing
|
||||
yes = prompt_yes_or_no(
|
||||
'The ' + sheet + ' sheet is not editable. Do you want to copy it to '
|
||||
'your user cheatsheets directory before editing? Keep in mind that '
|
||||
'your sheet will always be used before system-wide one.'
|
||||
)
|
||||
|
||||
# if yes, copy the cheatsheet to the home directory before editing
|
||||
if yes:
|
||||
copy(path(sheet), os.path.join(sheets.default_path(), sheet))
|
||||
edit(sheet)
|
||||
|
||||
# if no, just abort
|
||||
else:
|
||||
die('Aborting.')
|
||||
|
||||
|
||||
def create(sheet):
|
||||
""" Creates a cheatsheet """
|
||||
new_sheet_path = os.path.join(sheets.default_path(), sheet)
|
||||
|
||||
try:
|
||||
subprocess.call([editor(), new_sheet_path])
|
||||
|
||||
except OSError:
|
||||
die('Could not launch ' + editor())
|
||||
|
||||
|
||||
def edit(sheet):
|
||||
""" Opens a cheatsheet for editing """
|
||||
|
||||
try:
|
||||
subprocess.call([editor(), path(sheet)])
|
||||
|
||||
except OSError:
|
||||
die('Could not launch ' + editor())
|
||||
|
||||
|
||||
def exists(sheet):
|
||||
""" Predicate that returns true if the sheet exists """
|
||||
return sheet in sheets.get() and os.access(path(sheet), os.R_OK)
|
||||
|
||||
|
||||
def is_writable(sheet):
|
||||
""" Predicate that returns true if the sheet is writeable """
|
||||
return sheet in sheets.get() and os.access(path(sheet), os.W_OK)
|
||||
|
||||
|
||||
def path(sheet):
|
||||
""" Returns a sheet's filesystem path """
|
||||
return sheets.get()[sheet]
|
||||
|
||||
|
||||
def read(sheet):
|
||||
""" Returns the contents of the cheatsheet as a String """
|
||||
if not exists(sheet):
|
||||
die('No cheatsheet found for ' + sheet)
|
||||
|
||||
with open (path(sheet)) as cheatfile:
|
||||
return cheatfile.read()
|
||||
Loaded 100 of 105 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user