slk 0.4.0 → 0.4.2
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 +4 -4
- data/CHANGELOG.md +33 -0
- data/lib/slk/api/saved.rb +26 -0
- data/lib/slk/cli.rb +12 -1
- data/lib/slk/commands/activity.rb +7 -13
- data/lib/slk/commands/base.rb +2 -1
- data/lib/slk/commands/help.rb +2 -0
- data/lib/slk/commands/later.rb +297 -0
- data/lib/slk/commands/messages.rb +4 -3
- data/lib/slk/commands/thread.rb +27 -9
- data/lib/slk/formatters/activity_formatter.rb +4 -7
- data/lib/slk/formatters/markdown_output.rb +98 -0
- data/lib/slk/formatters/message_formatter.rb +10 -18
- data/lib/slk/formatters/reaction_formatter.rb +1 -1
- data/lib/slk/formatters/saved_item_formatter.rb +144 -0
- data/lib/slk/formatters/search_formatter.rb +4 -8
- data/lib/slk/formatters/text_processor.rb +48 -0
- data/lib/slk/models/saved_item.rb +128 -0
- data/lib/slk/runner.rb +22 -2
- data/lib/slk/services/message_resolver.rb +38 -0
- data/lib/slk/support/inline_images.rb +94 -10
- data/lib/slk/version.rb +1 -1
- data/lib/slk.rb +7 -0
- metadata +8 -7
|
@@ -2,11 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
module Slk
|
|
4
4
|
module Support
|
|
5
|
-
# Shared module for inline image display in
|
|
5
|
+
# Shared module for inline image display in terminals supporting
|
|
6
|
+
# iTerm2 protocol (iTerm2/WezTerm/Mintty) or Kitty graphics protocol (Ghostty/Kitty)
|
|
6
7
|
# Includes special handling for tmux passthrough sequences
|
|
7
8
|
module InlineImages
|
|
8
|
-
# Check if terminal supports
|
|
9
|
+
# Check if terminal supports any inline image protocol
|
|
9
10
|
def inline_images_supported?
|
|
11
|
+
iterm2_protocol_supported? || kitty_graphics_supported?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Check if terminal supports iTerm2 inline image protocol
|
|
15
|
+
def iterm2_protocol_supported?
|
|
10
16
|
# iTerm2, WezTerm, Mintty support inline images
|
|
11
17
|
# LC_TERMINAL persists through tmux/ssh
|
|
12
18
|
['iTerm.app', 'WezTerm'].include?(ENV.fetch('TERM_PROGRAM', nil)) ||
|
|
@@ -15,31 +21,88 @@ module Slk
|
|
|
15
21
|
ENV['TERM'] == 'mintty'
|
|
16
22
|
end
|
|
17
23
|
|
|
24
|
+
# Check if terminal supports Kitty graphics protocol (Ghostty, Kitty)
|
|
25
|
+
def kitty_graphics_supported?
|
|
26
|
+
ENV['TERM_PROGRAM'] == 'ghostty' ||
|
|
27
|
+
ENV['GHOSTTY_RESOURCES_DIR'] ||
|
|
28
|
+
ENV['TERM']&.include?('kitty') ||
|
|
29
|
+
tmux_client_is_kitty_compatible?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Check if tmux client terminal supports Kitty graphics
|
|
33
|
+
def tmux_client_is_kitty_compatible?
|
|
34
|
+
return false unless in_tmux?
|
|
35
|
+
|
|
36
|
+
@tmux_client_is_kitty_compatible ||= begin
|
|
37
|
+
output = begin
|
|
38
|
+
`tmux display-message -p '\#{client_termname}'`.chomp
|
|
39
|
+
rescue StandardError
|
|
40
|
+
''
|
|
41
|
+
end
|
|
42
|
+
output.include?('ghostty') || output.include?('kitty')
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
18
46
|
# Check if running inside tmux
|
|
19
47
|
def in_tmux?
|
|
20
48
|
# tmux sets TERM to screen-* or tmux-*
|
|
21
49
|
ENV['TERM']&.include?('screen') || ENV['TERM']&.start_with?('tmux')
|
|
22
50
|
end
|
|
23
51
|
|
|
24
|
-
# Print an inline image using
|
|
52
|
+
# Print an inline image using the appropriate protocol
|
|
25
53
|
# In tmux, uses passthrough sequence and cursor positioning
|
|
26
54
|
def print_inline_image(path, height: 1)
|
|
27
|
-
data =
|
|
55
|
+
data = read_image_data_for_protocol(path)
|
|
28
56
|
return unless data
|
|
29
57
|
|
|
30
58
|
encoded = [data].pack('m0')
|
|
31
|
-
|
|
59
|
+
|
|
60
|
+
if kitty_graphics_supported?
|
|
61
|
+
in_tmux? ? print_tmux_kitty_image(encoded, height) : print_kitty_image(encoded, height)
|
|
62
|
+
else
|
|
63
|
+
in_tmux? ? print_tmux_iterm_image(encoded, height) : print_iterm_image(encoded, height)
|
|
64
|
+
end
|
|
32
65
|
end
|
|
33
66
|
|
|
34
|
-
def
|
|
67
|
+
def read_image_data_for_protocol(path)
|
|
35
68
|
return nil unless File.exist?(path)
|
|
36
69
|
|
|
37
|
-
File.binread(path)
|
|
70
|
+
data = File.binread(path)
|
|
71
|
+
return nil unless data
|
|
72
|
+
|
|
73
|
+
# Kitty protocol requires PNG format; convert GIF/JPEG if needed
|
|
74
|
+
if kitty_graphics_supported? && !png_data?(data)
|
|
75
|
+
convert_to_png(path)
|
|
76
|
+
else
|
|
77
|
+
data
|
|
78
|
+
end
|
|
38
79
|
rescue IOError, SystemCallError
|
|
39
80
|
nil
|
|
40
81
|
end
|
|
41
82
|
|
|
42
|
-
def
|
|
83
|
+
def png_data?(data)
|
|
84
|
+
# PNG files start with magic bytes: 137 80 78 71 13 10 26 10
|
|
85
|
+
data[0, 8]&.bytes == [137, 80, 78, 71, 13, 10, 26, 10]
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def convert_to_png(path)
|
|
89
|
+
# Use sips (macOS) to convert to PNG
|
|
90
|
+
require 'tempfile'
|
|
91
|
+
temp = Tempfile.new(['emoji', '.png'])
|
|
92
|
+
temp.close
|
|
93
|
+
|
|
94
|
+
system('sips', '-s', 'format', 'png', path, '--out', temp.path,
|
|
95
|
+
out: File::NULL, err: File::NULL)
|
|
96
|
+
|
|
97
|
+
return nil unless File.exist?(temp.path) && File.size(temp.path).positive?
|
|
98
|
+
|
|
99
|
+
File.binread(temp.path)
|
|
100
|
+
ensure
|
|
101
|
+
temp&.unlink
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# iTerm2 protocol methods
|
|
105
|
+
def print_tmux_iterm_image(encoded, height)
|
|
43
106
|
fmt = "\ePtmux;\e\e]1337;File=inline=1;preserveAspectRatio=0;" \
|
|
44
107
|
"size=%<size>d;height=%<height>d:%<data>s\a\e\\\n "
|
|
45
108
|
printf fmt, size: encoded.length, height: height, data: encoded
|
|
@@ -49,6 +112,26 @@ module Slk
|
|
|
49
112
|
printf "\e]1337;File=inline=1;height=%<height>d:%<data>s\a", height: height, data: encoded
|
|
50
113
|
end
|
|
51
114
|
|
|
115
|
+
# Kitty graphics protocol methods (Ghostty, Kitty)
|
|
116
|
+
# a=T: transmit and display, q=1: suppress OK response, f=100: PNG, r=rows, m=0: no more chunks
|
|
117
|
+
def print_kitty_image(encoded, height)
|
|
118
|
+
printf "\e_Ga=T,q=1,f=100,r=%<height>d,m=0;%<data>s\e\\", height: height, data: encoded
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Kitty graphics with Unicode placeholders for tmux (images clear/scroll with text)
|
|
122
|
+
# See: https://sw.kovidgoyal.net/kitty/graphics-protocol/#unicode-placeholders
|
|
123
|
+
def print_tmux_kitty_image(encoded, _height)
|
|
124
|
+
@kitty_image_id ||= 30
|
|
125
|
+
@kitty_image_id = (@kitty_image_id % 255) + 1
|
|
126
|
+
image_id = @kitty_image_id
|
|
127
|
+
|
|
128
|
+
# tmux passthrough: transmit image with Unicode placeholder mode (U=1), 2 cols x 1 row
|
|
129
|
+
$stdout.print "\ePtmux;\e\e_Ga=T,U=1,q=1,f=100,i=#{image_id},c=2,r=1,m=0;#{encoded}\e\e\\\e\\"
|
|
130
|
+
# Output placeholder cells (U+10EEEE + row/col diacritics) with foreground color = image_id
|
|
131
|
+
$stdout.print "\e[38;5;#{image_id}m\u{10EEEE}\u0305\u0305\u{10EEEE}\u0305\u030D\e[39m"
|
|
132
|
+
$stdout.flush
|
|
133
|
+
end
|
|
134
|
+
|
|
52
135
|
# Print inline image with name on same line
|
|
53
136
|
# Handles tmux cursor positioning to keep image and text on same line
|
|
54
137
|
def print_inline_image_with_text(path, text, height: 1) # rubocop:disable Naming/PredicateMethod
|
|
@@ -56,11 +139,12 @@ module Slk
|
|
|
56
139
|
|
|
57
140
|
print_inline_image(path, height: height)
|
|
58
141
|
|
|
59
|
-
if in_tmux?
|
|
60
|
-
# tmux: image ends with \n + space, cursor on next line
|
|
142
|
+
if in_tmux? && !kitty_graphics_supported?
|
|
143
|
+
# iTerm2 in tmux: image ends with \n + space, cursor on next line
|
|
61
144
|
# Move up 1 line, right 3 cols (past image), then print text
|
|
62
145
|
print "\e[1A\e[3C#{text}\n"
|
|
63
146
|
else
|
|
147
|
+
# Direct output or Unicode placeholders (regular text, just print after)
|
|
64
148
|
puts " #{text}"
|
|
65
149
|
end
|
|
66
150
|
|
data/lib/slk/version.rb
CHANGED
data/lib/slk.rb
CHANGED
|
@@ -33,6 +33,7 @@ module Slk
|
|
|
33
33
|
autoload :Channel, 'slk/models/channel'
|
|
34
34
|
autoload :Preset, 'slk/models/preset'
|
|
35
35
|
autoload :SearchResult, 'slk/models/search_result'
|
|
36
|
+
autoload :SavedItem, 'slk/models/saved_item'
|
|
36
37
|
end
|
|
37
38
|
|
|
38
39
|
# Application services for configuration, caching, and API communication
|
|
@@ -54,11 +55,13 @@ module Slk
|
|
|
54
55
|
autoload :TargetResolver, 'slk/services/target_resolver'
|
|
55
56
|
autoload :SetupWizard, 'slk/services/setup_wizard'
|
|
56
57
|
autoload :UserLookup, 'slk/services/user_lookup'
|
|
58
|
+
autoload :MessageResolver, 'slk/services/message_resolver'
|
|
57
59
|
end
|
|
58
60
|
|
|
59
61
|
# Output formatters for messages, durations, and emoji
|
|
60
62
|
module Formatters
|
|
61
63
|
autoload :Output, 'slk/formatters/output'
|
|
64
|
+
autoload :MarkdownOutput, 'slk/formatters/markdown_output'
|
|
62
65
|
autoload :DurationFormatter, 'slk/formatters/duration_formatter'
|
|
63
66
|
autoload :MentionReplacer, 'slk/formatters/mention_replacer'
|
|
64
67
|
autoload :EmojiReplacer, 'slk/formatters/emoji_replacer'
|
|
@@ -69,6 +72,8 @@ module Slk
|
|
|
69
72
|
autoload :AttachmentFormatter, 'slk/formatters/attachment_formatter'
|
|
70
73
|
autoload :BlockFormatter, 'slk/formatters/block_formatter'
|
|
71
74
|
autoload :SearchFormatter, 'slk/formatters/search_formatter'
|
|
75
|
+
autoload :SavedItemFormatter, 'slk/formatters/saved_item_formatter'
|
|
76
|
+
autoload :TextProcessor, 'slk/formatters/text_processor'
|
|
72
77
|
end
|
|
73
78
|
|
|
74
79
|
# CLI commands implementing user-facing functionality
|
|
@@ -89,6 +94,7 @@ module Slk
|
|
|
89
94
|
autoload :Emoji, 'slk/commands/emoji'
|
|
90
95
|
autoload :Config, 'slk/commands/config'
|
|
91
96
|
autoload :Help, 'slk/commands/help'
|
|
97
|
+
autoload :Later, 'slk/commands/later'
|
|
92
98
|
end
|
|
93
99
|
|
|
94
100
|
# Thin wrappers around Slack API endpoints
|
|
@@ -103,6 +109,7 @@ module Slk
|
|
|
103
109
|
autoload :Usergroups, 'slk/api/usergroups'
|
|
104
110
|
autoload :Activity, 'slk/api/activity'
|
|
105
111
|
autoload :Search, 'slk/api/search'
|
|
112
|
+
autoload :Saved, 'slk/api/saved'
|
|
106
113
|
end
|
|
107
114
|
|
|
108
115
|
# Utility classes for paths, parsing, and helpers
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: slk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Eric Boehs
|
|
@@ -32,6 +32,7 @@ files:
|
|
|
32
32
|
- lib/slk/api/conversations.rb
|
|
33
33
|
- lib/slk/api/dnd.rb
|
|
34
34
|
- lib/slk/api/emoji.rb
|
|
35
|
+
- lib/slk/api/saved.rb
|
|
35
36
|
- lib/slk/api/search.rb
|
|
36
37
|
- lib/slk/api/threads.rb
|
|
37
38
|
- lib/slk/api/usergroups.rb
|
|
@@ -45,6 +46,7 @@ files:
|
|
|
45
46
|
- lib/slk/commands/dnd.rb
|
|
46
47
|
- lib/slk/commands/emoji.rb
|
|
47
48
|
- lib/slk/commands/help.rb
|
|
49
|
+
- lib/slk/commands/later.rb
|
|
48
50
|
- lib/slk/commands/messages.rb
|
|
49
51
|
- lib/slk/commands/presence.rb
|
|
50
52
|
- lib/slk/commands/preset.rb
|
|
@@ -60,16 +62,20 @@ files:
|
|
|
60
62
|
- lib/slk/formatters/duration_formatter.rb
|
|
61
63
|
- lib/slk/formatters/emoji_replacer.rb
|
|
62
64
|
- lib/slk/formatters/json_message_formatter.rb
|
|
65
|
+
- lib/slk/formatters/markdown_output.rb
|
|
63
66
|
- lib/slk/formatters/mention_replacer.rb
|
|
64
67
|
- lib/slk/formatters/message_formatter.rb
|
|
65
68
|
- lib/slk/formatters/output.rb
|
|
66
69
|
- lib/slk/formatters/reaction_formatter.rb
|
|
70
|
+
- lib/slk/formatters/saved_item_formatter.rb
|
|
67
71
|
- lib/slk/formatters/search_formatter.rb
|
|
72
|
+
- lib/slk/formatters/text_processor.rb
|
|
68
73
|
- lib/slk/models/channel.rb
|
|
69
74
|
- lib/slk/models/duration.rb
|
|
70
75
|
- lib/slk/models/message.rb
|
|
71
76
|
- lib/slk/models/preset.rb
|
|
72
77
|
- lib/slk/models/reaction.rb
|
|
78
|
+
- lib/slk/models/saved_item.rb
|
|
73
79
|
- lib/slk/models/search_result.rb
|
|
74
80
|
- lib/slk/models/status.rb
|
|
75
81
|
- lib/slk/models/user.rb
|
|
@@ -83,6 +89,7 @@ files:
|
|
|
83
89
|
- lib/slk/services/emoji_searcher.rb
|
|
84
90
|
- lib/slk/services/encryption.rb
|
|
85
91
|
- lib/slk/services/gemoji_sync.rb
|
|
92
|
+
- lib/slk/services/message_resolver.rb
|
|
86
93
|
- lib/slk/services/preset_store.rb
|
|
87
94
|
- lib/slk/services/reaction_enricher.rb
|
|
88
95
|
- lib/slk/services/setup_wizard.rb
|
|
@@ -111,12 +118,6 @@ metadata:
|
|
|
111
118
|
source_code_uri: https://github.com/ericboehs/slk
|
|
112
119
|
changelog_uri: https://github.com/ericboehs/slk/blob/master/CHANGELOG.md
|
|
113
120
|
rubygems_mfa_required: 'true'
|
|
114
|
-
post_install_message: |
|
|
115
|
-
slk 0.2.0: Config directory changed from slack-cli to slk
|
|
116
|
-
|
|
117
|
-
If upgrading from 0.1.x, migrate your config:
|
|
118
|
-
mv ${XDG_CONFIG_HOME:-~/.config}/slack-cli ${XDG_CONFIG_HOME:-~/.config}/slk
|
|
119
|
-
mv ${XDG_CACHE_HOME:-~/.cache}/slack-cli ${XDG_CACHE_HOME:-~/.cache}/slk
|
|
120
121
|
rdoc_options: []
|
|
121
122
|
require_paths:
|
|
122
123
|
- lib
|