howzit 2.1.13 → 2.1.15

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f0fc931036b21c7bb13c805751a146432d14c40a9a910fd9999aa42fb34658cb
4
- data.tar.gz: 31b927c85e4c7ba6938eff929e7670c1a997d79f21053ce230da3a1a5ca4b246
3
+ metadata.gz: 801a2edf83210d0abd3cf17ab9c9259469429478c48b8245df7475bde19c6676
4
+ data.tar.gz: c47dd24e16f255fcbbd0ac5acadb3c57f423bda0237bbbb85b43f8c82e08b0db
5
5
  SHA512:
6
- metadata.gz: 6382fd78151da4a021d605276121fc48f0b1cb7692ee3a4657fd4dee820577f0f5357aa98be565dd120e440619906b1881da2269fe0e53c2321160a34dee26ac
7
- data.tar.gz: d402a1dcf7715f04ed32fc282450c4132bf13cd3a43830eb464c298f79dc86fa4c47f30a6bd8d3698e588468f107b0b4eae6ad90c89195d878ef1f610846ab78
6
+ metadata.gz: f8ea4385da70cb5cf7e8d66b5352f164d7cee71b050cf47a544539bf61d0ffd95b4c46f77347b8cf016fd50bd9edf6f7fe1b088fb4f8d324af9343c833334204
7
+ data.tar.gz: 7bc8190df842331c74ab4dc0146262b886c1174d3fcf2faef35dc536d0622fe29c2868c4db6e2067e1198c801116d8b67bb0272214cfe8a75dd210a86ec8db66
data/.gitignore CHANGED
@@ -42,3 +42,4 @@ Gemfile.lock
42
42
  # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
43
43
  .rvmrc
44
44
  results.log
45
+ html
data/.irbrc ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+ `gem rdoc binbundle --ri`
3
+
4
+ # rubocop:disable Style/MixinUsage
5
+ include Howzit # standard:disable all
6
+ # rubocop:enable Style/MixinUsage
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ ### 2.1.15
2
+
3
+ 2024-08-07 13:10
4
+
5
+ #### FIXED
6
+
7
+ - Prompt for editor when $EDITOR is not defined
8
+ - Use exec for CLI editors provide a separate process
9
+ - Remove tests for editor in main executable
10
+
11
+ ### 2.1.14
12
+
13
+ 2024-08-06 16:36
14
+
15
+ #### IMPROVED
16
+
17
+ - Better algorithm for best match when `multiple_matches: best` is set
18
+
1
19
  ### 2.1.13
2
20
 
3
21
  2024-08-05 12:04
data/README.md CHANGED
@@ -2,13 +2,13 @@
2
2
  # Howzit
3
3
 
