Code Monkey home page Code Monkey logo

theca's Introduction

#  _   _                    
# | |_| |__   ___  ___ __ _
# | __|  _ \ / _ \/ __/ _` |
# | |_| | | |  __/ (_| (_| |
#  \__|_| |_|\___|\___\__,_|
#

example usage of theca

a simple, fully featured, command line note taking tool written in Rust.

Build Status

Features

  • Multiple profile support
  • Plaintext or 256-bit AES encrypted profiles
  • JSON profile format for easy scripting/integration
  • Traditional and condensed printing modes
  • Add/edit/delete notes
  • Add/edit note body using command line arguments, STDIN, or using the editor set via $VISUAL or $EDITOR
  • Transfer notes between profiles
  • Search notes (title or body using keyword or regex pattern)

Contents

Installation

Binaries

I've built a simple multi-(platform/arch) binary package builder (tools/theca-packer.py) based on Fabric so I can provide both x86_64 and i686 packages for unknown-linux-gnu and apple-darwin. You can either download the binary packages and install them using the packaged install.sh script, or you can use curl to install theca like so

$ curl -s https://static.bracewel.net/theca/get_theca.sh | sh

If you want to uninstall you just need to add the --uninstall flag like so

$ curl -s https://static.bracewel.net/theca/get_theca.sh | sh -s -- --uninstall

From source

All that's needed to build theca is a copy of the rustc compiler and the cargo packaging tool which can be downloaded directly from the Rust website or by running

$ curl -s https://static.rust-lang.org/rustup.sh | sh

to get the nightly rustc and cargo binaries, once those have finished building we can clone and build theca

$ git clone https://github.com/rolandshoemaker/theca.git
...

$ cd theca
$ cargo build [--release]
...

$ sudo bash tools/build.sh install [--release, --man, --bash-complete, --zsh-complete]

The cargo flag --release enables rustc optimizations. F The cargo flag --release enables rustc optimizations.or the install the flag --man will additionally install the man page and --bash-complete and --zsh-complete will additionally install the bash or zsh tab completion scripts. cargo will automatically download and compile thecas dependencies for you.

Usage

$ theca --help
theca - simple cli note taking tool

Usage:
    theca [options] new-profile [<name>]
    theca [options] encrypt-profile [--new-key KEY]
    theca [options] decrypt-profile
    theca [options] info
    theca [options] clear
    theca [options]
    theca [options] <id>
    theca [options] search [--regex, --search-body] <pattern>
    theca [options] transfer <id> to <name>
    theca [options] import <id> from <name>
    theca [options] add <title> [-s|-u] [-b BODY|-t|-]
    theca [options] edit <id> [<title>] [-s|-u|-n] [-b BODY|-t|-]
    theca [options] del <id>...

Profiles:
    -f PATH, --profile-folder PATH      Path to folder containing profile.json
                                        files [default can be set with env var 
                                        THECA_PROFILE_FOLDER].
    -p PROFILE, --profile PROFILE       Specify non-default profile [default
                                        can be set with env var 
                                        THECA_DEFAULT_PROFILE].

Printing format:
    -c, --condensed                     Use the condensed printing format.
    -j, --json                          Print list output as a JSON object.

Note list formatting:
    -l LIMIT, --limit LIMIT             Limit output to LIMIT notes
                                        [default: 0].
    -d, --datesort                      Sort notes by date.
    -r, --reverse                       Reverse list.

Input:
    -y, --yes                           Silently agree to any [y/n] prompts.

Statuses:
    -n, --none                          No status. (note default)
    -s, --started                       Started status.
    -u, --urgent                        Urgent status.

Body:
    -b BODY, --body BODY                Set body of the note to BODY.
    -t, --editor                        Drop to $EDITOR to set/edit note body.
    -                                   Set body of the note from STDIN.

Encryption:
    -e, --encrypted                     Specifies using an encrypted profile.
    -k KEY, --key KEY                   Encryption key to use for encryption/
                                        decryption, a prompt will be
                                        displayed if no key is provided.
    --new-key KEY                       Specifies the encryption key for a
                                        profile when using `encrypt-profile`,
                                        a prompt will be displayed if no key
                                        is provided.

Search:
    --search-body                       Search the body of notes instead of
                                        the title.
    --regex                             Set search pattern to regex (default
                                        is keyword).

Miscellaneous:
    -h, --help                          Display this help and exit.
    -v, --version                       Display the version of theca and exit.

First run

new default profile

