heytmux 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 85b63f2a2697dfa9be0ef1b209e308f5ffce4480
4
- data.tar.gz: fe1606f7147b1bb5ca3f1283477f2796f83f163a
2
+ SHA256:
3
+ metadata.gz: 2416296679429973f3324dee4b41204cf0414cba0296028c2856215370dc2627
4
+ data.tar.gz: 6b5b41223076adf68875297d9e2c5fc8959b07250a37e9df71e435baa03bed6a
5
5
  SHA512:
6
- metadata.gz: 166da8ba7bc7393509acffe0f43b0c72209ca2c8e41f3467b10d77a0f9081a858342ade4e3d7d8f94cd247891844577bf80c7a255deacb7c588e0b6a6b9b1662
7
- data.tar.gz: 1289e4ec84118413d2868ebd91eb2c4ae5b0aacfdab632181bedf83c46d2ea805bb51a96069b63b275b0e294060bb49dfe1552daa66b0fb8a7621d463132f063
6
+ metadata.gz: 579bf7e26c4e2c91870303e608c6e5a9bfe9d9368b1d610550fa6d0e185e4cfc62aaf4c364f12ef5679e5a263548b5c44720074e8675e0759059701e0b587b7b
7
+ data.tar.gz: fcb6ae512001bb29b3af8c2aeb8f124dbb2fe66b018769ca6bd7af9804b3dbc82058dcbc96a4cf7951cff939ed635f7085dc7fed95ffdd33c9a4f3b3ec87e453
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in heytmux.gemspec
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  Hey tmux!
2
2
  =========
3
3
 
