mate 2.1.1 → 3.1.0

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: c775458d416142a253db083e4d9c60a0f54d826cca9b02b4529a95b52a679b86
4
- data.tar.gz: 2b80d97ceaf6f1dffb92666cbe5bd35178ac5f018ea44c0008ce18570b3c12fc
3
+ metadata.gz: af1807dfe07bd73b3f6f6f1bf995e9f7dfb53c6ca77a04c3d8a7c300d4b8d44f
4
+ data.tar.gz: f55507e729d7c4c2cfb0c26a22e664db8f82f1df3df9e380af0fc34c31a0d80d
5
5
  SHA512:
6
- metadata.gz: 32f73c550e6dd223f666bef6bf245d33827cddba3622a2a2a71033cc9a4c129636c036fc9f33a004ab055cf2290a5e5c3eadc38e2d91c5bc030c5576a19297b5
7
- data.tar.gz: 13d6e400fef725d92257084a779b63bce93b6186e83ed7705208041f61932f8785e6a083fff42cc5c8f451b59867aa6bece381c567f12f39616e9d462675a137
6
+ metadata.gz: 0420bdd314f766093447f27d14b754f30a84dbdc992dc0671df7f775e37032b25bd26b9411443563d33222c8db0e48131d03fabc8fecc2ab2655afea1c66f5cc
7
+ data.tar.gz: fd4824a180151d3bdb5e27d052b4d09998a18e0569c27cc7f9879af78f0950c4ea0ba98517d20d15829ac2dd09469be78521f58aa09c7ddd42f2d3c40e25762b
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010-2019 Ivan Kuchin
1
+ Copyright (c) 2010-2022 Ivan Kuchin
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.markdown CHANGED
@@ -1,11 +1,11 @@
1
1
  # mate
2
2
 
3
- TextMate project builder and TextMate 2 properties builder using git ignores for exclusions.
3
+ TextMate 2 properties builder using git ignores for exclusions.
4
4
 
5
- You can add `alias mate='tm'` or `alias mate='tm2'` to your `.profile`, `.bash_profile` …
5
+ You can add `alias mate='tm2'` to your `.profile`, `.bash_profile` …
6
6
 
7
- When `tm` command (or `mate` if aliased) is called with one or more paths and any of them is a directory, than project is created in `~/.tmprojs/` and opened. When `tm2` command (or `mate` if aliased) is called with one or more paths, for all directories a `.tm_properties` file is generated or changed and mate is called. Its file and folder filters are built based on all types of git ignores (global, `.gitignore` and `.git/info/exclude`) and special `.tmignore` which works like other ignore files for project but doesn't affect git itself (you can use global `~/.tmignore` file), also `.git` folder and certain files (images, archives, media files, logs and some other binary files) are filtered.
7
+ When `tm2` command (or `mate` if aliased) is called with one or more paths, for all directories a `.tm_properties` file is generated or changed and mate is called. Its file and folder filters are built based on all types of git ignores (global, `.gitignore` and `.git/info/exclude`) and special `.tmignore` which works like other ignore files for project but doesn't affect git itself (you can use global `~/.tmignore` file), also `.git` folder and certain files (images, archives, media files, logs and some other binary files) are filtered.
8
8
 
9
9
  ## Copyright
10
10
 
11
- Copyright (c) 2010-2019 Ivan Kuchin. See LICENSE.txt for details.
11
+ Copyright (c) 2010-2022 Ivan Kuchin. See LICENSE.txt for details.
data/bin/tm2 CHANGED
@@ -1,11 +1,22 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'optparse'
4
+
3
5
  require 'mate/bin'
4
6
  require 'mate/tm_properties'
5
7
 
8
+ options = {}
9
+ OptionParser.new do |op|
10
+ op.banner = "Usage: #{op.program_name} [options] dir [...]"
11
+
12
+ op.on('--no-info-exclude', 'Skip reading .git/info/exclude') do
13
+ options[:skip_info_exclude] = true
14
+ end
15
+ end.order!
16
+
6
17
  ARGV.each do |arg|