theca new-profile will create the ~/.theca folder as well as the default note profile in ~/.theca/default.json. If you would like to use a non-standard profile folder you can use --profile-folder PATH.

Adding notes

adding a basic note

theca add <title> will add a note to the default profile with no body or status. These flags can be used to add a note with a status and/or a body

Statuses:
    -s, --started                       Started status.
    -u, --urgent                        Urgent status.

Body:
    -b BODY, --body BODY                Set body of the note to BODY.
    -t, --editor                        Drop to $EDITOR to set/edit note body.
    -                                   Set body of the note from STDIN.

Editing notes

editing a notes status

theca edit <id> is used to edit the title, status, or body of a note.

Statuses:
    -n, --none                          No status. (note default)
    -s, --started                       Started status.
    -u, --urgent                        Urgent status.

Body:
    -b BODY, --body BODY                Set body of the note to BODY.
    -t, --editor                        Drop to $EDITOR to set/edit note body.
    -                                   Set body of the note from STDIN.

Deleting notes

deleting some notes

theca del <id>.. deletes one or more notes specified by space separated note ids.

List all notes

list all notes

theca prints out all notes in the current profile, the following options can be used to limit/sort the resulting list

Printing format:
    -c, --condensed                     Use the condensed printing format.
    -j, --json                          Print list output as a JSON object.

Note list formatting:
    -l LIMIT, --limit LIMIT             Limit output to LIMIT notes.
                                        [default: 0].
    -d, --datesort                      Sort notes by date.
    -r, --reverse                       Reverse list.

View a single note

view a note

view a note using the short print style

theca <id> prints out a single note, including the status and body, the following options can be used to alter the output style

Printing format:
    -c, --condensed                     Use the condensed printing format.
    -j, --json                          Print list output as a JSON object.

Searching notes

searching notes

Notes can be search using either keyword or regex matching against note titles or bodies using theca search. theca doesn't support any kind of tagging (beyond the two basic statuses) but you can implement this quite simply by just appending or prepending a tag of sorts to the note title or body, e.g. "(THECA) something about theca", and then do a keyword search for "(THECA)" to get all notes tagged as such.

Search:
    --search-body                       Search the body of notes instead of
                                        the title.
    --regex                             Set search pattern to regex (default
                                        is keyword).

A quick note on statuses

During initial development of theca I spent quite a bit of time trying to figure out what statuses I should include (or if I should allow completely custom statuses) and after playing with quite a few I ended up realising I only ever used three (well... two, if that).

  • No status at all (-n or --none)
  • Started (-s or --started)
  • Urgent (-u or --urgent)

These flags can be used when adding notes, editing notes, searching notes, and listing events to either specify the note status or filter lists by status.

Non-default profiles

new non default profile

New named profiles can be created with the theca new-profile <name> command and will be stored alongside default.json in either ~/.theca/ or in the folder specified by --profile-folder PATH.

Setting the default profile

setting the THECA_DEFAULT_PROFILE env var

The default profile that theca loads (normalled default) can be changed by setting the environment variable THECA_DEFAULT_PROFILE.

Setting the default profile folder

The default profile folder can also be set via a enviroment variable, THECA_PROFILE_FOLDER.

List all profiles

list all profiles in the current profile folder

All profiles in the current profile folder can be view using theca list-profiles.

Transfer a note to another profile

transfer a note

theca transfer <id> to <name> transfers a note from the current profile (in this case default) to another profile.

Import a note from another profile

import a note

theca import <id> from <name> transfers a note from the profile <name> to the current profile (in this case default).

Encrypted profiles

new encrypted profile

Using --encrypted tells theca that it should be dealing with encrypted profiles, so using theca --encrypted new-profile secrets theca knows to create an encrypted profile and will ask you for a key to encrypt the resulting secrets.json. If you'd like not to be prompted you can specify it with the argument --key KEY.

--encrypted and --key can be used with all the other commands that read or write a profile to specify that the profile you want to use will need to be encrypted/decrypted.

Encryption:
    -e, --encrypted                     Specifies using an encrypted profile.
    -k KEY, --key KEY                   Encryption key to use for encryption/
                                        decryption, a prompt will be
                                        displayed if no key is provided.
Decrypt a encrypted profile

decrypt a profile

You can decrypt an encrypted profile in place using theca decrypt-profile.

Encrypt a plaintext profile

encrypt a profile

You can also encrypt a profile in place using theca encrypt-profile [--new-key KEY], if --new-key isn't used you will be prompted for the encryption key to use to encrypt the profile.