4
- [![travis-ci](https://travis-ci.org/junegunn/heytmux.svg?branch=master)](https://travis-ci.org/junegunn/heytmux)
4
+ [![GitHub Actions Status](https://github.com/junegunn/heytmux/actions/workflows/ubuntu.yml/badge.svg)](https://github.com/junegunn/heytmux/actions)
5
5
  [![Coverage Status](https://coveralls.io/repos/github/junegunn/heytmux/badge.svg?branch=master)](https://coveralls.io/github/junegunn/heytmux?branch=master)
6
6
  [![Gem](https://img.shields.io/gem/v/heytmux.svg)](https://rubygems.org/gems/heytmux)
7
7
 
@@ -221,7 +221,7 @@ expanded according to the list.
221
221
  - pane {{item}}: sleep {{item}}
222
222
  ```
223
223
 
224
- Note that you have to quote a pane title if it starts with `{{ item }}`.
224
+ Note that you have to quote a pane title if it starts with `{{`.
225
225
 
226
226
  This is often useful when you have to work with a series of log files or with
227
227
  a set of servers.
@@ -238,6 +238,7 @@ a set of servers.
238
238
  - ssh user@{{item}} tail -f /var/log/server-{{item}}.log
239
239
  ```
240
240
 
241
+ Also note that `{{ item.index }}` expands to zero-based index of the item.
241
242
 
242
243
  #### Referring to environment variables
243
244
 
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
  require 'rake/testtask'
3
5
 
data/exe/heytmux CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'heytmux'
4
5
 
@@ -17,13 +18,13 @@ if (unreadable = ARGV.find { |f| !File.readable?(f) })
17
18
  end
18
19
 
19
20
  require 'yaml'
20
- strings = [$stdin.tty? ? nil : ['standard input', $stdin.read],
21
+ strings = [ARGV.any? || $stdin.tty? ? nil : ['standard input', $stdin.read],
21
22
  *ARGV.map { |f| [f, File.read(f)] }].compact
22
23
  specs = strings.map do |name, str|
23
24
  begin
24
25
  str = Heytmux.replace_env_vars(str)
25
- YAML.respond_to?(:safe_load) ? YAML.safe_load(str) : YAML.load(str)
26
- rescue => e
26
+ YAML.safe_load(str)
27
+ rescue StandardError => e
27
28
  abort("Failed to parse #{name}: #{e}")
28
29
  end
29
30
  end
data/heytmux.gemspec CHANGED
@@ -1,6 +1,6 @@
1
- # coding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path('../lib', __FILE__)
3
+ lib = File.expand_path('lib', __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require 'heytmux/version'
6
6
 
@@ -21,11 +21,10 @@ Gem::Specification.new do |spec|
21
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
22
  spec.require_paths = ['lib']
23
23
 
24
- spec.required_ruby_version = '>= 2.0'
25
- spec.add_development_dependency 'bundler', '~> 1.15'
26
- spec.add_development_dependency 'rake', '~> 12.0'
27
- spec.add_development_dependency 'minitest', '~> 5.10'
24
+ spec.required_ruby_version = '>= 2.4'
25
+ spec.add_development_dependency 'bundler', '>= 2.2.15'
26
+ spec.add_development_dependency 'coveralls_reborn'
27
+ spec.add_development_dependency 'minitest'
28
28
  spec.add_development_dependency 'pry'
29
- spec.add_development_dependency 'simplecov'
30
- spec.add_development_dependency 'coveralls'
29
+ spec.add_development_dependency 'rake'
31
30
  end
data/lib/heytmux/core.rb CHANGED
@@ -71,12 +71,17 @@ module Heytmux
71
71
 
72
72
  # Finds appropriate PaneActions for the commands and processes them
73
73
  def process_command!(window_index, pane)
74
- pane_index, item, commands = pane.values_at(:index, :item, :command)
74
+ pane_index, item, item_index, commands =
75
+ pane.values_at(:index, :item, :item_index, :command)
75
76
  [*commands].compact.each do |command|
76
77
  label, body = command.is_a?(Hash) ? command.first : [:paste, command]
77
78
  PaneAction.for(label).process(window_index, pane_index, body) do |source|
78
79
  string = source.to_s
79
- item ? string.gsub(ITEM_PAT, item) : string
80
+ if item
81
+ string.gsub(ITEM_PAT, item).gsub(ITEM_INDEX_PAT, item_index.to_s)
82
+ else
83
+ string
84
+ end
80
85
  end
81
86
  end
82
87
  end
@@ -84,9 +89,8 @@ module Heytmux
84
89
  # Groups entities by the group key and extracts unique, sorted indexes and
85
90
  # returns stateful indexer that issues index number for the given group key
86
91
  def indexer(entities, group_key, index_key)
87
- indexes =
88
- Hash[entities.group_by { |e| e[group_key] }
89
- .map { |g, es| [g, es.map { |e| e[index_key] }.sort.uniq] }]
92
+ indexes = entities.group_by { |e| e[group_key] }
93
+ .transform_values { |es| es.map { |e| e[index_key] }.sort.uniq }
90
94
  ->(group) { indexes.fetch(group, []).shift }
91
95
  end
92
96
  private_class_method :indexer
@@ -140,12 +144,20 @@ module Heytmux
140
144
  end
141
145
 
142
146
  def interpret_and_expand_pane_spec(pane, items, pane_indexer)
147
+ pane_items = pane[ITEMS_KEY]
148
+ if pane_items && pane.length > 1
149
+ pane = pane.except(ITEMS_KEY)
150
+ items = pane_items || items
151
+ end
152
+
143
153
  title, command = pane.is_a?(Hash) ? pane.first : [pane.tr("\n", ' '), pane]
144
- if title =~ ITEM_PAT
145
- items.map do |item|
154
+ if title =~ ITEM_PAT || title =~ ITEM_INDEX_PAT
155
+ items.map.with_index do |item, item_idx|
146
156
  title_sub = title.gsub(ITEM_PAT, item.to_s)
157
+ .gsub(ITEM_INDEX_PAT, item_idx.to_s)
147
158
  { title: title_sub, command: command,
148
- item: item.to_s, index: pane_indexer[title_sub] }
159
+ item: item.to_s, item_index: item_idx,
160
+ index: pane_indexer[title_sub] }
149
161
  end
150
162
  else
151
163
  [{ title: title, command: command, index: pane_indexer[title] }]
@@ -154,9 +166,9 @@ module Heytmux
154
166
 
155
167
  # Checks if there are entities without the required_field and creates them
156
168
  # with the given block. Returns two arrays of found and created entities.
157
- def create_if_missing(entities, required_field)
169
+ def create_if_missing(entities, required_field, &block)
158
170
  found, missing = entities.partition { |e| e[required_field] }
159
- [found, missing.map { |e| yield e }]
171
+ [found, missing.map(&block)]
160
172
  end
161
173
  private_class_method :create_if_missing
162
174
 
@@ -25,7 +25,7 @@ module Heytmux
25
25
  def register(*labels, klass)
26
26
  instance = klass.new
27
27
  (@actions ||= {}).merge!(
28
- Hash[labels.map { |label| [label, instance] }]
28
+ labels.to_h { |label| [label, instance] }
29
29
  )
30
30
  end
31
31
 
@@ -17,6 +17,7 @@ module Heytmux
17
17
  wait_until do
18
18
  content = Tmux.capture(window_index, pane_index)
19
19
  raise 'Failed to capture pane content' unless $CHILD_STATUS.success?
20
+
20
21
  content =~ regex
21
22
  end
22
23
  end
data/lib/heytmux/tmux.rb CHANGED
@@ -23,7 +23,7 @@ module Heytmux
23
23
  list = tmux(%w[list-panes -s -F],
24
24
  labels.map { |label| "\#{#{label}}" }.join(delimiter))
25
25
  list.each_line.map do |line|
26
- Hash[labels.zip(line.chomp.split(delimiter))].tap do |h|
26
+ labels.zip(line.chomp.split(delimiter)).to_h.tap do |h|
27
27
  h[:window_index] = h[:window_index].to_i
28
28
  h[:pane_index] = h[:pane_index].to_i
29
29
  end
@@ -12,15 +12,15 @@ module Heytmux
12
12
  unless spec.key?(WINDOWS_KEY)
13
13
  raise(ArgumentError, 'windows key is not found')
14
14
  end
15
+
15
16
  spec[WINDOWS_KEY]
16
17
  when Array then spec
17
18
  else
18
19
  raise ArgumentError, "Not a valid spec: #{spec}"
19
20
  end
20
21
 
21
- unless windows.is_a?(Array)
22
- raise ArgumentError, 'windows must be given as a list'
23
- end
22
+ raise ArgumentError, 'windows must be given as a list' unless windows.is_a?(Array)
23
+
24
24
  windows.each { |window| validate_window(window) }
25
25
  nil
26
26
  end
@@ -33,9 +33,8 @@ module Heytmux
33
33
  message = "Not a valid window spec: #{window_spec.inspect}"
34
34
  case window_spec
35
35
  when Hash
36
- unless single_spec?(window_spec, Hash, Array)
37
- raise ArgumentError, message
38
- end
36
+ raise ArgumentError, message unless single_spec?(window_spec, Hash, Array)
37
+
39
38
  spec = window_spec.first.last
40
39
  spec = { PANES_KEY => spec } if spec.is_a?(Array)
41
40
  spec.fetch(PANES_KEY, []).each do |pane|
@@ -55,6 +54,17 @@ module Heytmux
55
54
  message = "Not a valid pane spec: #{pane_spec.inspect}"
56
55
  case pane_spec
57
56
  when Hash
57
+ # Is 'items' present?
58
+ has_items = pane_spec.key?(ITEMS_KEY)
59
+ if has_items && pane_spec.except(ITEMS_KEY).any?
60
+ items = pane_spec[ITEMS_KEY]
61
+ if !items.is_a?(Array) || items.empty?
62
+ raise ArgumentError, "'items' must be a non-empty array"
63
+ end
64
+
65
+ pane_spec = pane_spec.except(ITEMS_KEY)
66
+ end
67
+
58
68
  unless single_spec?(pane_spec)
59
69
  if unquoted_pane_title?(pane_spec)
60
70
  message = 'Invalid pane title. ' \
@@ -62,6 +72,15 @@ module Heytmux
62
72
  end
63
73
  raise ArgumentError, message
64
74
  end
75
+
76
+ if has_items
77
+ title = pane_spec.first.first
78
+ unless title =~ ITEM_PAT || title =~ ITEM_INDEX_PAT
79
+ raise ArgumentError,
80
+ 'Pane title must contain {{ item }} or {{ item.index }} ' \
81
+ "when 'items' is given"
82
+ end
83
+ end
65
84
  validate_commands(pane_spec.first.last)
66
85
  else
67
86
  raise ArgumentError, message unless valid_name?(pane_spec)
@@ -77,6 +96,7 @@ module Heytmux
77
96
  case command
78
97
  when Hash
79
98
  raise ArgumentError, message unless single_spec?(command)
99
+
80
100
  label, body = command.first
81
101
  validate_action(label, body)
82
102
  else
@@ -90,6 +110,7 @@ module Heytmux
90
110
  def validate_action(label, body)
91
111
  action = PaneAction.for(label)
92
112
  raise ArgumentError, "Unsupported action: #{label}" unless action
113
+
93
114
  action.validate(body)
94
115
  end
95
116
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Heytmux
4
- VERSION = '0.1.1'
4
+ VERSION = '0.3.0'
5
5
  end
data/lib/heytmux.rb CHANGED
@@ -6,9 +6,9 @@ require 'set'
6
6
  module Heytmux
7
7
  DEFAULT_LAYOUT = ->(num_panes) { num_panes <= 3 ? 'even-vertical' : 'tiled' }
8
8
  DEFAULT_OPTIONS = {
9
- 'automatic-rename' => 'off',
10
- 'allow-rename' => 'off',
11
- 'pane-base-index' => 0,
9
+ 'automatic-rename' => 'off',
10
+ 'allow-rename' => 'off',
11
+ 'pane-base-index' => 0,
12
12
  'pane-border-status' => 'bottom',
13
13
  'pane-border-format' => '#{pane_title}'
14
14
  }.freeze
@@ -17,8 +17,9 @@ module Heytmux
17
17
  LAYOUT_KEY = 'layout'
18
18
  PANES_KEY = 'panes'
19
19
  ITEMS_KEY = 'items'
20
- ITEM_PAT = /{{ *item *}}/i
21
- ENV_PAT = /{{ *\$([a-z0-9_]+) *(?:\| *(.*?) *)?}}/i
20
+ ITEM_PAT = /{{ *item *}}/i.freeze
21
+ ITEM_INDEX_PAT = /{{ *item\.index *}}/i.freeze
22
+ ENV_PAT = /{{ *\$([a-z0-9_]+) *(?:\| *(.*?) *)?}}/i.freeze
22
23
 
23
24
  EXPECT_SLEEP_INTERVAL = 0.5
24
25
  EXPECT_TIMEOUT = 60
metadata CHANGED
@@ -1,59 +1,44 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: heytmux
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Junegunn Choi
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2017-07-08 00:00:00.000000000 Z
10
+ date: 2025-05-20 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: bundler
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
- - - "~>"
16
+ - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: '1.15'
18
+ version: 2.2.15
20
19
  type: :development
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
- - - "~>"
23
+ - - ">="
25
24
  - !ruby/object:Gem::Version
26
- version: '1.15'
25
+ version: 2.2.15
27
26
  - !ruby/object:Gem::Dependency
28
- name: rake
27
+ name: coveralls_reborn
29
28
  requirement: !ruby/object:Gem::Requirement
30
29
  requirements:
31
- - - "~>"
30
+ - - ">="
32
31
  - !ruby/object:Gem::Version
33
- version: '12.0'
32
+ version: '0'
34
33
  type: :development
35
34
  prerelease: false
36
35
  version_requirements: !ruby/object:Gem::Requirement
37
36
  requirements:
38
- - - "~>"
37
+ - - ">="
39
38
  - !ruby/object:Gem::Version
40
- version: '12.0'
39
+ version: '0'
41
40
  - !ruby/object:Gem::Dependency
42
41
  name: minitest
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '5.10'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '5.10'
55
- - !ruby/object:Gem::Dependency
56
- name: pry
57
42
  requirement: !ruby/object:Gem::Requirement
58
43
  requirements:
59
44
  - - ">="
@@ -67,7 +52,7 @@ dependencies:
67
52
  - !ruby/object:Gem::Version
68
53
  version: '0'
69
54
  - !ruby/object:Gem::Dependency
70
- name: simplecov
55
+ name: pry
71
56
  requirement: !ruby/object:Gem::Requirement
72
57
  requirements:
73
58
  - - ">="
@@ -81,7 +66,7 @@ dependencies:
81
66
  - !ruby/object:Gem::Version
82
67
  version: '0'
83
68
  - !ruby/object:Gem::Dependency
84
- name: coveralls
69
+ name: rake
85
70
  requirement: !ruby/object:Gem::Requirement
86
71
  requirements:
87
72
  - - ">="
@@ -121,7 +106,6 @@ files:
121
106
  homepage: https://github.com/junegunn/heytmux
122
107
  licenses: []
123
108
  metadata: {}
124
- post_install_message:
125
109
  rdoc_options: []
126
110
  require_paths:
127
111
  - lib
@@ -129,16 +113,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
129
113
  requirements:
130
114
  - - ">="
131
115
  - !ruby/object:Gem::Version
132
- version: '2.0'
116
+ version: '2.4'
133
117
  required_rubygems_version: !ruby/object:Gem::Requirement
134
118
  requirements:
135
119
  - - ">="
136
120
  - !ruby/object:Gem::Version
137
121
  version: '0'
138
122
  requirements: []
139
- rubyforge_project:
140
- rubygems_version: 2.6.8
141
- signing_key:
123
+ rubygems_version: 3.6.2
142
124
  specification_version: 4
143
125
  summary: Hey tmux!
144
126
  test_files: []