4
4
  [![Gem](https://img.shields.io/gem/v/howzit.svg)](https://rubygems.org/gems/howzit)
5
- [![Travis](https://api.travis-ci.com/ttscoff/howzit.svg?branch=main)](https://travis-ci.org/makenew/ruby-gem)
6
5
  [![GitHub license](https://img.shields.io/github/license/ttscoff/howzit.svg)](./LICENSE.txt)
7
6
 
8
7
  A command-line reference tool for tracking project build systems
9
8
 
10
9
  Howzit is a tool that allows you to keep Markdown-formatted notes about a project's tools and procedures. It functions as an easy lookup for notes about a particular task, as well as a task runner to automatically execute appropriate commands.
11
10
 
11
+
12
12
  ## Features
13
13
 
14
14
  - Match topic titles with any portion of title
data/README.rdoc ADDED
@@ -0,0 +1,6 @@
1
+ = Howzit
2
+
3
+ A command-line reference tool for tracking project build systems
4
+
5
+
6
+
data/Rakefile CHANGED
@@ -6,6 +6,13 @@ require 'rspec/core/rake_task'
6
6
  require 'rubocop/rake_task'
7
7
  require 'yard'
8
8
  require 'tty-spinner'
9
+ require 'rdoc/task'
10
+
11
+ Rake::RDocTask.new do |rd|
12
+ rd.main = 'README.rdoc'
13
+ rd.rdoc_files.include('README.rdoc', 'lib/**/*.rb', 'bin/**/*')
14
+ rd.title = 'Howzit'
15
+ end
9
16
 
10
17
  task default: %i[test yard]
11
18
 
@@ -41,17 +48,20 @@ task :dockertest, :version, :login do |_, args|
41
48
  args.with_defaults(version: 'all', login: false)
42
49
  case args[:version]
43
50
  when /^a/
44
- %w[6 7 3].each do |v|
51
+ %w[2 3 32].each do |v|
45
52
  Rake::Task['dockertest'].reenable
46
53
  Rake::Task['dockertest'].invoke(v, false)
47
54
  end
48
55
  Process.exit 0
56
+ when /^32/
57
+ img = 'howzittest32'
58
+ file = 'docker/Dockerfile-3.2'
49
59
  when /^3/
50
60
  img = 'howzittest3'
51
61
  file = 'docker/Dockerfile-3.0'
52
- when /6$/
53
- img = 'howzittest26'
54
- file = 'docker/Dockerfile-2.6'
62
+ # when /6$/
63
+ # img = 'howzittest26'
64
+ # file = 'docker/Dockerfile-2.6'
55
65
  when /(^2|7$)/
56
66
  img = 'howzittest27'
57
67
  file = 'docker/Dockerfile-2.7'
@@ -64,7 +74,7 @@ task :dockertest, :version, :login do |_, args|
64
74
 
65
75
  exec "docker run -v #{File.dirname(__FILE__)}:/howzit -it #{img} /bin/bash -l" if args[:login]
66
76
 
67
- spinner = TTY::Spinner.new('[:spinner] Running tests ...', hide_cursor: true)
77
+ spinner = TTY::Spinner.new("[:spinner] Running tests #{img}", hide_cursor: true)
68
78
 
69
79
  spinner.auto_spin
70
80
  res = `docker run --rm -v #{File.dirname(__FILE__)}:/howzit -it #{img}`
data/bin/howzit CHANGED
@@ -159,15 +159,13 @@ OptionParser.new do |opts|
159
159
  Process.exit 0
160
160
  end
161
161
 
162
- editor = File.basename(Howzit.options[:editor])
163
- desc = %(Edit buildnotes file in current working directory using editor (#{editor}))
162
+ desc = %(Edit buildnotes file in current working directory using default editor)
164
163
  opts.on('-e', '--edit', desc) do
165
164
  Howzit.buildnote.edit
166
165
  Process.exit 0
167
166
  end
168
167
 
169
- config_editor = File.basename(Howzit.options[:config_editor])
170
- opts.on('--edit-config', "Edit configuration file using editor (#{config_editor})") do
168
+ opts.on('--edit-config', "Edit configuration file using default editor") do
171
169
  Howzit.config.editor
172
170
  Process.exit 0
173
171
  end
@@ -3,7 +3,7 @@ FROM ruby:2.6
3
3
  RUN mkdir /howzit
4
4
  WORKDIR /howzit
5
5
  # COPY ./ /howzit/
6
- RUN gem install bundler:2.2.17
6
+ RUN gem install bundler:2.2.29
7
7
  RUN apt-get update -y
8
8
  RUN apt-get install -y less vim
9
9
  COPY ./docker/inputrc /root/.inputrc
@@ -3,7 +3,7 @@ FROM ruby:2.7
3
3
  RUN mkdir /howzit
4
4
  WORKDIR /howzit
5
5
  # COPY ./ /howzit/
6
- RUN gem install bundler:2.2.17
6
+ RUN gem install bundler:2.2.29
7
7
  RUN apt-get update -y
8
8
  RUN apt-get install -y less vim
9
9
  COPY ./docker/inputrc /root/.inputrc
@@ -3,7 +3,7 @@ FROM ruby:3.0.0
3
3
  RUN mkdir /howzit
4
4
  WORKDIR /howzit
5
5
  # COPY ./ /howzit/
6
- RUN gem install bundler:2.2.17
6
+ RUN gem install bundler:2.2.29
7
7
  RUN apt-get update -y
8
8
  RUN apt-get install -y less vim
9
9
  COPY ./docker/inputrc /root/.inputrc
@@ -0,0 +1,11 @@
1
+ FROM ruby:3.2.0
2
+ # RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
3
+ RUN mkdir /howzit
4
+ WORKDIR /howzit
5
+ # COPY ./ /howzit/
6
+ RUN gem install bundler:2.2.29
7
+ RUN apt-get update -y
8
+ RUN apt-get install -y less vim
9
+ COPY ./docker/inputrc /root/.inputrc
10
+ COPY ./docker/bash_profile /root/.bash_profile
11
+ CMD ["scripts/runtests.sh"]
data/docker/bash_profile CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/bin/bash
2
2
  export GLI_DEBUG=true
3
3
  export EDITOR="/usr/bin/vim"
4
+ export PATH=$PATH:$GEM_HOME/bin
4
5
  alias b="bundle exec bin/howzit"
5
6
 
6
7
  shopt -s nocaseglob
@@ -499,7 +499,7 @@ module Howzit
499
499
  ## @return [String] file path
500
500
  ##
501
501
  def glob_note
502
- Dir.glob('*.{txt,md,markdown}').select(&:build_note?)[0]
502
+ Dir.glob('*.{txt,md,markdown}').select(&:build_note?).sort[0]
503
503
  end
504
504
 
505
505
  ##
@@ -655,12 +655,14 @@ module Howzit
655
655
  def edit_note
656
656
  editor = Howzit.options.fetch(:editor, ENV['EDITOR'])
657
657
 
658
+ editor = Howzit.config.update_editor if editor.nil?
659
+
658
660
  raise 'No editor defined' if editor.nil?
659
661
 
660
662
  raise "Invalid editor (#{editor})" unless Util.valid_command?(editor)
661
663
 
662
664
  create_note(prompt: true) if note_file.nil?
663
- `#{editor} "#{note_file}"`
665
+ exec %(#{editor} "#{note_file}")
664
666
  end
665
667
 
666
668
  ##
@@ -680,6 +682,8 @@ module Howzit
680
682
  def edit_template_file(file)
681
683
  editor = Howzit.options.fetch(:editor, ENV['EDITOR'])
682
684
 
685
+ editor = Howzit.config.update_editor if editor.nil?
686
+
683
687
  raise 'No editor defined' if editor.nil?
684
688
 
685
689
  raise "Invalid editor (#{editor})" unless Util.valid_command?(editor)
@@ -780,7 +784,7 @@ module Howzit
780
784
  when :first
781
785
  topic_matches.push(matches[0])
782
786
  when :best
783
- topic_matches.push(matches.sort.min_by { |t| t.title.length })
787
+ topic_matches.push(matches.sort_by { |a| [a.title.comp_distance(s), a.title.length] })
784
788
  when :all
785
789
  topic_matches.concat(matches)
786
790
  else
data/lib/howzit/config.rb CHANGED
@@ -127,6 +127,31 @@ module Howzit
127
127
  edit_config
128
128
  end
129
129
 
130
+ ## Update editor config
131
+ def update_editor
132
+ puts 'No $EDITOR defined, no value in config'
133
+ editor = Prompt.read_editor
134
+ if editor.nil?
135
+ 'Cancelled, no editor stored.'
136
+ Process.exit 1
137
+ end
138
+ update_config_option({ config_editor: editor, editor: editor })
139
+ puts "Default editor set to #{editor}, modify in config file"
140
+ editor
141
+ end
142
+
143
+ ##
144
+ ## Update a config option and resave config file
145
+ ##
146
+ ## @param options [Hash] key value pairs
147
+ ##
148
+ def update_config_option(options)
149
+ options.each do |key, value|
150
+ Howzit.options[key] = value
151
+ end
152
+ write_config(Howzit.options)
153
+ end
154
+
130
155
  private
131
156
 
132
157
  ##
@@ -263,13 +288,15 @@ module Howzit
263
288
  def edit_config
264
289
  editor = Howzit.options.fetch(:config_editor, ENV['EDITOR'])
265
290
 
291
+ editor = update_editor if editor.nil?
292
+
266
293
  raise 'No config_editor defined' if editor.nil?
267
294
 
268
295
  # raise "Invalid editor (#{editor})" unless Util.valid_command?(editor)
269
296
 
270
297
  load_config
271
298
  if Util.valid_command?(editor.split(/ /).first)
272
- system %(#{editor} "#{config_file}")
299
+ exec %(#{editor} "#{config_file}")
273
300
  else
274
301
  `open -a "#{editor}" "#{config_file}"`
275
302
  end
data/lib/howzit/prompt.rb CHANGED
@@ -159,6 +159,22 @@ module Howzit
159
159
  system('stty', @stty_save)
160
160
  end
161
161
 
162
+ ##
163
+ ## Request editor
164
+ ##
165
+ def read_editor(default = nil)
166
+ @stty_save = `stty -g`.chomp
167
+
168
+ default ||= 'vim'
169
+ prompt = "Define a default editor command (default #{default}): "
170
+ res = Readline.readline(prompt, true).squeeze(' ').strip
171
+ res = default if res.empty?
172
+
173
+ Util.valid_command?(res) ? res : default
174
+ ensure
175
+ system('stty', @stty_save)
176
+ end
177
+
162
178
  ##
163
179
  ## Convert a response to an Integer
164
180
  ##
@@ -3,6 +3,86 @@
3
3
  module Howzit
4
4
  # String Extensions
5
5
  module StringUtils
6
+ ## Compare strings and return a distance
7
+ ##
8
+ ## @param other [String] The string to compare
9
+ ## @param term [String] The search term
10
+ ##
11
+ ## @return [Float] distance
12
+ def comp_distance(term)
13
+ chars = term.split(//)
14
+ contains_count(chars) + distance(chars)
15
+ end
16
+
17
+ ##
18
+ ## Number of matching characters the string contains
19
+ ##
20
+ ## @param chars [String|Array] The characters
21
+ ##
22
+ def contains_count(chars)
23
+ chars = chars.split(//) if chars.is_a?(String)
24
+ count = 0
25
+ chars.each { |char| count += 1 if self =~ /#{char}/i }
26
+ count
27
+ end
28
+
29
+ ##
30
+ ## Determine if characters are in order
31
+ ##
32
+ ## @param chars [String|Array] The characters
33
+ ##
34
+ ## @return [Boolean] characters are in order
35
+ ##
36
+ def in_order(chars)
37
+ chars = chars.split(//) if chars.is_a?(String)
38
+ position = 0
39
+ in_order = 0
40
+ chars.each do |char|
41
+ new_pos = self[position..] =~ /#{char}/i
42
+ if new_pos
43
+ position += new_pos
44
+ in_order += 1
45
+ end
46
+ end
47
+ in_order
48
+ end
49
+
50
+ ##
51
+ ## Determine if a series of characters are all within a given distance of
52
+ ## each other in the String
53
+ ##
54
+ ## @param chars [String|Array] The characters
55
+ ## @param distance [Number] The distance
56
+ ##
57
+ ## @return [Boolean] true if within distance
58
+ ##
59
+ def in_distance?(chars, distance)
60
+ chars = chars.split(//) if chars.is_a?(String)
61
+ rx = Regexp.new(chars.join(".{,#{distance}}"), 'i')
62
+ self =~ rx ? true : false
63
+ end
64
+
65
+ ##
66
+ ## Determine the minimum distance between characters that they all still
67
+ ## fall within
68
+ ##
69
+ ## @param chars [Array] The characters
70
+ ##
71
+ ## @return [Number] distance
72
+ ##
73
+ def distance(chars)
74
+ distance = 0
75
+ max = self.length - chars.length
76
+ return max unless in_order(chars) == chars.length
77
+
78
+ while distance < max
79
+ return distance if in_distance?(chars, distance)
80
+
81
+ distance += 1
82
+ end
83
+ distance
84
+ end
85
+
6
86
  ##
7
87
  ## Test if the filename matches the conditions to be a build note
8
88
  ##
@@ -3,5 +3,5 @@
3
3
  # Primary module for this gem.
4
4
  module Howzit
5
5
  # Current Howzit version.
6
- VERSION = '2.1.13'
6
+ VERSION = '2.1.15'
7
7
  end
data/lib/howzit.rb CHANGED
@@ -77,8 +77,8 @@ module Howzit
77
77
  ##
78
78
  ## Module storage for buildnote
79
79
  ##
80
- def buildnote
81
- @buildnote ||= BuildNote.new
80
+ def buildnote(file = nil)
81
+ @buildnote ||= BuildNote.new(file: file)
82
82
  end
83
83
 
84
84
  ##
data/scripts/runtests.sh CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
2
 
3
3
  bundle install
4
- rake test
4
+ export EDITOR="/usr/bin/vim"
5
+ export PATH=$PATH:$GEM_HOME/bin
6
+ rake spec
@@ -3,7 +3,7 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Howzit::BuildNote do
6
- subject(:how) { @hz }
6
+ subject(:how) { Howzit.buildnote('builda.md') }
7
7
 
8
8
  describe ".note_file" do
9
9
  it "locates a build note file" do
@@ -27,43 +27,55 @@ describe Howzit::BuildNote do
27
27
  expect(matches.count).to eq 1
28
28
  expect(matches[0].title).to eq 'Topic Tropic'
29
29
  end
30
+
30
31
  it "fuzzy matches" do
31
32
  Howzit.options[:matching] = 'fuzzy'
32
33
  matches = how.find_topic('trpc')
33
34
  expect(matches.count).to eq 1
34
35
  expect(matches[0].title).to eq 'Topic Tropic'
35
36
  end
37
+
36
38
  it "succeeds with partial match" do
37
39
  Howzit.options[:matching] = 'partial'
38
40
  matches = how.find_topic('trop')
39
41
  expect(matches.count).to eq 1
40
42
  expect(matches[0].title).to eq 'Topic Tropic'
41
43
  end
44
+
42
45
  it "succeeds with beginswith match" do
43
46
  Howzit.options[:matching] = 'beginswith'
44
47
  matches = how.find_topic('topic')
45
48
  expect(matches.count).to eq 3
46
49
  expect(matches[0].title).to eq 'Topic Balogna'
47
50
  end
51
+
48
52
  it "succeeds with exact match" do
49
53
  Howzit.options[:matching] = 'exact'
50
54
  matches = how.find_topic('topic tropic')
51
55
  expect(matches.count).to eq 1
52
56
  expect(matches[0].title).to eq 'Topic Tropic'
53
57
  end
58
+
54
59
  it "fails with incomplete exact match" do
55
60
  Howzit.options[:matching] = 'exact'
56
61
  matches = how.find_topic('topic trop')
57
62
  expect(matches.count).to eq 0
58
63
  end
64
+
65
+ it "Handles multiple matches with best match" do
66
+ Howzit.options[:matching] = 'fuzzy'
67
+ Howzit.options[:multiple_matches] = :best
68
+ matches = how.find_topic('banana')
69
+ expect(matches.first.title).to match(/banana/i)
70
+ end
59
71
  end
60
72
 
61
73
  describe ".topics" do
62
74
  it "contains 4 topics" do
63
- expect(how.list_topics.count).to eq 3
75
+ expect(how.list_topics.count).to eq 4
64
76
  end
65
77
  it "outputs a newline-separated string for completion" do
66
- expect(how.list_completions.scan(/\n/).count).to eq 2
78
+ expect(how.list_completions.scan(/\n/).count).to eq 3
67
79
  end
68
80
  end
69
81
  end
data/spec/cli_spec.rb CHANGED
@@ -15,7 +15,7 @@ describe 'CLI' do
15
15
  execute_script('bin/howzit', use_bundler: true, args: %w[-L])
16
16
  expect(last_execution).to be_successful
17
17
  expect(last_execution.stdout).to match(/Topic Balogna/)
18
- expect(last_execution.stdout.split(/\n/).count).to eq 3
18
+ expect(last_execution.stdout.split(/\n/).count).to eq 4
19
19
  end
20
20
 
21
21
  it 'lists available tasks' do
data/spec/spec_helper.rb CHANGED
@@ -63,8 +63,13 @@ def save_buildnote
63
63
 
64
64
  Bermuda, Bahama, something something wanna.
65
65
  @copy(Balogna) Just some balogna
66
+
67
+ ## Happy Bgagngagnga
68
+
69
+ This one is just to throw things off
66
70
  EONOTE
67
71
  File.open('builda.md', 'w') { |f| f.puts note }
72
+ # puts "Saved to builda.md: #{File.exist?('builda.md')}"
68
73
  end
69
74
 
70
75
  def delete_buildnote
data/spec/topic_spec.rb CHANGED
@@ -21,7 +21,10 @@ describe Howzit::Topic do
21
21
  end
22
22
 
23
23
  describe Howzit::Topic do
24
- subject(:topic) { @hz.find_topic('Topic Balogna')[0] }
24
+ subject(:topic) {
25
+ bn = Howzit.buildnote
26
+ bn.find_topic('Topic Balogna')[0]
27
+ }
25
28
 
26
29
  describe '.title' do
27
30
  it 'has the correct title' do
data/src/_README.md CHANGED
@@ -2,12 +2,12 @@
2
2
  # Howzit
3
3
 
4
4
  [![Gem](https://img.shields.io/gem/v/howzit.svg)](https://rubygems.org/gems/howzit)
5
- [![Travis](https://api.travis-ci.com/ttscoff/howzit.svg?branch=main)](https://travis-ci.org/makenew/ruby-gem)
6
5
  [![GitHub license](https://img.shields.io/github/license/ttscoff/howzit.svg)](./LICENSE.txt)
7
- <!--END GITHUB-->
6
+
8
7
  A command-line reference tool for tracking project build systems
9
8
 
10
9
  Howzit is a tool that allows you to keep Markdown-formatted notes about a project's tools and procedures. It functions as an easy lookup for notes about a particular task, as well as a task runner to automatically execute appropriate commands.
10
+ <!--END GITHUB-->
11
11
 
12
12
  ## Features
13
13
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: howzit
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.13
4
+ version: 2.1.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-05 00:00:00.000000000 Z
11
+ date: 2024-08-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -294,6 +294,7 @@ files:
294
294
  - ".github/FUNDING.yml"
295
295
  - ".gitignore"
296
296
  - ".howzit.taskpaper.bak"
297
+ - ".irbrc"
297
298
  - ".rspec"
298
299
  - ".rubocop.yml"
299
300
  - ".travis.yml"
@@ -303,12 +304,14 @@ files:
303
304
  - Guardfile
304
305
  - LICENSE.txt
305
306
  - README.md
307
+ - README.rdoc
306
308
  - Rakefile
307
309
  - bin/howzit
308
310
  - docker/Dockerfile
309
311
  - docker/Dockerfile-2.6
310
312
  - docker/Dockerfile-2.7
311
313
  - docker/Dockerfile-3.0
314
+ - docker/Dockerfile-3.2
312
315
  - docker/bash_profile
313
316
  - docker/inputrc
314
317
  - fish/completions/bld.fish