dockedit 1.0.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 +7 -0
- data/.rspec +4 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +37 -0
- data/README.md +262 -0
- data/Rakefile +97 -0
- data/bin/dockedit +10 -0
- data/build_standalone.rb +88 -0
- data/dockedit +1461 -0
- data/lib/dockedit/app_finder.rb +46 -0
- data/lib/dockedit/cli.rb +166 -0
- data/lib/dockedit/commands.rb +372 -0
- data/lib/dockedit/constants.rb +44 -0
- data/lib/dockedit/dock.rb +98 -0
- data/lib/dockedit/folder_updater.rb +58 -0
- data/lib/dockedit/matcher.rb +136 -0
- data/lib/dockedit/parsers.rb +62 -0
- data/lib/dockedit/path_utils.rb +44 -0
- data/lib/dockedit/plist_reader.rb +158 -0
- data/lib/dockedit/plist_writer.rb +52 -0
- data/lib/dockedit/tile_factory.rb +189 -0
- data/lib/dockedit/version.rb +7 -0
- data/lib/dockedit.rb +25 -0
- metadata +82 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DockEdit
|
|
4
|
+
# Factory for creating Dock tile elements.
|
|
5
|
+
#
|
|
6
|
+
# These helpers construct the REXML structures that represent apps,
|
|
7
|
+
# folders, and spacer tiles inside the Dock plist.
|
|
8
|
+
class TileFactory
|
|
9
|
+
# Create a spacer tile element.
|
|
10
|
+
#
|
|
11
|
+
# @param small [Boolean] When +true+, create a half-size spacer.
|
|
12
|
+
# @return [REXML::Element] Newly created tile `<dict>` element.
|
|
13
|
+
def self.create_spacer_tile(small: false)
|
|
14
|
+
tile_type = small ? 'small-spacer-tile' : 'spacer-tile'
|
|
15
|
+
|
|
16
|
+
spacer = REXML::Element.new('dict')
|
|
17
|
+
|
|
18
|
+
key1 = REXML::Element.new('key')
|
|
19
|
+
key1.text = 'tile-data'
|
|
20
|
+
spacer.add(key1)
|
|
21
|
+
|
|
22
|
+
tile_data = REXML::Element.new('dict')
|
|
23
|
+
label_key = REXML::Element.new('key')
|
|
24
|
+
label_key.text = 'file-label'
|
|
25
|
+
tile_data.add(label_key)
|
|
26
|
+
label_string = REXML::Element.new('string')
|
|
27
|
+
label_string.text = ''
|
|
28
|
+
tile_data.add(label_string)
|
|
29
|
+
spacer.add(tile_data)
|
|
30
|
+
|
|
31
|
+
key2 = REXML::Element.new('key')
|
|
32
|
+
key2.text = 'tile-type'
|
|
33
|
+
spacer.add(key2)
|
|
34
|
+
|
|
35
|
+
type_string = REXML::Element.new('string')
|
|
36
|
+
type_string.text = tile_type
|
|
37
|
+
spacer.add(type_string)
|
|
38
|
+
|
|
39
|
+
spacer
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Create an app tile element.
|
|
43
|
+
#
|
|
44
|
+
# @param app_path [String] Absolute path to the `.app` bundle.
|
|
45
|
+
# @param app_info [Hash] Parsed plist info from {PlistReader.read_app_info}.
|
|
46
|
+
# @return [REXML::Element] Newly created tile `<dict>` element.
|
|
47
|
+
def self.create_app_tile(app_path, app_info)
|
|
48
|
+
app_dict = REXML::Element.new('dict')
|
|
49
|
+
|
|
50
|
+
# tile-data key
|
|
51
|
+
td_key = REXML::Element.new('key')
|
|
52
|
+
td_key.text = 'tile-data'
|
|
53
|
+
app_dict.add(td_key)
|
|
54
|
+
|
|
55
|
+
# tile-data dict
|
|
56
|
+
tile_data = REXML::Element.new('dict')
|
|
57
|
+
|
|
58
|
+
# bundle-identifier
|
|
59
|
+
add_plist_key_value(tile_data, 'bundle-identifier', 'string', app_info['CFBundleIdentifier'])
|
|
60
|
+
|
|
61
|
+
# dock-extra
|
|
62
|
+
add_plist_key_value(tile_data, 'dock-extra', 'false', nil)
|
|
63
|
+
|
|
64
|
+
# file-data dict
|
|
65
|
+
fd_key = REXML::Element.new('key')
|
|
66
|
+
fd_key.text = 'file-data'
|
|
67
|
+
tile_data.add(fd_key)
|
|
68
|
+
|
|
69
|
+
file_data = REXML::Element.new('dict')
|
|
70
|
+
add_plist_key_value(file_data, '_CFURLString', 'string', "file://#{URI.encode_www_form_component(app_path).gsub('%2F', '/')}/")
|
|
71
|
+
add_plist_key_value(file_data, '_CFURLStringType', 'integer', '15')
|
|
72
|
+
tile_data.add(file_data)
|
|
73
|
+
|
|
74
|
+
# file-label
|
|
75
|
+
label = app_info['CFBundleName'] || app_info['CFBundleDisplayName'] || File.basename(app_path, '.app')
|
|
76
|
+
add_plist_key_value(tile_data, 'file-label', 'string', label)
|
|
77
|
+
|
|
78
|
+
# file-mod-date
|
|
79
|
+
add_plist_key_value(tile_data, 'file-mod-date', 'integer', '0')
|
|
80
|
+
|
|
81
|
+
# file-type
|
|
82
|
+
add_plist_key_value(tile_data, 'file-type', 'integer', '41')
|
|
83
|
+
|
|
84
|
+
# is-beta
|
|
85
|
+
add_plist_key_value(tile_data, 'is-beta', 'false', nil)
|
|
86
|
+
|
|
87
|
+
# parent-mod-date
|
|
88
|
+
add_plist_key_value(tile_data, 'parent-mod-date', 'integer', '0')
|
|
89
|
+
|
|
90
|
+
app_dict.add(tile_data)
|
|
91
|
+
|
|
92
|
+
# tile-type key
|
|
93
|
+
tt_key = REXML::Element.new('key')
|
|
94
|
+
tt_key.text = 'tile-type'
|
|
95
|
+
app_dict.add(tt_key)
|
|
96
|
+
|
|
97
|
+
tt_value = REXML::Element.new('string')
|
|
98
|
+
tt_value.text = 'file-tile'
|
|
99
|
+
app_dict.add(tt_value)
|
|
100
|
+
|
|
101
|
+
app_dict
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Create a folder tile element.
|
|
105
|
+
#
|
|
106
|
+
# @param folder_path [String] Absolute path to the folder.
|
|
107
|
+
# @param show_as [Integer] Show-as value (1=fan, 2=grid, 3=list, 4=auto).
|
|
108
|
+
# @param display_as [Integer] Display-as value (0=stack, 1=folder).
|
|
109
|
+
# @return [REXML::Element] Newly created folder tile `<dict>` element.
|
|
110
|
+
def self.create_folder_tile(folder_path, show_as: 4, display_as: 1)
|
|
111
|
+
folder_dict = REXML::Element.new('dict')
|
|
112
|
+
|
|
113
|
+
# tile-data key
|
|
114
|
+
td_key = REXML::Element.new('key')
|
|
115
|
+
td_key.text = 'tile-data'
|
|
116
|
+
folder_dict.add(td_key)
|
|
117
|
+
|
|
118
|
+
# tile-data dict
|
|
119
|
+
tile_data = REXML::Element.new('dict')
|
|
120
|
+
|
|
121
|
+
# arrangement (0 = by name)
|
|
122
|
+
add_plist_key_value(tile_data, 'arrangement', 'integer', '0')
|
|
123
|
+
|
|
124
|
+
# displayas (0 = stack, 1 = folder)
|
|
125
|
+
add_plist_key_value(tile_data, 'displayas', 'integer', display_as.to_s)
|
|
126
|
+
|
|
127
|
+
# file-data dict
|
|
128
|
+
fd_key = REXML::Element.new('key')
|
|
129
|
+
fd_key.text = 'file-data'
|
|
130
|
+
tile_data.add(fd_key)
|
|
131
|
+
|
|
132
|
+
file_data = REXML::Element.new('dict')
|
|
133
|
+
encoded_path = URI.encode_www_form_component(folder_path).gsub('%2F', '/')
|
|
134
|
+
add_plist_key_value(file_data, '_CFURLString', 'string', "file://#{encoded_path}/")
|
|
135
|
+
add_plist_key_value(file_data, '_CFURLStringType', 'integer', '15')
|
|
136
|
+
tile_data.add(file_data)
|
|
137
|
+
|
|
138
|
+
# file-label
|
|
139
|
+
label = File.basename(folder_path)
|
|
140
|
+
add_plist_key_value(tile_data, 'file-label', 'string', label)
|
|
141
|
+
|
|
142
|
+
# file-mod-date
|
|
143
|
+
add_plist_key_value(tile_data, 'file-mod-date', 'integer', '0')
|
|
144
|
+
|
|
145
|
+
# file-type
|
|
146
|
+
add_plist_key_value(tile_data, 'file-type', 'integer', '2')
|
|
147
|
+
|
|
148
|
+
# parent-mod-date
|
|
149
|
+
add_plist_key_value(tile_data, 'parent-mod-date', 'integer', '0')
|
|
150
|
+
|
|
151
|
+
# preferreditemsize (-1 = default)
|
|
152
|
+
add_plist_key_value(tile_data, 'preferreditemsize', 'integer', '-1')
|
|
153
|
+
|
|
154
|
+
# showas (1=fan, 2=grid, 3=list, 4=auto)
|
|
155
|
+
add_plist_key_value(tile_data, 'showas', 'integer', show_as.to_s)
|
|
156
|
+
|
|
157
|
+
folder_dict.add(tile_data)
|
|
158
|
+
|
|
159
|
+
# tile-type key
|
|
160
|
+
tt_key = REXML::Element.new('key')
|
|
161
|
+
tt_key.text = 'tile-type'
|
|
162
|
+
folder_dict.add(tt_key)
|
|
163
|
+
|
|
164
|
+
tt_value = REXML::Element.new('string')
|
|
165
|
+
tt_value.text = 'directory-tile'
|
|
166
|
+
folder_dict.add(tt_value)
|
|
167
|
+
|
|
168
|
+
folder_dict
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Helper to add a key/value pair to a plist `<dict>` element.
|
|
172
|
+
#
|
|
173
|
+
# @param dict [REXML::Element] Target `<dict>` element.
|
|
174
|
+
# @param key_name [String] Key to add.
|
|
175
|
+
# @param value_type [String] Name of the value element type (e.g. "string").
|
|
176
|
+
# @param value [String, nil] Optional text value for the element.
|
|
177
|
+
# @return [void]
|
|
178
|
+
def self.add_plist_key_value(dict, key_name, value_type, value)
|
|
179
|
+
key = REXML::Element.new('key')
|
|
180
|
+
key.text = key_name
|
|
181
|
+
dict.add(key)
|
|
182
|
+
|
|
183
|
+
val_elem = REXML::Element.new(value_type)
|
|
184
|
+
val_elem.text = value if value
|
|
185
|
+
dict.add(val_elem)
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
data/lib/dockedit.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# dockedit - A script to edit the macOS Dock
|
|
4
|
+
# Usage: dockedit <subcommand> [options] [args]
|
|
5
|
+
|
|
6
|
+
require 'rexml/document'
|
|
7
|
+
require 'fileutils'
|
|
8
|
+
require 'optparse'
|
|
9
|
+
require 'uri'
|
|
10
|
+
require 'stringio'
|
|
11
|
+
|
|
12
|
+
require_relative 'dockedit/version'
|
|
13
|
+
require_relative 'dockedit/constants'
|
|
14
|
+
require_relative 'dockedit/matcher'
|
|
15
|
+
require_relative 'dockedit/path_utils'
|
|
16
|
+
require_relative 'dockedit/plist_reader'
|
|
17
|
+
require_relative 'dockedit/plist_writer'
|
|
18
|
+
require_relative 'dockedit/app_finder'
|
|
19
|
+
require_relative 'dockedit/tile_factory'
|
|
20
|
+
require_relative 'dockedit/folder_updater'
|
|
21
|
+
require_relative 'dockedit/parsers'
|
|
22
|
+
require_relative 'dockedit/dock'
|
|
23
|
+
require_relative 'dockedit/commands'
|
|
24
|
+
require_relative 'dockedit/cli'
|
|
25
|
+
|
metadata
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: dockedit
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Brett Terpstra
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rexml
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '3.2'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '3.2'
|
|
26
|
+
description: dockedit allows you to add, remove, move, and manage apps and folders
|
|
27
|
+
in your macOS Dock from the command line
|
|
28
|
+
email:
|
|
29
|
+
- github@brettterpstra.com
|
|
30
|
+
executables:
|
|
31
|
+
- dockedit
|
|
32
|
+
extensions: []
|
|
33
|
+
extra_rdoc_files: []
|
|
34
|
+
files:
|
|
35
|
+
- ".rspec"
|
|
36
|
+
- CHANGELOG.md
|
|
37
|
+
- Gemfile
|
|
38
|
+
- Gemfile.lock
|
|
39
|
+
- README.md
|
|
40
|
+
- Rakefile
|
|
41
|
+
- bin/dockedit
|
|
42
|
+
- build_standalone.rb
|
|
43
|
+
- dockedit
|
|
44
|
+
- lib/dockedit.rb
|
|
45
|
+
- lib/dockedit/app_finder.rb
|
|
46
|
+
- lib/dockedit/cli.rb
|
|
47
|
+
- lib/dockedit/commands.rb
|
|
48
|
+
- lib/dockedit/constants.rb
|
|
49
|
+
- lib/dockedit/dock.rb
|
|
50
|
+
- lib/dockedit/folder_updater.rb
|
|
51
|
+
- lib/dockedit/matcher.rb
|
|
52
|
+
- lib/dockedit/parsers.rb
|
|
53
|
+
- lib/dockedit/path_utils.rb
|
|
54
|
+
- lib/dockedit/plist_reader.rb
|
|
55
|
+
- lib/dockedit/plist_writer.rb
|
|
56
|
+
- lib/dockedit/tile_factory.rb
|
|
57
|
+
- lib/dockedit/version.rb
|
|
58
|
+
homepage: https://github.com/ttscoff/dockedit
|
|
59
|
+
licenses:
|
|
60
|
+
- MIT
|
|
61
|
+
metadata:
|
|
62
|
+
homepage_uri: https://github.com/ttscoff/dockedit
|
|
63
|
+
source_code_uri: https://github.com/ttscoff/dockedit
|
|
64
|
+
changelog_uri: https://github.com/ttscoff/dockedit/blob/main/CHANGELOG.md
|
|
65
|
+
rdoc_options: []
|
|
66
|
+
require_paths:
|
|
67
|
+
- lib
|
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
69
|
+
requirements:
|
|
70
|
+
- - ">="
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: 2.7.0
|
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
74
|
+
requirements:
|
|
75
|
+
- - ">="
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: '0'
|
|
78
|
+
requirements: []
|
|
79
|
+
rubygems_version: 3.6.7
|
|
80
|
+
specification_version: 4
|
|
81
|
+
summary: A command-line tool to edit the macOS Dock
|
|
82
|
+
test_files: []
|