Class: DotfileLinker::Linker

Inherits:
Object
  • Object
show all
Defined in:
lib/dotfile_linker.rb

Constant Summary collapse

BLACKLIST =
%w{ .git }

Instance Method Summary collapse

Constructor Details

#initializeLinker



18
19
20
# File 'lib/dotfile_linker.rb', line 18

def initialize
  @options = {}
end

Instance Method Details

#dotfiles_dirObject



36
37
38
# File 'lib/dotfile_linker.rb', line 36

def dotfiles_dir
  @options[:path] || Dir.pwd
end

#each_dotfile(dirname) ⇒ Object



32
33
34
# File 'lib/dotfile_linker.rb', line 32

def each_dotfile(dirname)
  Dir.foreach(dirname) { |filename| yield filename if filename =~ /^\./ }
end

#exclude_file?(filename) ⇒ Boolean



94
95
96
# File 'lib/dotfile_linker.rb', line 94

def exclude_file?(filename)
  filename =~ /^\.\.?$/ or BLACKLIST.include?(filename) or ignore_list.include?(filename)
end

#home_dirObject



40
41
42
# File 'lib/dotfile_linker.rb', line 40

def home_dir
  ENV['HOME']
end

#ignore_file(filename) ⇒ Object



88
89
90
91
92
# File 'lib/dotfile_linker.rb', line 88

def ignore_file(filename)
  File.open(ignore_file_name, 'a') do |f|
    f.puts filename
  end
end

#ignore_file_nameObject



44
45
46
# File 'lib/dotfile_linker.rb', line 44

def ignore_file_name
  File.expand_path("~/.dotfile_linker_ignore")
end

#ignore_listObject



79
80
81
82
83
84
85
86
# File 'lib/dotfile_linker.rb', line 79

def ignore_list
  @ignore_list ||=
    begin
      File.open(ignore_file_name, 'rb').lines.to_a.map(&:chomp)
    rescue Errno::ENOENT
      []
    end
end


98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/dotfile_linker.rb', line 98

def link_file(filename)
  home_dir_file_path = File.expand_path("~/#{ filename }")
  dotfiles_dir_file_path = File.expand_path("#{ dotfiles_dir }/#{ filename }")
  unless File.symlink?(home_dir_file_path) || exclude_file?(filename)
    case user_response_or_exit("move and link #{ home_dir_file_path.human_filename.magenta } -> #{ dotfiles_dir_file_path.human_filename.cyan }?", " (y/n/i[gnore]/q)")
    when :yes
      FileUtils.mv(home_dir_file_path, dotfiles_dir_file_path, :verbose => true)
      FileUtils.ln_s(dotfiles_dir_file_path, home_dir_file_path, :verbose => true)
    when :ignore
      ignore_file(filename)
      puts "added #{filename.cyan} to ignore file"
    end
  end
end


113
114
115
# File 'lib/dotfile_linker.rb', line 113

def link_files
  each_dotfile(home_dir) { |filename| link_file(filename) }
end

#parse_optionsObject



22
23
24
25
26
27
28
29
30
# File 'lib/dotfile_linker.rb', line 22

def parse_options
  optparse = OptionParser.new do |opts|
    opts.on('-p', '--path PATH', 'Use [PATH] as dotfiles directory (instead of current directory)') { |path| @options[:path] = File.expand_path(path) }
    opts.on_tail('-u', '--unlink', 'Unlink mode') { @options[:unlink_mode] = true }
    opts.on_tail('-v', '--version', 'Show version') { puts DotfileLinker::VERSION; exit }
    opts.on_tail('-h', '--help', 'Show this message') { puts opts; exit }
  end
  optparse.parse!
end

#raise_if_home_and_dotfiles_dir_matchObject



48
49
50
51
52
# File 'lib/dotfile_linker.rb', line 48

def raise_if_home_and_dotfiles_dir_match
  if File.expand_path(home_dir) == File.expand_path(dotfiles_dir)
    raise InvalidDotfilesDir, "#{ dotfiles_dir } is not a valid dotfiles directory. Please specify your dotfiles directory by running `link_dotfiles` from that path, or providing a --path flag".red
  end
end

#startObject



133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/dotfile_linker.rb', line 133

def start
  parse_options
  raise_if_home_and_dotfiles_dir_match
  if @options[:unlink_mode]
    unlink_files
  else
    link_files
  end
  puts 'Finished'
rescue Interrupt
  # do nothing
rescue InvalidDotfilesDir => e
  puts e.message
end


117
118
119
120
121
122
123
124
125
126
127
# File 'lib/dotfile_linker.rb', line 117

def unlink_file(filename)
  home_dir_symlink_path = File.expand_path("~/#{ filename }")
  dotfiles_dir_file_path = File.expand_path("#{ dotfiles_dir }/#{ filename }")
  if File.symlink?(home_dir_symlink_path)
    case user_response_or_exit("unlink #{ home_dir_symlink_path.human_filename.magenta } and restore #{ dotfiles_dir_file_path.human_filename.cyan }?", " (y/n/q)")
    when :yes
      FileUtils.rm(home_dir_symlink_path, :verbose => true)
      FileUtils.mv(dotfiles_dir_file_path, home_dir_symlink_path, :verbose => true)
    end
  end
end


129
130
131
# File 'lib/dotfile_linker.rb', line 129

def unlink_files
  each_dotfile(dotfiles_dir) { |filename| unlink_file(filename) }
end

#user_response(message, choices) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/dotfile_linker.rb', line 54

def user_response(message, choices)
  puts "#{message} #{choices}"
  case gets.strip
  when /^y/i
    :yes
  when /^n/i
    :no
  when /^i/i
    :ignore
  when /^q/i
    :quit
  else
    user_response("Please enter a valid response", choices)
  end
end

#user_response_or_exit(message, choices) ⇒ Object



70
71
72
73
74
75
76
77
# File 'lib/dotfile_linker.rb', line 70

def user_response_or_exit(message, choices)
  response = user_response(message, choices)
  if response == :quit
    puts "Exiting"
    exit
  end
  response
end