--new-key KEY                       Specifies the encryption key for a
                                    profile when using `encrypt-profile`,
                                    a prompt will be displayed if no key
                                    is provided.
Changing the encryption key for an already encrypted profile

change encryption key

You can also use theca encrypt-profile --new-key KEY to change the encryption key of an already encrypted profile which is pretty cool and avoids the user having to do encrypted with old key -> plaintext -> encrypted with new key!

Synchronizing profiles

If you use a synchronization tool like Dropbox, ownCloud, BitTorrent Sync, or even some obscure rsync setup you can easily share your note profiles between machines by using --profile-folder to specify a folder for your profiles that is synced and your sync'r should do the rest for you. Since theca makes transactional*-ish* updates to the profile files it should be perfectly safe, unless you concurrently edit a profile, though theca will attempt to merge changes when this happens. You could even store a profle in a git repository if you really wanted to.

JSON output mode

view list as json

view note as json

You can view a single note or note list (using theca or theca search) to output the result as either a JSON object or list of JSON objects by passing the --json or -j flag. This works with the standard limit formatting arguments like -r, -d, and -l LIMIT.

Printing format:
    -j, --json                          Print list output as a JSON object.

Note list formatting:
    -l LIMIT, --limit LIMIT             Limit output to LIMIT notes
                                        [default: 0].
    -d, --datesort                      Sort notes by date.
    -r, --reverse                       Reverse list.

Tab completion

There are preliminary bash and zsh tab completion scripts in the completion/ directory which can be installed manually or by using the --bash-complete or --zsh-complete flags with sudo bash tools/build.sh install when installing the theca binary or by default when using the binary installer.sh. They both need quite a bit of work but are still relatively usable for the time being.

man page

the man page

theca uses md2man-roff from md2man to convert docs/THECA.1.md to the roff format man page docs/THECA.1.

Contributing

If you think I've left out some necessary feature feel free to open an issue or to fork the project and work on a patch that introduces it.

I'm pretty sure there are quite a few places where memory optimizations could be made, as well as various other performance and (extensive) design improvements.

Any and all pull requests will be considered and tremendously appreciated.

Bugs

theca almost certainly contains bugs, I haven't had the time to write as many test cases as are really necessary to fully cover the codebase. if you find one, please submit a issue explaining how to trigger the bug, and if you're really awesome a test case that exposes it.

TODO

  • clean-ups/optimizations pretty much everywhere
  • ThecaProfile and ThecaItem and assosiated functions should be moved out of src/theca/lib.rs to their own file
  • list-profiles should be alphabetic
  • bash_complete.sh could use a lot of improvement, _theca also, but less...
  • save_to_file and transfer_note (and inherently the import logic) could use some work, specifically the profile changed stuff... <-- because of that we have pass pretty much all of the Args struct
  • probably the bold/plain line printing could be done cleaner... (macro perhaps?)
  • (long term) remote encrypted storage (some kind of super simple standalone REST API to hold encrypted profile blobs + client integrated into theca to retrieve them)

Development

JSON profile format

As described much more verbosely in docs/schema.json, this is what a note profile might look like

{
    "encrypted": false,
    "notes": [
        {
            "id": 1,
            "title": "\\(◕ ◡ ◕\\)",
            "status": "",
            "body": "",
            "last_touched": "2015-01-22 15:01:39 -0800"
        },
        {
            "id": 3,
            "title": "(THECA) add super secret stuff",
            "status": "",
            "body": "",
            "last_touched": "2015-01-22 15:21:01 -0800"
        }
    ]
}

Cryptographic design

theca uses the AES CBC mode symmetric cipher (implementation provided by rust-crypto) with a 256-bit key to encrypt/decrypt profile files. The key is derived using pbkdf2 (using the sha-256 PRF, again from rust-crypto) with 2056 rounds salted with the sha256 hash of the password used for the key derivation (probably not the best idea).

Basic Python implementation

During development it can be quite useful to encrypt/decrypt profiles using a scripting language like Python. A key can be derived quite quickly using hashlib and passlib

from hashlib import sha256
from passlib.utils.pbkdf2 import pbkdf2

passphrase = "DEBUG"
key = pbkdf2(
    bytes(passphrase.encode("utf-8")),
    sha256(bytes(passphrase.encode("utf-8"))).hexdigest().encode("utf-8"),
    2056,
    32,
    "hmac-sha256"
)

