34 Commits

Author SHA1 Message Date
kojix2
5695bbe91f v0.4.5 2023-01-09 20:37:34 +09:00
kojix2
0e2f8014fd Improved error messages 2023-01-05 13:54:47 +09:00
kojix2
a6c054f596 Added comment 2023-01-05 13:45:39 +09:00
kojix2
26050a2f87 Added config option to allow configuration files to be specified later 2023-01-05 13:40:52 +09:00
kojix2
8eca14a70d Fix typo 2023-01-05 12:56:06 +09:00
kojix2
654dbfca62 Added configuration file paths and improved messages 2023-01-05 12:54:43 +09:00
kojix2
433c24e710 Added configuration section to README 2023-01-05 12:30:02 +09:00
kojix2
b1baa4073c Added --config option 2023-01-05 12:20:56 +09:00
kojix2
27a84a4df1 Minor refactoring 2023-01-05 12:05:11 +09:00
kojix2
f8bd152a63 Improved the way help is displayed
- Add `help` to the subcommand.
- Use same method to display help in stdout or stderr.
2023-01-05 11:57:46 +09:00
kojix2
f9ffca636f Rubocop auto correct 2023-01-05 11:48:19 +09:00
kojix2
83b1da9b96 Refactoring of config file reading 2023-01-05 11:40:51 +09:00
kojix2
1f41e79952 Add alias l for line and alias ls for lins as a trial (#17) 2023-01-05 10:53:23 +09:00
kojix2
85ed440c52 Add Ruby 3.2 to CI 2022-12-25 21:00:53 +09:00
kojix2
16525233f3 Update doc.yml
Use latest ruby
2022-12-16 21:04:44 +09:00
kojix2
4efdc79e30 Use actions/checkout v3 2022-10-19 09:22:26 +09:00
kojix2
19f05e57ac v0.4.4 2022-08-02 17:05:30 +09:00
kojix2
f11fd6babb Consistent variable names 2022-08-02 16:58:48 +09:00
kojix2
9d69c4322c Make configuration files available (#30) 2022-07-31 22:37:50 +09:00
kojix2
41c0d37a13 Friendly error messages 2022-05-25 16:24:13 +09:00
kojix2
a1dcc532ea Friendly error messages 2022-05-25 16:03:33 +09:00
kojix2
523700348c Create doc.yml 2022-03-24 18:47:41 +09:00
kojix2
e34ab2b097 Update README.md
Do you need commit rights to my repository?
Do you want to get admin rights and take over the project?
If so, please feel free to contact kojix2.
2022-02-13 13:05:13 +09:00
kojix2
f8fe010d27 Add Ruby3.1 to CI (#29) 2021-12-30 11:54:15 +09:00
kojix2
e76d4f279e v0.4.3 2021-11-19 14:09:46 +09:00
kojix2
3a1a29424d Remove add_development_dependency from gem 2021-11-19 14:03:57 +09:00
kojix2
b78da2388a Rubocop auto correct 2021-11-19 13:56:09 +09:00
KIKISeries
a7bb75e87d Fix a typo
S -> s
2021-07-14 09:56:47 +09:00
kojix2
ca9f97a7dc Specify the version of UnicodePlot 2021-07-12 14:56:41 +09:00
kojix2
f67a5ce913 Add comments on the run_as_executable variable 2021-07-12 14:49:34 +09:00
kojix2
dbbfd366be Remove unused variable 2021-07-11 08:59:44 +09:00
kojix2
42cadee553 Improved CI
Remove needless line
2021-07-11 08:43:47 +09:00
kojix2
e689c69838 Update CI
* Enable bundler-cache
2021-07-11 08:38:05 +09:00
kojix2
c53169e9ee Update README.md (#24) 2021-07-03 07:22:19 +09:00
11 changed files with 207 additions and 44 deletions

View File

@@ -6,13 +6,12 @@ jobs:
runs-on: ${{ matrix.os }}-latest runs-on: ${{ matrix.os }}-latest
strategy: strategy:
matrix: matrix:
os: ['ubuntu', 'macos'] os: [ 'ubuntu', 'macos' ]
ruby: [ '2.4', '2.5', '2.6', '2.7', '3.0' ] ruby: [ '2.4', '2.5', '2.6', '2.7', '3.0', '3.1', '3.2' ]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1 - uses: ruby/setup-ruby@v1
with: with:
ruby-version: ${{ matrix.ruby }} ruby-version: ${{ matrix.ruby }}
- run: gem install bundler bundler-cache: true
- run: bundle install
- run: bundle exec rake test - run: bundle exec rake test

23
.github/workflows/doc.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: doc
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
with:
ruby-version: ruby
- name: Generate document
run: gem install -N yard && yard doc
- name: Publish Documentation on GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./doc

View File

@@ -4,3 +4,9 @@ source 'https://rubygems.org'
# Specify your gem's dependencies in youplot.gemspec # Specify your gem's dependencies in youplot.gemspec
gemspec gemspec
group :test do
gem 'rake'
gem 'simplecov'
gem 'test-unit'
end

View File

@@ -7,7 +7,7 @@
<a href="https://rubydoc.info/gems/youplot/"><img alt="Docs Stable" src="https://img.shields.io/badge/docs-stable-blue.svg"></a> <a href="https://rubydoc.info/gems/youplot/"><img alt="Docs Stable" src="https://img.shields.io/badge/docs-stable-blue.svg"></a>
<a href="LICENSE.txt"><img alt="The MIT License" src="https://img.shields.io/badge/license-MIT-blue.svg"></a> <a href="LICENSE.txt"><img alt="The MIT License" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
YouPlot is a command line tool that draws plots in the terminal. YouPlot is a command line tool that draws plots on the terminal.
:bar_chart: Powered by [UnicodePlot](https://github.com/red-data-tools/unicode_plot.rb) :bar_chart: Powered by [UnicodePlot](https://github.com/red-data-tools/unicode_plot.rb)
</div> </div>
@@ -189,7 +189,7 @@ The following sub-commands are available.
* The `--help` option will show more detailed options for each subcommand. * The `--help` option will show more detailed options for each subcommand.
* `uplot hist --help` * `uplot hist --help`
### Set columns as x-axis or y-axis? ### Set columns as x-axis or y-axis
* YouPlot treats the first column as the X axis and the second column as the Y axis. When working with multiple series, the first column is the X axis, the second column is series Y1, the third column is series Y2, and so on. * YouPlot treats the first column as the X axis and the second column as the Y axis. When working with multiple series, the first column is the X axis, the second column is series Y1, the third column is series Y2, and so on.
* If you pass only one column of data for `line` and `bar`, YouPlot will automatically use a sequential number starting from 1 as the X-axis. * If you pass only one column of data for `line` and `bar`, YouPlot will automatically use a sequential number starting from 1 as the X-axis.
@@ -203,7 +203,7 @@ The following sub-commands are available.
### Categorical data ### Categorical data
* With gne datamash, you can manage to handle categorized data. * With GNU datamash, you can manage to handle categorized data.
* `cat test/fixtures/iris.csv | sed '/^$/d' | datamash --header-in --output-delimiter=: -t, -g5 collapse 3,4 | cut -f2-3 -d: | sed 's/:/\n/g' | uplot s -d, -T --fmt xyxy` * `cat test/fixtures/iris.csv | sed '/^$/d' | datamash --header-in --output-delimiter=: -t, -g5 collapse 3,4 | cut -f2-3 -d: | sed 's/:/\n/g' | uplot s -d, -T --fmt xyxy`
* This is not so easy... * This is not so easy...
@@ -211,6 +211,14 @@ The following sub-commands are available.
* Not yet supported. * Not yet supported.
### YouPlot Configuration (youplotrc)
You can specify default options in a configuration file in YAML format. For more information, enter the following command.
```
uplot --config
```
## Tools that are useful to use with YouPlot ## Tools that are useful to use with YouPlot
* [csvtk](https://github.com/shenwei356/csvtk) * [csvtk](https://github.com/shenwei356/csvtk)
@@ -241,6 +249,10 @@ bundle exec rake install # Installation from source code
bundle exec exe/uplot # Run youplot (Try out the edited code) bundle exec exe/uplot # Run youplot (Try out the edited code)
``` ```
Do you need commit rights to my repository?
Do you want to get admin rights and take over the project?
If so, please feel free to contact us.
### Acknowledgements ### Acknowledgements
* [sampo grafiikka](https://jypg.net/sampo_grafiikka) - Project logo creation * [sampo grafiikka](https://jypg.net/sampo_grafiikka) - Project logo creation

View File

@@ -6,6 +6,12 @@ require_relative 'youplot/parameters'
require_relative 'youplot/command' require_relative 'youplot/command'
module YouPlot module YouPlot
# @run_as_executable = true / false
# YouPlot behaves slightly differently when run as a command line tool
# and when run as a script (e.g. for testing). In the event of an error,
# when run as a command line tool, YouPlot will display a short error message
# and exit abnormally. When run as a script, it will just raise an error.
@run_as_executable = false
class << self class << self
attr_accessor :run_as_executable attr_accessor :run_as_executable
@@ -13,5 +19,4 @@ module YouPlot
@run_as_executable @run_as_executable
end end
end end
@run_as_executable = false
end end

View File

@@ -127,11 +127,10 @@ module YouPlot
def plot_xyxy(data, method1, params) def plot_xyxy(data, method1, params)
headers = data.headers headers = data.headers
series = data.series series2 = data.series
.map { |s| s.map(&:to_f) }
.each_slice(2).to_a
method2 = get_method2(method1) method2 = get_method2(method1)
series.map! { |s| s.map(&:to_f) }
series2 = series.each_slice(2).to_a
series = nil
params.name ||= headers[0] if headers params.name ||= headers[0] if headers
params.xlim ||= series2.map(&:first).flatten.minmax # why need? params.xlim ||= series2.map(&:first).flatten.minmax # why need?
params.ylim ||= series2.map(&:last).flatten.minmax # why need? params.ylim ||= series2.map(&:last).flatten.minmax # why need?

View File

@@ -63,9 +63,15 @@ module YouPlot
# normal mode # normal mode
else else
# Sometimes the input file does not end with a newline code. # Sometimes the input file does not end with a newline code.
while (input = Kernel.gets(nil)) begin
begin
input = Kernel.gets(nil)
rescue Errno::ENOENT => e
warn e.message
next
end
main(input) main(input)
end end until input
end end
end end
@@ -135,7 +141,12 @@ module YouPlot
rescue CSV::MalformedCSVError => e rescue CSV::MalformedCSVError => e
warn 'Failed to parse the text. ' warn 'Failed to parse the text. '
warn 'Please try to set the correct character encoding with --encoding option.' warn 'Please try to set the correct character encoding with --encoding option.'
raise e warn e.backtrace.grep(/youplot/).first
exit 1
rescue ArgumentError => e
warn 'Failed to parse the text. '
warn e.backtrace.grep(/youplot/).first
exit 1
end end
data data
@@ -149,9 +160,9 @@ module YouPlot
@backend.barplot(data, params, count: true, reverse: options[:reverse]) @backend.barplot(data, params, count: true, reverse: options[:reverse])
when :hist, :histogram when :hist, :histogram
@backend.histogram(data, params) @backend.histogram(data, params)
when :line, :lineplot when :line, :lineplot, :l
@backend.line(data, params, options[:fmt]) @backend.line(data, params, options[:fmt])
when :lines, :lineplots when :lines, :lineplots, :ls
@backend.lines(data, params, options[:fmt]) @backend.lines(data, params, options[:fmt])
when :scatter, :s when :scatter, :s
@backend.scatter(data, params, options[:fmt]) @backend.scatter(data, params, options[:fmt])

View File

@@ -9,7 +9,8 @@ module YouPlot
class Error < StandardError; end class Error < StandardError; end
attr_reader :command, :options, :params, attr_reader :command, :options, :params,
:main_parser, :sub_parser :main_parser, :sub_parser,
:config_file, :config
def initialize def initialize
@command = nil @command = nil
@@ -30,6 +31,61 @@ module YouPlot
@params = Parameters.new @params = Parameters.new
end end
def apply_config_file
return if !config_file && find_config_file.nil?
read_config_file
configure
end
def config_file_candidate_paths
# keep the order of the paths
paths = []
paths << ENV['MYYOUPLOTRC'] if ENV['MYYOUPLOTRC']
paths << '.youplot.yml'
paths << '.youplotrc'
if ENV['HOME']
paths << File.join(ENV['HOME'], '.youplotrc')
paths << File.join(ENV['HOME'], '.youplot.yml')
paths << File.join(ENV['HOME'], '.config', 'youplot', 'youplotrc')
paths << File.join(ENV['HOME'], '.config', 'youplot', 'youplot.yml')
end
paths
end
def find_config_file
config_file_candidate_paths.each do |file|
path = File.expand_path(file)
next unless File.exist?(path)
@config_file = path
ENV['MYYOUPLOTRC'] = path
return @config_file
end
nil
end
def read_config_file
require 'yaml'
@config = YAML.load_file(config_file)
end
def configure
option_members = @options.members
param_members = @params.members
# It would be more useful to be able to configure by plot type
config.each do |k, v|
k = k.to_sym
if option_members.include?(k)
@options[k] ||= v
elsif param_members.include?(k)
@params[k] ||= v
else
raise Error, "Unknown option/param in config file: #{k}"
end
end
end
def create_base_parser def create_base_parser
OptionParser.new do |parser| OptionParser.new do |parser|
parser.program_name = 'YouPlot' parser.program_name = 'YouPlot'
@@ -95,7 +151,7 @@ module YouPlot
parser.on('-M', '--monochrome', TrueClass, 'no colouring even if writing to a tty') do |_v| parser.on('-M', '--monochrome', TrueClass, 'no colouring even if writing to a tty') do |_v|
UnicodePlot::IOContext.define_method(:color?) { false } # FIXME UnicodePlot::IOContext.define_method(:color?) { false } # FIXME
end end
parser.on('--encoding STR', String, 'Specify the input encoding') do |v| parser.on('--encoding STR', String, 'specify the input encoding') do |v|
options[:encoding] = v options[:encoding] = v
end end
# Optparse adds the help option, but it doesn't show up in usage. # Optparse adds the help option, but it doesn't show up in usage.
@@ -104,6 +160,9 @@ module YouPlot
puts parser.help puts parser.help
exit if YouPlot.run_as_executable? exit if YouPlot.run_as_executable?
end end
parser.on('--config FILE', 'specify a config file') do |v|
@config_file = v
end
parser.on('--debug', TrueClass, 'print preprocessed data') do |v| parser.on('--debug', TrueClass, 'print preprocessed data') do |v|
options[:debug] = v options[:debug] = v
end end
@@ -135,6 +194,7 @@ module YouPlot
colors color show the list of available colors colors color show the list of available colors
General options: General options:
--config print config file info
--help print command specific help menu --help print command specific help menu
--version print the version of YouPlot --version print the version of YouPlot
MSG MSG
@@ -142,10 +202,36 @@ module YouPlot
# Help for the main parser is simple. # Help for the main parser is simple.
# Simply show the banner above. # Simply show the banner above.
main_parser.on('--help', 'print sub-command help menu') do main_parser.on('--help', 'print sub-command help menu') do
puts main_parser.banner show_main_help
puts
exit if YouPlot.run_as_executable?
end end
main_parser.on('--config', 'show config file info') do
show_config_info
end
end
def show_main_help(out = $stdout)
out.puts main_parser.banner
out.puts
exit if YouPlot.run_as_executable?
end
def show_config_info
if ENV['MYYOUPLOTRC']
puts "config file : #{ENV['MYYOUPLOTRC']}"
puts config.inspect
else
puts <<~EOS
Configuration file not found.
It should be a YAML file, like this example:
width : 40
height : 20
By default, YouPlot will look for the configuration file in these locations:
#{config_file_candidate_paths.map { |s| ' ' + s }.join("\n")}
If you have the file elsewhere, you can specify its location with the `MYYOUPLOTRC` environment variable.
EOS
end
exit if YouPlot.run_as_executable?
end end
def sub_parser_add_symbol def sub_parser_add_symbol
@@ -215,10 +301,13 @@ module YouPlot
case command case command
# If you type only `uplot` in the terminal. # If you type only `uplot` in the terminal.
# Output help to standard error output.
when nil when nil
warn main_parser.banner show_main_help($stderr)
warn "\n"
exit 1 if YouPlot.run_as_executable? # Output help to standard output.
when :help
show_main_help
when :barplot, :bar when :barplot, :bar
sub_parser_add_symbol sub_parser_add_symbol
@@ -241,14 +330,14 @@ module YouPlot
params.nbins = v params.nbins = v
end end
when :lineplot, :line when :lineplot, :line, :l
sub_parser_add_canvas sub_parser_add_canvas
sub_parser_add_grid sub_parser_add_grid
sub_parser_add_fmt_yx sub_parser_add_fmt_yx
sub_parser_add_ylim sub_parser_add_ylim
sub_parser_add_xlim sub_parser_add_xlim
when :lineplots, :lines when :lineplots, :lines, :ls
sub_parser_add_canvas sub_parser_add_canvas
sub_parser_add_grid sub_parser_add_grid
sub_parser_add_fmt_xyxy sub_parser_add_fmt_xyxy
@@ -277,14 +366,19 @@ module YouPlot
options[:color_names] = v options[:color_names] = v
end end
# Currently it simply displays the configuration file,
# but in the future this may be changed to open a text editor like Vim
# to edit the configuration file.
when :config
show_config_info
else else
error_message = "uplot: unrecognized command '#{command}'" error_message = "YouPlot: unrecognized command '#{command}'"
if YouPlot.run_as_executable? raise Error, error_message unless YouPlot.run_as_executable?
warn error_message
exit 1 warn error_message
else exit 1
raise Error, error_message
end
end end
end end
@@ -292,7 +386,7 @@ module YouPlot
begin begin
create_main_parser.order!(argv) create_main_parser.order!(argv)
rescue OptionParser::ParseError => e rescue OptionParser::ParseError => e
warn "uplot: #{e.message}" warn "YouPlot: #{e.message}"
exit 1 if YouPlot.run_as_executable? exit 1 if YouPlot.run_as_executable?
end end
@@ -301,7 +395,14 @@ module YouPlot
begin begin
create_sub_parser&.parse!(argv) create_sub_parser&.parse!(argv)
rescue OptionParser::ParseError => e rescue OptionParser::ParseError => e
warn "uplot: #{e.message}" warn "YouPlot: #{e.message}"
exit 1 if YouPlot.run_as_executable?
end
begin
apply_config_file
rescue StandardError => e
warn "YouPlot: #{e.message}"
exit 1 if YouPlot.run_as_executable? exit 1 if YouPlot.run_as_executable?
end end
end end

View File

@@ -1,5 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
module YouPlot module YouPlot
VERSION = '0.4.2' VERSION = '0.4.5'
end end

View File

@@ -69,6 +69,12 @@ class YouPlotIRISTest < Test::Unit::TestCase
assert_equal fixture('iris-lineplot.txt'), @stderr_file.read assert_equal fixture('iris-lineplot.txt'), @stderr_file.read
end end
# l is an undocumented alias of lineplot.
test :l do
YouPlot::Command.new(['l', '-H', '-d,', '-t', 'IRIS-LINEPLOT']).run
assert_equal fixture('iris-lineplot.txt'), @stderr_file.read
end
test :lineplots do test :lineplots do
YouPlot::Command.new(['lineplots', '-H', '-d,', '-t', 'IRIS-LINEPLOTS']).run YouPlot::Command.new(['lineplots', '-H', '-d,', '-t', 'IRIS-LINEPLOTS']).run
assert_equal fixture('iris-lineplots.txt'), @stderr_file.read assert_equal fixture('iris-lineplots.txt'), @stderr_file.read
@@ -79,6 +85,12 @@ class YouPlotIRISTest < Test::Unit::TestCase
assert_equal fixture('iris-lineplots.txt'), @stderr_file.read assert_equal fixture('iris-lineplots.txt'), @stderr_file.read
end end
# ls is an undocumented alias of lineplots.
test :ls do
YouPlot::Command.new(['lines', '-H', '-d,', '-t', 'IRIS-LINEPLOTS']).run
assert_equal fixture('iris-lineplots.txt'), @stderr_file.read
end
test :scatter do test :scatter do
YouPlot::Command.new(['scatter', '-H', '-d,', '-t', 'IRIS-SCATTER']).run YouPlot::Command.new(['scatter', '-H', '-d,', '-t', 'IRIS-SCATTER']).run
assert_equal fixture('iris-scatter.txt'), @stderr_file.read assert_equal fixture('iris-scatter.txt'), @stderr_file.read

View File

@@ -19,10 +19,5 @@ Gem::Specification.new do |spec|
spec.executables = %w[uplot youplot] spec.executables = %w[uplot youplot]
spec.require_paths = ['lib'] spec.require_paths = ['lib']
spec.add_runtime_dependency 'unicode_plot' spec.add_dependency 'unicode_plot', '>= 0.0.5'
spec.add_development_dependency 'bundler'
spec.add_development_dependency 'rake'
spec.add_development_dependency 'rubocop'
spec.add_development_dependency 'simplecov'
spec.add_development_dependency 'test-unit'
end end