Compare commits

...

5 Commits

7 changed files with 224 additions and 65 deletions

View File

@ -1,5 +1,10 @@
# Changelog
## 1.1.2
* Fixed bug where "hostname" portion of author is missing or garbled.
* Added CLI completion scripts for bash and zsh. [Thanks, jlxip!](https://github.com/jlxip)
* Minor tweaks and additions to the documentation.
## 1.1.1
* Make discarded message response more prominent
* Try nano if /usr/bin/vim is not set

143
README.md
View File

@ -14,6 +14,7 @@ Iris is strictly text-based, requiring no GUI or web servers.
* [Text Features/Markup](#text-featuresmarkup)
* [Philosophy](#philosophy)
* [Tests](#tests)
* [Cutting A Release](#cutting-a-release)
* [Technical Bits](#technical-bits)
* [License](#license)
@ -36,7 +37,7 @@ Iris has a readline interface that can be used to navigate the message corpus.
```bash
%> iris
Welcome to Iris v. 1.1.1. Type "help" for a list of commands.; Ctrl-D or 'quit' to leave.
Welcome to Iris v. 1.1.2. Type "help" for a list of commands.; Ctrl-D or 'quit' to leave.
| ID | U | TIMESTAMP | AUTHOR | TITLE
| 1 | | 2018-01-24T05:49:53Z | jimmy_foo@ctrl-c.club | Welcome!
@ -368,7 +369,7 @@ This outputs the current version of Iris, along with messsage, topic, and author
```bash
jennie_minnie@ctrl-c.club~> info
Iris 1.1.1
Iris 1.1.2
22 topics, 0 unread.
50 messages, 0 unread.
10 authors.
@ -385,25 +386,50 @@ This displays helpful reminders of the commands that Iris supports.
There are a few options you can pass in from the command-line:
* [--version, -v](#--version-v)
* [--stats, -s](#--stats-s)
* [--interactive, -i](#--interactive-i)
* [--mark-all-read](#--mark-all-read)
* [--debug](#--debug)
* [--dump, -d](#--dump-d)
* [--help, -h](#--help-h)
* [--debug](#--debug)
* [--interactive, -i](#--interactive-i)
* [--mark-all-read](#--mark-all-read)
* [--stats, -s](#--stats-s)
* [--test-file, -s](#--test-file)
* [--version, -v](#--version-v)
### --version/-v
### --debug
This displays the current version of Iris and exits.
This option turns on debug mode. Warnings and errors will be output as the program is used.
```bash
iris --version
```
Having these messages constantly appear can be distracting or annoying during regular Iris usage, but are useful when tracking down issues.
```bash
Iris 1.1.1
```
This option works in both interactive and non-interactive mode.
---
### --dump/-d
This reads the entire message corpus and outputs it as a stream of JSON data, suitable for piping into a backup file, `jq` parser, or similar.
This command does not enter Iris' interactive mode.
---
### --help/-h
This command displays a complete list of options that Iris recognizes.
---
### --interactive/-i
This command enters Iris' interactive mode, the default mode with which users can compose and read topics and replies.
This is the mode that Iris enters if no options are passed on the command-line.
---
### --mark-all-read
This command simply marks every message as read in Iris. It's a quick way to get to "Irisbox Zero".
---
@ -418,7 +444,7 @@ iris --stats
```
```bash
Iris 1.1.1
Iris 1.1.2
22 topics, 0 unread.
50 messages, 0 unread.
10 authors.
@ -426,39 +452,6 @@ Iris 1.1.1
---
### --interactive/-i
This command enters Iris' interactive mode, the default mode with which users can compose and read topics and replies.
This is the mode that Iris enters if no options are passed on the command-line.
---
### --mark-all-read
This command simply marks every message as read in Iris. It's a quick way to get to "Irisbox Zero".
---
### --dump/-d
This reads the entire message corpus and outputs it as a stream of JSON data, suitable for piping into a backup file, `jq` parser, or similar.
This command does not enter Iris' interactive mode.
---
### --debug
This option turns on debug mode. Warnings and errors will be output as the program is used.
Having these messages constantly appear can be distracting or annoying during regular Iris usage, but are useful when tracking down issues.
This option works in both interactive and non-interactive mode.
---
### --test-file/-f
```bash
@ -471,9 +464,17 @@ This option works in both interactive and non-interactive mode.
---
### --help/-h
### --version/-v
This command displays a complete list of options that Iris recognizes.
This displays the current version of Iris and exits.
```bash
iris --version
```
```bash
Iris 1.1.2
```
## Text Features/Markup
@ -596,7 +597,7 @@ Iris must:
* Deleted or edited messages should leave flags or placeholders for other users to know that other content was there before.
* The Iris client should expect that any message file could be missing, altered, or corrupted, and should handle those cases gracefully.
* Be portable
* All Iris files should be human-readable (and -editable, in a pinch)
* All Iris data files should be human-readable (and -editable, in a pinch)
* The use of the official Iris client should be optional for a user to manage his or her messages. A text editor should suffice.
* Other clients which follow the Iris file format should work seamlessly with the official Iris client.
* Be secure
@ -605,7 +606,7 @@ Iris must:
* Be a teacher
* Code should be clean, well-organized, and readable.
* Be limited in scope
* The source code should not exceed 1,000 LOC
* The source code should not exceed 1,000 SLOC
## Tests
@ -622,6 +623,42 @@ To run the tests:
ruby tests/iris_test.rb
```
```bash
Run options: --seed 11507
# Running:
.........................SSS.......SS.......S.....SSSSSSS....SSSSS
Finished in 0.107785s, 612.3294 runs/s, 677.2734 assertions/s.
66 runs, 73 assertions, 0 failures, 0 errors, 18 skips
You have skipped tests. Run with --verbose for details.
```
## Cutting A Release
### Prep
* Make all updates in an appropriately named branch. (ie. `1.1.2`)
* Make sure all commits are clean.
* Make sure tests pass.
### Updates
* Change version number in `iris.rb`
* Change version numbers in documentation `README.md`
* Add new version and details to `CHANGELOG`
* Create new commit for release (Named "Bump Iris version to 1.1.2" or similar)
### Make the Sausage
* Push the branch
* `git push origin`
* Merge the branch (Fast-forward only, for a linear commit history)
* Tag the release
* `git tag 1.1.2`
* Push the tags
* `git push origin --tags`
## Technical Bits
* [Dependencies](#dependencies)

View File

@ -10,6 +10,8 @@
* Flesh out technical sections
### Bugs
* Terrible slowdown when refreshing topics
* Performance is fine when no new topics show up
* Is `Time.now.utc.iso8601` working as expected?
* Fix bug when people are posting from different time zones
* Fix message ordering when editing/deleting multiple messages

41
completions/bash Executable file
View File

@ -0,0 +1,41 @@
#!/bin/bash -eu
# This is a bash completion script for iris
# It should be copied to /usr/share/bash-completion/completions/iris
_iris_module() {
local cur prev OPTS
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
case $prev in
-f | --test-file)
return 0 # File
;;
esac
case $cur in
--*)
OPTS="--debug
--dump
--help
--interactive
--stats
--test-file
--version"
;;
*)
OPTS="-d
-f
-h
-i
-s
-v"
;;
esac
COMPREPLY=( $(compgen -W "${OPTS[*]}" -- $cur) )
}
complete -F _iris_module -o bashdefault -o default iris

29
completions/zsh Executable file
View File

@ -0,0 +1,29 @@
#compdef _iris iris
# This is a zsh completion script for iris
# It should be copied to /usr/share/zsh/functions/Completion/Unix/_iris
function _iris {
local context state state_descr line
typeset -A opt_args
_arguments -C \
"--debug[Print warnings and debug informtation during use]" \
"-d[Dump entire message corpus out]" \
"--dump[Dump entire message corpus out]" \
"-h[Show help information]" \
"--help[Show help information]" \
"-i[Enter interactive mode (default)]" \
"--interactive[Enter interactive mode (default)]" \
"--mark-all-read[Mark every message in Iris as \"read\".]"
"-s[Display Iris version and message stats]" \
"--stats[Display Iris version and message stats]" \
"-f[Use the specified test file for messages]:f:->f" \
"--test-file[Use the specified test file for messages]:f:->f" \
"-v[Display the current version of Iris]" \
"--version[Display the current version of Iris]" \
if [ "$state" = "f" ]; then
_files
fi
}

25
iris.rb
View File

@ -22,18 +22,31 @@ class String
end
class Config
VERSION = '1.1.1'
VERSION = '1.1.2'
MESSAGE_FILE = "#{ENV['HOME']}/.iris.messages"
HISTORY_FILE = "#{ENV['HOME']}/.iris.history"
IRIS_SCRIPT = __FILE__
USER = ENV['USER'] || ENV['LOGNAME'] || ENV['USERNAME']
HOSTNAME = `hostname -d`.chomp
AUTHOR = "#{USER}@#{HOSTNAME}"
ENV_EDITOR = ENV['EDITOR'].presence || `which nano`.chomp.presence
@@debug_mode = false
def self.hostname
return @hostname if @hostname
hostname = `hostname`.chomp
hostname = 'localhost' if hostname.empty?
return @hostname = hostname if hostname == 'localhost'
@hostname = hostname.split('.')[-2..-1].compact.join('.')
end
def self.author
user = ENV['USER'] || ENV['LOGNAME'] || ENV['USERNAME']
@author ||= "#{user}@#{self.hostname}"
end
def self.find_files
(`ls /home/**/.iris.messages`).split("\n")
end
@ -343,7 +356,7 @@ end
class Message
attr_reader :timestamp, :edit_hash, :author, :parent, :message, :errors, :is_deleted
def initialize(message, parent = nil, author = Config::AUTHOR, edit_hash = nil, timestamp = Time.now.utc.iso8601, is_deleted = nil)
def initialize(message, parent = nil, author = Config.author, edit_hash = nil, timestamp = Time.now.utc.iso8601, is_deleted = nil)
@message = message
@parent = parent
@author = author
@ -890,7 +903,7 @@ class Interface
end
def prompt
"#{Config::AUTHOR}~> "
"#{Config.author}~> "
end
def initialize(args)

View File

@ -24,16 +24,48 @@ describe Config do
_(Config::HISTORY_FILE).must_match /\/\.iris\.history$/
end
it 'has the username' do
_(Config::USER).must_equal 'jerryberry'
end
describe '.hostname' do
before do
Config.instance_variable_set(:@hostname, nil)
end
it 'has a hostname' do
_(Config::HOSTNAME).wont_be_nil
it 'has a hostname' do
_(Config.hostname).wont_be_nil
end
it 'correctly interprets an empty string' do
Config.expects(:`).with('hostname').returns('')
_(Config.hostname).must_equal 'localhost'
end
it 'correctly interprets localhost' do
Config.instance_variable_set(:@hostname, nil)
Config.expects(:`).with('hostname').returns('localhost')
_(Config.hostname).must_equal 'localhost'
end
it 'correctly interprets a subdomain' do
Config.instance_variable_set(:@hostname, nil)
Config.expects(:`).with('hostname').returns('example.com')
_(Config.hostname).must_equal 'example.com'
end
it 'correctly interprets a subsubdomain' do
Config.instance_variable_set(:@hostname, nil)
Config.expects(:`).with('hostname').returns('foo.example.com')
_(Config.hostname).must_equal 'example.com'
end
it 'correctly interprets an arbitrary number of subdomains' do
Config.instance_variable_set(:@hostname, nil)
Config.expects(:`).with('hostname').returns('foo.bar.baz.quux.example.com')
_(Config.hostname).must_equal 'example.com'
end
end
it 'has the author' do
_(Config::AUTHOR).must_equal "#{Config::USER}@#{Config::HOSTNAME}"
user = 'jerryberry'
_(Config.author).must_equal "#{user}@#{Config.hostname}"
end
it 'has the $EDITOR environment variable' do