我经常遇到这种情况:
GitBook 有 “server” 命令,例如 gitbook serve
Jekyll 有 “server” 命令,例如 jekyll serve
Rails 有 “server” 命令,例如 rails server

以上命令都不尽相同,每次打 “server” 命令之前都得想一会儿到底该使用哪个命令,好烦
假如有一个 server 命令,可以自动选择合适的命令去执行就好了

心动不如行动,下面是我用 Ruby 写的解决方案
若不喜欢用 Ruby, 可用 Python, shell script 等改写一下即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env ruby

dir_commands = {
  "/Users/mwum/Gitbook/Ruby"            => "gitbook serve --port 4006",
  "/Users/mwum/dx"                      => "jekyll serve -w",
  "/Users/mwum/Code/Rails/chat-system"  => "bundle exec rails server"
}

dir_commands.each do |dir, command|
  if Dir.pwd == dir
    exec command
  end
end

puts "Command not found: #{File.basename __FILE__}"
puts "In this directory: #{Dir.pwd}"

将以上文件命名为 server, 并放到 bin 目录下,在给它加上可执行权限 chmod +x ./server, 即可愉快使用了

有一点需要注意的:
使用 exec 比较合适,不要使用 system
如果使用 system, Ruby 进程并不会退出而是会等待 system 返回,
而 server 命令不是立即返回的,所以用 system 不合适,Ruby 进程会一直等待。
但是 exec 是完全替换进程的,所以不存在这个问题

以上程序还是不够智能,如果我想使某个目录下的所有子目录都执行相同的命令,
岂不是要一个个子目录去设置,这显然是不合适的
所以继续给上面的程序加入正则匹配功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/env ruby

dir_commands = {
  /\/Users\/mwum\/Gitbook\/*/       => "gitbook serve --port 4006",
  "/Users/mwum/dx"                  => "jekyll serve -w",
  /\/Users\/mwum\/Code\/Rails\/*/   => "bundle exec rails server"
}

dir_commands.each do |dir, command|
  if dir.class == Regexp
    if Dir.pwd =~ dir
      exec command
    end
  elsif dir.class == String
    if Dir.pwd == dir
      exec command
    end
  else
    puts "This class is not supported: #{dir.class}"
    exit
  end
end

puts "Command not found: #{File.basename __FILE__}"
puts "In this directory: #{Dir.pwd}"