and the ciphertext can be decrypted using the AES implementation from pycrypto

from Crypto.Cipher import AES

# the IV makes up the first 16 bytes of the ciphertext
iv = ciphertext[0:16]
decryptor = AES.new(key, AES.MODE_CBC, iv)
plaintext = decryptor.decrypt(ciphertext[16:])

# remove any padding from the end of the final block
plaintext = plaintext[:-plaintext[-1]].decode("utf-8")

tools/build.sh

build.sh is a pretty simple bash holdall in lieu of a Makefile (ew) that really exists because I have a bad memory and forget some of the commands i'm supposed to remember. It will also set the build version environment variable (THECA_BUILD_VER) which is used to set the verson theca -v.

Usage is pretty simple

$ bash tools/build.sh
Usage: build.sh {build|build-man|test|install|clean}
  • build passes through any argument to cargo build so things like --release and --verbose work fine
  • build-man requires the md2man-roff tool to convert the Markdown man page to the roff man page format
  • test runs both all the Rust tests (cargo test) and all the Python harness tests
  • install copies the binary to /usr/local/bin. It can also be used with --man, --bash-complete, or --zsh-complete to install the man page, bash completion script, or the zsh completion script manually.
  • clean deletes the binary in ., the target/ folder, and the man page in docs/ if they exist

tools/theca_test_harness.py

theca_test_harness.py is a relatively simple python3 test harness for the compiled theca binary. It reads in JSON files which describe test cases and executes them, providing relatively simple information like passed/failed/time taken.

The harness can preform three different output checks, against

  • the resulting profile file
  • the JSON output of view, list, and search commands
  • the text output of add, edit, delete commands, etc

The python script has a number of arguments that may or may not be helpful

$ python3 tools/theca_test_harness.py -h
usage: theca_test_harness.py [-h] [-tc THECA_COMMAND] [-tf TEST_FILE] [-pt]
                             [-jt] [-tt]

test harness for the theca cli binary.

optional arguments:
  -h, --help            show this help message and exit
  -tc THECA_COMMAND, --theca-command THECA_COMMAND
                        where is the theca binary
  -tf TEST_FILE, --test-file TEST_FILE
                        path to specific test file to run
  -pt, --profile-tests  only run the profile output tests
  -jt, --json-tests     only run the json output tests
  -tt, --text-tests     only run the text output tests

Test suite file format

A JSON test suite file for theca_test_harness.py looks something like this

{
  "title": "GOOD DEFAULT TESTS",
  "desc": "testing correct input with the default profile.",
  "tests": [
  	...
  ]
}
Test formats
  • a profile result test looks something like this

      {
        "name": "add note",
        "cmds": [
          ["new-profile"],
          ["add", "this is the title"]
        ],
        "result_path": "default.json",
        "result": {
          "encrypted": false,
          "notes": [
            {
              "id": 1,
              "title": "this is the title",
              "status": "",
              "body": ""
            }
          ]
        }
      }
    
  • a JSON output test looks something like this

      {
        "name": "list",
        "cmds": [
          ["new-profile"],
          ["add", "a title this is"],
          ["add", "another title this is"],
          ["-j"]
        ],
        "result_type": "json",
        "results": [
          null,
          null,
          null,
          [
            {
              "id": 1,
              "title": "a title this is",
              "status": "",
              "body": ""
            },{
              "id": 2,
              "title": "another title this is",
              "status": "",
              "body": ""
            }
          ]
        ]
      }
    
  • a text output test looks something like this

      {
        "name": "new-profile",
        "cmds": [
          ["new-profile"]
        ],
        "result_type": "text",
        "results": [
          "creating profile 'default'\n"
        ]
      }
    

Author

theca is written by roland shoemaker ([email protected]), this is my first foray into a Rust project and my first time diving back into a systems language since 2007 or so, so please excuse the messiness of some of the code, dynamic languages have ruined me.

License

theca is licensed under the MIT license, the full text of which can be found at http://opensource.org/licenses/MIT or in LICENSE.

theca's People

Contributors

dlobatog avatar rolandshoemaker 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

theca's Issues

theca is not available at crates.io

crate allows for an easy installation of rust tools. After running crate install theca I got an error message that it's not available:

$ cargo install theca
    Updating registry `https://github.com/rust-lang/crates.io-index`
error: could not find `theca` in `registry https://github.com/rust-lang/crates.io-index`

It would be really handy to be able to install the tool by means other than executing a shell script that needs to be reviewed beforehand.

