xdg 1.0.0 → 2.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.
@@ -0,0 +1,220 @@
1
+ module XDG
2
+
3
+ # Base Directory Standard
4
+ class BaseDir
5
+
6
+ # Try to get information from Ruby's install configuration.
7
+ require 'rbconfig'
8
+
9
+ sysconfdir = ::Config::CONFIG['sysconfdir'] || '/etc'
10
+ datadir = ::Config::CONFIG['datadir'] || '/usr/share'
11
+
12
+ # Standard defaults for locations.
13
+ DEFAULTS = {
14
+ 'XDG_DATA_HOME' => ['~/.local/share'],
15
+ 'XDG_DATA_DIRS' => ['/usr/local/share', datadir],
16
+ 'XDG_CONFIG_HOME' => ['~/.config'],
17
+ 'XDG_CONFIG_DIRS' => [File.join(sysconfdir,'xdg'), sysconfdir],
18
+ 'XDG_CACHE_HOME' => ['~/.cache'],
19
+ 'XDG_CACHE_DIRS' => ['/tmp']
20
+ }
21
+
22
+ # BaseDir iterates over directory paths.
23
+ include Enumerable
24
+
25
+ # Shortcut for `BaseDir.new`.
26
+ def self.[](*env)
27
+ new(*env)
28
+ end
29
+
30
+ # Initialize new instance of BaseDir class.
31
+ def initialize(*env)
32
+ @environment_variables = []
33
+ env.each do |v|
34
+ v = v.to_s.upcase
35
+ if v !~ /_/
36
+ @environment_variables << 'XDG_' + v + '_HOME'
37
+ @environment_variables << 'XDG_' + v + '_DIRS'
38
+ else
39
+ @environment_variables << 'XDG_' + v
40
+ end
41
+ end
42
+ end
43
+
44
+ # The environment variables being referenced.
45
+ #
46
+ # @return [Array] list of XDG environment variable names
47
+ def environment_variables
48
+ @environment_variables
49
+ end
50
+
51
+ # Returns a complete list of directories.
52
+ def to_a
53
+ environment_variables.map do |v|
54
+ if paths = ENV[v]
55
+ dirs = paths.split(/[:;]/)
56
+ else
57
+ dirs = DEFAULTS[v]
58
+ end
59
+ dirs.map{ |path| expand(path) }
60
+ end.flatten
61
+ end
62
+
63
+ # BaseDir is essentially an array.
64
+ alias_method :to_ary, :to_a
65
+
66
+ # Number of directory paths.
67
+ def size
68
+ to_a.size
69
+ end
70
+
71
+ # Iterate of each directory.
72
+ def each(&block)
73
+ to_a.each(&block)
74
+ end
75
+
76
+ # Returns a complete list of directories.
77
+ def list
78
+ to_a
79
+ end
80
+
81
+ # List of directories as Pathanme objects.
82
+ #
83
+ # @return [Array<Pathname>] list of directories as Pathname objects
84
+ def paths
85
+ map{ |dir| Pathname.new(dir) }
86
+ end
87
+
88
+ # Return array of matching files or directories
89
+ # in any of the resource locations, starting with
90
+ # the home directory and searching outward into
91
+ # system directories.
92
+ #
93
+ # Unlike #select, this doesn't take a block and each
94
+ # additional glob argument is treated as a logical-or.
95
+ #
96
+ # XDG[:DATA].glob("stick/*.rb", "stick/*.yaml")
97
+ #
98
+ def glob(*glob_and_flags)
99
+ glob, flags = *parse_arguments(*glob_and_flags)
100
+ find = []
101
+ list.each do |dir|
102
+ glob.each do |pattern|
103
+ find.concat(Dir.glob(File.join(dir, pattern), flags))
104
+ end
105
+ end
106
+ find.uniq
107
+ end
108
+
109
+ # Return array of matching files or directories
110
+ # in any of the resource locations, starting with
111
+ # the home directory and searching outward into
112
+ # system directories.
113
+ #
114
+ # String parameters are joined into a pathname
115
+ # while Integers and Symbols treated as flags.
116
+ #
117
+ # For example, the following are equivalent:
118
+ #
119
+ # XDG::BaseDir[:DATA,:HOME].select('stick/units', File::FNM_CASEFOLD)
120
+ #
121
+ # XDG::BaseDir[:DATA,:HOME].select('stick', 'units', :casefold)
122
+ #
123
+ def select(*glob_and_flags, &block)
124
+ glob, flag = *parse_arguments(*glob_and_flags)
125
+ find = []
126
+ list.each do |dir|
127
+ path = File.join(dir, *glob)
128
+ hits = Dir.glob(path, flag)
129
+ hits = hits.select(&block) if block_given?
130
+ find.concat(hits)
131
+ end
132
+ find.uniq
133
+ end
134
+
135
+ # Find a file or directory. This works just like #select
136
+ # except that it returns the first match found.
137
+ #
138
+ # TODO: It would be more efficient to traverse the dirs and use #fnmatch.
139
+ def find(*glob_and_flags, &block)
140
+ glob, flag = *parse_arguments(*glob_and_flags)
141
+ find = nil
142
+ list.each do |dir|
143
+ path = File.join(dir, *glob)
144
+ hits = Dir.glob(path, flag)
145
+ hits = hits.select(&block) if block_given?
146
+ find = hits.first
147
+ break if find
148
+ end
149
+ find
150
+ end
151
+
152
+ # @return [String] envinronment values.
153
+ def to_s
154
+ environment_variables.map{ |v| ENV[v] || DEFAULTS[v] }.join(':')
155
+ end
156
+
157
+ # @return [Pathname] pathname of first directory
158
+ def to_path
159
+ Pathname.new(to_s)
160
+ end
161
+
162
+ #
163
+ def env
164
+ environment_variables.map{ |v| ENV[v] }.join(':')
165
+ end
166
+
167
+ #
168
+ attr :subdirectory
169
+
170
+ #
171
+ def subdirectory=(path)
172
+ @subdirectory = path.to_s
173
+ end
174
+
175
+ #
176
+ def with_subdirectory(path)
177
+ @subdirectory = path if path
178
+ self
179
+ end
180
+
181
+ private
182
+
183
+ def parse_arguments(*glob_and_flags)
184
+ glob, flags = *glob_and_flags.partition{ |e| String===e }
185
+ glob = ['**/*'] if glob.empty?
186
+ flag = flags.inject(0) do |m, f|
187
+ if Symbol === f
188
+ m + File::const_get("FNM_#{f.to_s.upcase}")
189
+ else
190
+ m + f.to_i
191
+ end
192
+ end
193
+ return glob, flag
194
+ end
195
+
196
+ #
197
+ def expand(path)
198
+ if subdirectory
199
+ File.expand_path(File.join(path, subdirectory))
200
+ else
201
+ File.expand_path(path)
202
+ end
203
+ end
204
+
205
+ # If Pathname is referenced the library is automatically loaded.
206
+ def self.const_missing(const)
207
+ if const == :Pathname
208
+ require 'pathname'
209
+ ::Pathname
210
+ else
211
+ super(const)
212
+ end
213
+ end
214
+
215
+ end
216
+
217
+ end
218
+
219
+ # Copyright (c) 2008,2011 Thomas Sawyer
220
+ # Distributed under the terms of the APACHE 2.0 license.
@@ -0,0 +1,20 @@
1
+ module XDG
2
+
3
+ # Base directory interface class.
4
+ class BaseDir
5
+
6
+ #
7
+ DEFAULTS['XDG_RESOURCE_HOME'] = ['~/.local']
8
+ DEFAULTS['XDG_RESOURCE_DIRS'] = ['/usr/local','/usr']
9
+
10
+ # Working directory
11
+ # TODO: Not sure about these defaults
12
+ DEFAULTS['XDG_CONFIG_WORK'] = ['.config','config']
13
+ DEFAULTS['XDG_CACHE_WORK'] = ['.tmp','tmp']
14
+ DEFAULTS['XDG_RESOURCE_WORK'] = ['.local']
15
+ end
16
+
17
+ end
18
+
19
+ # Copyright (c) 2008,2011 Thomas Sawyer
20
+ # Distributed under the terms of the APACHE 2.0 license.
@@ -0,0 +1,18 @@
1
+ if RUBY_VERSION > '1.9'
2
+ require_relative 'base_dir'
3
+ else
4
+ require 'xdg/base_dir'
5
+ end
6
+
7
+ $XDG_DATA = XDG::BaseDir.new('DATA')
8
+ $XDG_DATA_HOME = XDG::BaseDir.new('DATA', 'HOME')
9
+ $XDG_DATA_DIRS = XDG::BaseDir.new('DATA', 'DIRS')
10
+
11
+ $XDG_CONFIG = XDG::BaseDir.new('CONFIG')
12
+ $XDG_CONFIG_HOME = XDG::BaseDir.new('CONFIG', 'HOME')
13
+ $XDG_CONFIG_DIRS = XDG::BaseDir.new('CONFIG', 'DIRS')
14
+
15
+ $XDG_CACHE = XDG::BaseDir.new('CACHE')
16
+ $XDG_CACHE_HOME = XDG::BaseDir.new('CACHE', 'HOME')
17
+ $XDG_CACHE_DIRS = XDG::BaseDir.new('CACHE', 'DIRS')
18
+
@@ -0,0 +1,72 @@
1
+ module XDG
2
+ class BaseDir
3
+ # Legacy API can serve as a stop gap until a developer
4
+ # has time to update an program already using XDG.
5
+ #
6
+ # Do NOT use this module for future development!!!
7
+ module Legacy
8
+ #
9
+ require 'xdg'
10
+ require 'xdg/base_dir/extended'
11
+
12
+ #
13
+ extend self
14
+
15
+ #
16
+ def home
17
+ File.expand_path('~')
18
+ end
19
+
20
+ #
21
+ def data
22
+ obj = XDG['DATA']
23
+ class << obj
24
+ def home
25
+ XDG['DATA_HOME'].to_a.first
26
+ end
27
+ def dirs
28
+ XDG['DATA_DIRS'].to_a
29
+ end
30
+ end
31
+ return obj
32
+ end
33
+
34
+ #
35
+ def config
36
+ obj = XDG['CONFIG']
37
+ class << obj
38
+ def home
39
+ XDG['CONFIG_HOME'].to_a.first
40
+ end
41
+ def dirs
42
+ XDG['CONFIG_DIRS'].to_a
43
+ end
44
+ def work
45
+ XDG['CONFIG_WORK'].to_a
46
+ end
47
+ end
48
+ return obj
49
+ end
50
+
51
+ #
52
+ def cache
53
+ obj = XDG['CACHE']
54
+ class << obj
55
+ def home
56
+ XDG['CACHE_HOME'].to_a.first
57
+ end
58
+ def dirs
59
+ XDG['CACHE_DIRS'].to_a
60
+ end
61
+ def work
62
+ XDG['CACHE_WORK'].to_a
63
+ end
64
+ end
65
+ return obj
66
+ end
67
+
68
+ end
69
+ end
70
+
71
+ extend BaseDir::Legacy
72
+ end
@@ -0,0 +1,84 @@
1
+ module XDG
2
+ class BaseDir
3
+ #
4
+ # The BaseDir::Mixin module can be used to add XDG base directory
5
+ # methods to your own classes.
6
+ #
7
+ # class MyAppConfig
8
+ # include XDG::BaseDir::Mixin
9
+ #
10
+ # def subdirectory
11
+ # 'myapp'
12
+ # end
13
+ # end
14
+ #
15
+ # c = MyAppConfig.new
16
+ #
17
+ # c.config.home.to_s #=> '~/.config/myapp'
18
+ #
19
+ module Mixin
20
+
21
+ # @todo do we need this?
22
+ extend self
23
+
24
+ # Override this method to change the subdirectory of the mixin.
25
+ def subdirectory
26
+ nil
27
+ end
28
+
29
+ #
30
+ def home
31
+ File.expand_path('~')
32
+ end
33
+
34
+ #
35
+ def data
36
+ obj = XDG['DATA'].with_subdirectory(subdirectory)
37
+ class << obj
38
+ def home
39
+ XDG['DATA_HOME'].with_subdirectory(subdirectory)
40
+ end
41
+ def dirs
42
+ XDG['DATA_DIRS'].with_subdirectory(subdirectory)
43
+ end
44
+ end
45
+ return obj
46
+ end
47
+
48
+ #
49
+ def config
50
+ obj = XDG['CONFIG'].with_subdirectory(subdirectory)
51
+ class << obj
52
+ def home
53
+ XDG['CONFIG_HOME'].with_subdirectory(subdirectory)
54
+ end
55
+ def dirs
56
+ XDG['CONFIG_DIRS'].with_subdirectory(subdirectory)
57
+ end
58
+ def work
59
+ XDG['CONFIG_WORK'].with_subdirectory(subdirectory)
60
+ end
61
+ end
62
+ return obj
63
+ end
64
+
65
+ #
66
+ def cache
67
+ obj = XDG['CACHE'].with_subdirectory(subdirectory)
68
+ class << obj
69
+ def home
70
+ XDG['CACHE_HOME'].with_subdirectory(subdirectory)
71
+ end
72
+ def dirs
73
+ XDG['CACHE_DIRS'].with_subdirectory(subdirectory)
74
+ end
75
+ def work
76
+ XDG['CACHE_WORK'].with_subdirectory(subdirectory)
77
+ end
78
+ end
79
+ return obj
80
+ end
81
+
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,3 @@
1
+ module XDG
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,77 @@
1
+ = XDG Base Directory Standard
2
+
3
+ The 2.0 API is much a great deal more concise than the original
4
+ 0.0+ and 1.0+ APIs. It consists primarily of a single
5
+ interface method `XDG[]`. Yet all the functionality of the older
6
+ API remain and then some.
7
+
8
+ First we need to require the library.
9
+
10
+ require 'xdg'
11
+
12
+ In the applique we have setup a fake root directory with
13
+ coorepsonding environment settings to use as test fixtures.
14
+
15
+ == Data Paths
16
+
17
+ === Home
18
+
19
+ XDG['DATA_HOME'].env.assert == ENV['XDG_DATA_HOME'].to_s
20
+ XDG['DATA_HOME'].environment_variables.assert == ['XDG_DATA_HOME']
21
+
22
+ Looking at the data home location by default it should be point to
23
+ our joe user's home directory under `.local/share`.
24
+
25
+ XDG['DATA_HOME'].to_a.assert == [$froot + 'home/joe/.local/share']
26
+
27
+ === Dirs
28
+
29
+ XDG['DATA_DIRS'].env.assert == ENV['XDG_DATA_DIRS'].to_s
30
+ XDG['DATA_DIRS'].environment_variables.assert == ['XDG_DATA_DIRS']
31
+
32
+ Looking at the system data locations
33
+
34
+ XDG['DATA_DIRS'].to_a.assert == [$froot + 'usr/share']
35
+
36
+ === Combined
37
+
38
+ XDG['DATA'].environment_variables.assert == ['XDG_DATA_HOME', 'XDG_DATA_DIRS']
39
+
40
+ Lookking at both data location combined
41
+
42
+ XDG['DATA'].to_a.assert == [$froot + 'home/joe/.local/share', $froot + 'usr/share']
43
+
44
+
45
+ == Config Paths
46
+
47
+ === Home
48
+
49
+ XDG['CONFIG_HOME'].env.assert == ENV['XDG_CONFIG_HOME'].to_s
50
+ XDG['CONFIG_HOME'].to_a.assert == [$froot + 'home/joe/.config']
51
+
52
+ === Dirs
53
+
54
+ XDG['CONFIG_DIRS'].env.assert == ENV['XDG_CONFIG_DIRS'].to_s
55
+ XDG['CONFIG_DIRS'].to_a.assert == [$froot + 'etc/xdg', $froot + 'etc']
56
+
57
+ === Combined
58
+
59
+ XDG['CONFIG'].to_a.assert == [$froot + 'home/joe/.config', $froot + 'etc/xdg', $froot + 'etc']
60
+
61
+
62
+ == Cache Paths
63
+
64
+ === Home
65
+
66
+ XDG['CACHE_HOME'].env.assert == ENV['XDG_CACHE_HOME'].to_s
67
+ XDG['CACHE_HOME'].to_a.assert == [$froot + 'home/joe/.cache']
68
+
69
+ === Dirs
70
+
71
+ XDG['CACHE_DIRS'].env.assert == ENV['XDG_CACHE_DIRS'].to_s
72
+ XDG['CACHE_DIRS'].to_a.assert == [$froot + 'tmp']
73
+
74
+ === Combined
75
+
76
+ XDG['CACHE'].to_a.assert == [$froot + 'home/joe/.cache', $froot + 'tmp']
77
+