7
18
  if File.directory?(arg)
8
- Mate::TmProperties.new(arg).save
19
+ Mate::TmProperties.create(arg, options)
9
20
  end
10
21
  end
11
22
 
data/lib/mate/bin.rb CHANGED
@@ -3,10 +3,6 @@ require 'shellwords'
3
3
  module Mate
4
4
  module Bin
5
5
  class << self
6
- def v1
7
- mate_version(/^mate r\d+/) or abort 'Can\'t find mate binary v1'
8
- end
9
-
10
6
  def v2
11
7
  mate_version(/^mate 2.\d+/) or abort 'Can\'t find mate binary v2'
12
8
  end
data/lib/mate/git.rb ADDED
@@ -0,0 +1,32 @@
1
+ module Mate
2
+ module Git
3
+ class << self
4
+ def excludesfile(workind_dir)
5
+ expand_path IO.popen(%W[git -C #{workind_dir} config --get core.excludesfile], &:read)
6
+ end
7
+
8
+ def global_tmignore
9
+ expand_path '~/.tmignore'
10
+ end
11
+
12
+ def toplevel(workind_dir)
13
+ expand_path IO.popen(%W[git -C #{workind_dir} rev-parse --show-toplevel], err: '/dev/null', &:read)
14
+ end
15
+
16
+ def git_dir(workind_dir)
17
+ expand_path IO.popen(%W[git -C #{workind_dir} rev-parse --absolute-git-dir], err: '/dev/null', &:read)
18
+ end
19
+
20
+ private
21
+
22
+ def expand_path(path)
23
+ return unless path
24
+
25
+ path = path.strip
26
+ return if path == ''
27
+
28
+ Pathname(path).expand_path
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,35 +1,48 @@
1
+ require 'mate/git'
2
+
1
3
  module Mate
2
4
  class TmProperties::Ignores
3
- GENERATED_SUFFIX = "## GENERATED ##"
5
+ GENERATED_SUFFIX = '## GENERATED ##'
4
6
  GENERATED_R = /^exclude(?:Directories)? = .* #{Regexp.escape(GENERATED_SUFFIX)}$/
5
7
 
6
8
  attr_reader :dir
7
- def initialize(dir)
9
+ def initialize(dir, options)
8
10
  @dir = dir
9
11
  @exclude = ['**/.git']
10
12
  @exclude_directories = []
11
13
 
12
- process(dir, '.', Pathname(`git config --get core.excludesfile`.strip).expand_path)
13
- process(dir, '.', Pathname('~/.tmignore').expand_path)
14
+ process('.', Git.excludesfile(dir))
15
+ process('.', Git.global_tmignore)
16
+ if !options[:skip_info_exclude] && (git_dir = Git.git_dir(dir))
17
+ process('.', git_dir + 'info/exclude')
18
+ end
14
19
 
15
20
  dir.find do |path|
16
- if path.directory?
21
+ next unless path.lstat.directory?
22
+
23
+ toplevel = dir == path
24
+
25
+ if !toplevel && (path + '.git').exist?
26
+ TmProperties.new(path, options).save
27
+ Find.prune
28
+ else
17
29
  relative_path = path.relative_path_from(dir).to_s
18
30
  Find.prune if ignore_dir?(relative_path)
19
- %w[.gitignore .tmignore .git/info/exclude].each do |ignore_file_name|
20
- if (ignore_file = path + ignore_file_name).file?
21
- process(dir, relative_path, ignore_file)
22
- end
31
+ %w[.gitignore .tmignore].each do |ignore_file_name|
32
+ process(relative_path, path + ignore_file_name)
33
+ end
34
+
35
+ if !toplevel && (path + '.tm_properties').exist?
36
+ TmProperties.new(path, options).cleanup
23
37
  end
24
38
  end
25
39
  end
26
40
  end
27
41
 
28
42
  def lines
29
- escaped_dir = glob_escape(dir.to_s)
30
43
  [
31
- "exclude = '#{escaped_dir}/#{glob_join(@exclude)}' #{GENERATED_SUFFIX}",
32
- "excludeDirectories = '#{escaped_dir}/#{glob_join(@exclude_directories)}' #{GENERATED_SUFFIX}",
44
+ "exclude = '$CWD/#{glob_join(@exclude)}' #{GENERATED_SUFFIX}",
45
+ "excludeDirectories = '$CWD/#{glob_join(@exclude_directories)}' #{GENERATED_SUFFIX}",
33
46
  ].map{ |line| line.gsub("\r", '\r') }
34
47
  end
35
48
 
@@ -43,8 +56,8 @@ module Mate
43
56
  end
44
57
  end
45
58
 
46
- def process(parent, subdirectory, ignore_file)
47
- return unless ignore_file.exist?
59
+ def process(subdirectory, ignore_file)
60
+ return unless ignore_file && ignore_file.exist?
48
61
 
49
62
  prefix = subdirectory == '.' ? '' : glob_escape("#{subdirectory}/")
50
63
 
@@ -1,26 +1,40 @@
1
1
  require 'pathname'
2
+ require 'mate/git'
2
3
 
3
4
  module Mate
4
5
  class TmProperties
5
- attr_reader :dir, :file
6
- def initialize(dir)
6
+ def self.create(dir, options)
7
+ new(Git.toplevel(dir) || dir, options).save
8
+ end
9
+
10
+ def initialize(dir, options)
7
11
  @dir = Pathname(dir).expand_path
8
12
  @file = @dir + '.tm_properties'
13
+ @lines = @file.exist? ? @file.read.split("\n") : []
14
+ @other_lines = @lines.reject{ |line| line =~ Ignores::GENERATED_R }
15
+ @options = options
9
16
  end
10
17
 
11
18
  def save
12
- ignores = Ignores.new(dir)
19
+ ignores = Ignores.new(@dir, @options)
20
+
21
+ write(ignores.lines + @other_lines)
22
+ end
13
23
 
14
- lines = if file.exist?
15
- file.readlines.reject do |line|
16
- line =~ Ignores::GENERATED_R
17
- end
24
+ def cleanup
25
+ if @other_lines.empty?
26
+ @file.unlink if @file.exist?
18
27
  else
19
- []
28
+ write(@other_lines)
20
29
  end
30
+ end
31
+
32
+ private
33
+
34
+ def write(lines)
35
+ return if lines == @lines
21
36
 
22
37
  @file.open('w') do |f|
23
- f.puts ignores.lines
24
38
  f.puts lines
25
39
  end
26
40
  end
data/mate.gemspec CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'mate'
5
- s.version = '2.1.1'
6
- s.summary = %q{TextMate project builder and TextMate 2 properties builder using git ignores for exclusions}
7
- s.homepage = "http://github.com/toy/#{s.name}"
5
+ s.version = '3.1.0'
6
+ s.summary = %q{TextMate 2 properties builder using git ignores for exclusions}
7
+ s.homepage = "https://github.com/toy/#{s.name}"
8
8
  s.authors = ['Ivan Kuchin']
9
9
  s.license = 'MIT'
10
10
 
@@ -18,6 +18,4 @@ Gem::Specification.new do |s|
18
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
19
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
20
  s.require_paths = %w[lib]
21
-
22
- s.add_runtime_dependency 'plist'
23
21
  end
metadata CHANGED
@@ -1,33 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mate
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Kuchin
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-14 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: plist
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- description:
28
- email:
11
+ date: 2022-06-14 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
29
15
  executables:
30
- - tm
31
16
  - tm2
32
17
  extensions: []
33
18
  extra_rdoc_files: []
@@ -35,22 +20,20 @@ files:
35
20
  - ".gitignore"
36
21
  - LICENSE.txt
37
22
  - README.markdown
38
- - bin/tm
39
23
  - bin/tm2
40
24
  - lib/mate/bin.rb
25
+ - lib/mate/git.rb
41
26
  - lib/mate/tm_properties.rb
42
27
  - lib/mate/tm_properties/ignores.rb
43
- - lib/mate/tmproj.rb
44
- - lib/mate/tmproj/ignores.rb
45
28
  - mate.gemspec
46
- homepage: http://github.com/toy/mate
29
+ homepage: https://github.com/toy/mate
47
30
  licenses:
48
31
  - MIT
49
32
  metadata:
50
33
  bug_tracker_uri: https://github.com/toy/mate/issues
51
- documentation_uri: https://www.rubydoc.info/gems/mate/2.1.1
34
+ documentation_uri: https://www.rubydoc.info/gems/mate/3.1.0
52
35
  source_code_uri: https://github.com/toy/mate
53
- post_install_message:
36
+ post_install_message:
54
37
  rdoc_options: []
55
38
  require_paths:
56
39
  - lib
@@ -65,9 +48,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
65
48
  - !ruby/object:Gem::Version
66
49
  version: '0'
67
50
  requirements: []
68
- rubygems_version: 3.0.3
69
- signing_key:
51
+ rubygems_version: 3.3.11
52
+ signing_key:
70
53
  specification_version: 4
71
- summary: TextMate project builder and TextMate 2 properties builder using git ignores
72
- for exclusions
54
+ summary: TextMate 2 properties builder using git ignores for exclusions
73
55
  test_files: []
data/bin/tm DELETED
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'mate/bin'
4
- require 'mate/tmproj'
5
-
6
- if !ARGV.empty? && ARGV.all?(&File.method(:exist?)) && ARGV.any?(&File.method(:directory?))
7
- Mate::Tmproj.new(ARGV).open
8
- else
9
- system Mate::Bin.v1, *ARGV
10
- end
@@ -1,100 +0,0 @@
1
- module Mate
2
- class Tmproj::Ignores
3
- BINARY_EXTENSIONS = [
4
- %w[jpe?g png gif psd], # images
5
- %w[zip tar t?(?:g|b)z], # archives
6
- %w[mp3 mov], # media
7
- %w[log tmp swf fla pdf], # other
8
- ]
9
- DOUBLE_ASTERISK_R = '(?:.+/)?'
10
-
11
- attr_reader :dir, :file_pattern, :folder_pattern
12
- def initialize(dir)
13
- @dir = dir
14
- @file_pattern = ["#{DOUBLE_ASTERISK_R}.+\\.(?:#{BINARY_EXTENSIONS.flatten.join('|')})"]
15
- @folder_pattern = ["#{DOUBLE_ASTERISK_R}.git"]
16
-
17
- process(dir, Pathname(`git config --get core.excludesfile`.strip).expand_path)
18
- process(dir, Pathname('~/.tmignore').expand_path)
19
-
20
- dir.find do |path|
21
- Find.prune if ignore?(path)
22
- if path.directory?
23
- %w[.gitignore .tmignore .git/info/exclude].each do |ignore_file_name|
24
- if (ignore_file = path + ignore_file_name).file?
25
- process(path, ignore_file)
26
- end
27
- end
28
- end
29
- end
30
- end
31
-
32
- def ignore?(path)
33
- case
34
- when path.file?
35
- path.to_s =~ /#{file_r}/
36
- when path.directory?
37
- path.to_s =~ /#{folder_r}/
38
- end
39
- end
40
-
41
- def file_r
42
- "^#{Regexp.escape(dir.to_s)}/(?:#{file_pattern.join('|')})$"
43
- end
44
- def folder_r
45
- "^#{Regexp.escape(dir.to_s)}/(?:#{folder_pattern.join('|')})$"
46
- end
47
-
48
- private
49
-
50
- def process(parent, ignore_file)
51
- return unless ignore_file.exist?
52
- current_file_pattern = []
53
- current_folder_pattern = []
54
- ignore_file.readlines.map do |line|
55
- line.lstrip[/(.*?)(\r?\n)?$/, 1] # this strange stuff strips line, but allows mac Icon\r files to be ignored
56
- end.reject do |line|
57
- line.empty? || %w[# !].include?(line[0, 1])
58
- end.each do |line|
59
- pattern = glob2regexp(line)
60
- unless pattern.sub!(/^\//, '')
61
- pattern = "#{DOUBLE_ASTERISK_R}#{pattern}"
62
- end
63
- unless pattern.sub!(/\/$/, '')
64
- current_file_pattern << pattern
65
- end
66
- current_folder_pattern << pattern
67
- end
68
- current_file_pattern = current_file_pattern.join('|')
69
- current_folder_pattern = current_folder_pattern.join('|')
70
- unless parent == dir
71
- parent_pattern = Regexp.escape(parent.relative_path_from(dir).to_s)
72
- current_file_pattern = "#{parent_pattern}/(?:#{current_file_pattern})"
73
- current_folder_pattern = "#{parent_pattern}/(?:#{current_folder_pattern})"
74
- end
75
- file_pattern << current_file_pattern
76
- folder_pattern << current_folder_pattern
77
- end
78
-
79
- def glob2regexp(glob)
80
- glob.gsub(/\[([^\]]*)\]|\{([^\}]*)\}|(\*+)|(\?+)|./) do |m|
81
- case
82
- when $1
83
- "[#{Regexp.escape($1)}]"
84
- when $2
85
- "(?:#{Regexp.escape($2).split(',').join('|')})"
86
- when $3 == '*'
87
- '[^/]*'
88
- when $3
89
- '.*'
90
- when $4 == '?'
91
- '[^/]'
92
- when $4
93
- "[^/]{#{$4.length}}"
94
- else
95
- Regexp.escape(m)
96
- end
97
- end
98
- end
99
- end
100
- end
data/lib/mate/tmproj.rb DELETED
@@ -1,66 +0,0 @@
1
- require 'pathname'
2
- require 'digest/sha2'
3
- require 'plist'
4
-
5
- module Mate
6
- class Tmproj
7
- TMPROJ_DIR = Pathname('~').expand_path + '.tmprojs'
8
-
9
- attr_reader :dirs, :file
10
- def initialize(dirs)
11
- @dirs = dirs.map{ |dir| Pathname(dir).expand_path }
12
- @file = TMPROJ_DIR + [
13
- Digest::SHA256.hexdigest(@dirs.join('-').downcase),
14
- "#{common_dir(@dirs).basename}.tmproj"
15
- ].join('/')
16
- end
17
-
18
- def open
19
- data = Plist::parse_xml(file) rescue {}
20
-
21
- data['documents'] = dirs.map do |dir|
22
- ignores = Ignores.new(dir)
23
- {
24
- :expanded => true,
25
- :name => dir.basename.to_s,
26
- :regexFileFilter => "!#{ignores.file_r}",
27
- :regexFolderFilter => "!#{ignores.folder_r}",
28
- :sourceDirectory => dir.to_s
29
- }
30
- end
31
- data['fileHierarchyDrawerWidth'] ||= 269
32
- data['metaData'] ||= {}
33
- data['showFileHierarchyDrawer'] = true unless data.has_key?('showFileHierarchyDrawer')
34
- dimensions = IO.popen(%q{osascript -e 'tell application "Finder" to get bounds of window of desktop'}, &:read).scan(/\d+/).map(&:to_i)
35
- data['windowFrame'] ||= "{{#{dimensions[0] + 100}, #{dimensions[1] + 50}}, {#{dimensions[2] - 200}, #{dimensions[3] - 100}}}"
36
-
37
- file.dirname.mkpath
38
- file.open('w'){ |f| f.write(data.to_plist) }
39
-
40
- system 'open', file.to_s
41
- end
42
-
43
- private
44
-
45
- def common_dir(paths)
46
- common = nil
47
- paths.each do |path|
48
- if path.file?
49
- path = path.dirname
50
- end
51
- ascendants = []
52
- path.ascend do |ascendant|
53
- ascendants << ascendant
54
- end
55
- unless common
56
- common = ascendants
57
- else
58
- common &= ascendants
59
- end
60
- end
61
- common && common.first
62
- end
63
- end
64
- end
65
-
66
- require 'mate/tmproj/ignores'