Make theca a library, so I can use it as library

I would love to have a library for this, so I can integrate it in imag - my personal information management suite for the commandline (written in Rust).

I could use the JSON API, but a native interface would be way nicer. I guess I would integrate it as notes module backend.

Occasionally unable to download get_theca

I noticed often times the domain is not responding properly to my curl requests. I tried from two different machines in different locations and networks and all I get is:

* About to connect() to static.bracewel.net port 443 (#0)
*   Trying 104.27.132.116...
* Connected to static.bracewel.net (104.27.132.116) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* NSS error -12286 (SSL_ERROR_NO_CYPHER_OVERLAP)
* Cannot communicate securely with peer: no common encryption algorithm(s).
* Error in TLS handshake, trying SSLv3...
> GET /theca/get_theca.sh HTTP/1.1
> User-Agent: curl/7.29.0
> Host: static.bracewel.net
> Accept: */*
> 
* Connection died, retrying a fresh connect
* Closing connection 0
* Issue another request to this URL: 'https://static.bracewel.net/theca/get_theca.sh'
* About to connect() to static.bracewel.net port 443 (#1)
*   Trying 104.27.132.116...
* Connected to static.bracewel.net (104.27.132.116) port 443 (#1)
* TLS disabled due to previous handshake failure
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* NSS error -12286 (SSL_ERROR_NO_CYPHER_OVERLAP)
* Cannot communicate securely with peer: no common encryption algorithm(s).
* Closing connection 1

Other curl requests the script does, like the one to https://static.rust-lang.org/rustup.sh work well. wgetting get_theca works too without a problem, downloading it from the browser works too. Let me know if you need more help.

Tested on:

  • System 1 (Fedora 21)
    curl 7.37.0 (x86_64-redhat-linux-gnu) libcurl/7.37.0 NSS/3.17.4 Basic ECC zlib/1.2.8 libidn/1.28 libssh2/1.4.3 Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz Metalink
  • System 2 (CentOS 7)
    curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.15.4 zlib/1.2.7 libidn/1.28 libssh2/1.4.3 Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz

Feature Request: Select by title or uid, default --editor on edit, color titles option, gpg encryption, and more [Feedback needed, I may add myself]

This software is really cool, I was thinking about building something very similar to this. Then I did some research on the rust ecosystem and found this. I have converted my notes over to it, I think it has a lot of potential.

Most of my suggestions actually require very little changes. It could all be done just using the profile.json

Let me know how you feel about these suggestions. I may add them myself soon as I have time available.

1. Replace symmetric encryption with GPG or additional add GPG as an encryption option I'm not a fan of the symmetric encryption, it'd be way better it if let you set a gpg key (or several for teams) and it just automatically encrypted to those keys when closing. If done well you could safely store your notes on Github.

2. Select note by UID or title Select by title and UID. It would be nice to be able to select by both.

3. Folder and Sub-folder organization Nesting/trees, so you could have programming/rust, programming/golang, programming/r. Have you used pass? This is along the lines of what I was thinking. You could also use the folder structure to provide more granularity with the gpg encryption. For example, one folder can be encrypted with 3 keys and another just encrypted with yours.

4. Option to default --editor when using edit or another short command to quickly open an editor The ability to default the edit command to open up the editor
This may require a config option, it can just be stored in the profile.json

theca edit 1 --editor 

is more than I want to type every time I edit

5. Optional color label for a note, to group similar notes and make division of different notes very clear at a glance It would also be nice to be able to set the color in the notes list, this could also be defined in the profile. When you have like 15 notes files it helps distinguish them, it could be like a label in a way.

6. Ability to very easily set a after_save hook script that runs every time a note file is saved Ability to very easily just add a script to the saving process, like a "after_save_script" attribute. So in the profile.json, one could specify a script to run when a file is saved. For example, I could define a sync.sh script, rsync the changes to another server or scp the changes to off site backup or assuming ~/.theca has a git repo like mine, one could commit and push the changes to an off site repo.

This could feasibly replace my request for gpg encryption, but personally I think adding gpg provides better security. The private gpg key would not even need to be present to encrypt, and the exposure from comparisons with symmetric encryption.

7. Alias commands to short 1 letter verisons For example, edit could also be accessed with e.

theca edit 1 --editor

becomes

theca e 1 --editor

Fails building libc with nightly

cargo build fails building libc v0.1.3 on nightly 696b7 on Linux and Windows. Could you specify which nightly builds the current codebase?

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.