summaryrefslogtreecommitdiffstats
path: root/scripts/import_vim
blob: 0cf9231c89375b2229e3561d3a6b6a9eb757096d (plain) (blame)
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#!/usr/bin/env ruby

require 'yaml'

def comma_expanson(s)
  s.scan(/{[^{]+}|[^{]+/).map { |a| a[0] == "{" ? a : a.split(",", -1) }.reduce([]) do |a, b|
    a.size > 0 ?
      (b.is_a?(String) ?
         a[0..-2] + [a[-1] + b] :
         a[0..-2] + [a[-1] + b[0]] + b[1..-1]) :
      [b].flatten
  end
end

def import_autocommands
  cmd = <<~EOF
vim -es -u DEFAULTS -c 'exe("func! Capture() \\n redir => capture \\n silent autocmd filetypedetect BufRead \\n redir END \\n return capture \\n endfunc") | let a = Capture() | put =a | %print | :q!'
  EOF
  filetypes = Hash.new { |h, k| h[k] = [] }
  autocommands = `#{cmd}`
  for pattern, cmd in autocommands.scan(/^    ([^ ]+)\s*(.*)\n/)
    cmd = cmd.strip

    what = {}
    if match = cmd.match(/^setf\s+(.*)$/)
      what[:ft] = match[1]
    elsif match = cmd.match(/^call s:StarSetf\(\'(.*)\'\)$/)
      what[:ft] = match[1]
    elsif match = cmd.match(/^set filetype=(.*)$/)
      what[:ft] = match[1]
    end

    if what != {}
      for p in comma_expanson(pattern.strip)
        filetypes[what[:ft].strip] << p
      end
    end
  end


  filetypes
end

$with_special_char = /#{[".", ":", "{", "}", "[", "]", ",", "&", "*", "#", "?", "|", "-", "<", ">", "=", "!", "%", "@", "\\"].map { |e| Regexp.escape(e) }.join("|")}/
def print_pattern(p)
  if p.match($with_special_char)
    p.gsub("'", "\\'")
  end

  return p
end

def generate_packages_entries(filetypes, comments)
  entries = []

  current_filetypes = YAML.load_stream(File.read('packages.yaml')).flat_map do |p|
    p["filetypes"].map { |a| a["name"] }
  end

  for ft, patterns in filetypes
    if current_filetypes.include?(ft)
      next
    end

    output = {
      "name" => ft,
      "remote" => "vim/vim:runtime",
      "glob" => "**/" + ft + ".vim",
      "filetypes" => [{
        "name" => ft,
        "patterns" => []
      }]
    }
    paths_with_comments = patterns.group_by { |p| (comments[ft] || {})[p] || "" }
    for comment, paths in paths_with_comments
      output["filetypes"][0]["patterns"] << {
        "pattern" => paths.join(","),
      }

      if comment.strip.size > 0
        output["filetypes"][0]["patterns"].last["description"] = comment
      end
    end
    entries << YAML.dump(output)
  end

  return entries
end

filetypes = import_autocommands

def fix_quotes(a)
  a = a.gsub(/\\/) { '\\\\' }
  a.scan(/^.*?"(.+?)"\n/m).each { |p| a[p[0]] = p[0].gsub('"') { '\\"'} }
  a
end

def get_comments
  comments_cmd = <<~'EOF'
  awk '/^"/ { comment = $0; next } match($0, "(\\S+)\\s+setf (\\S*)$", a) { print "- filetype: \"" a[2] "\"\n  description: \"" substr(comment, 3) "\"\n  patterns: \"" a[1] "\"" }' 'tmp/vim/vim/runtime/filetype.vim'
  EOF

  comments = YAML.load(fix_quotes(`#{comments_cmd}`))

  comments.reject! { |c| c["patterns"].strip == "" || c["patterns"].include?('\\') }
  result = {}
  comments = comments.flat_map do |c| 
    result[c["filetype"]] ||= {}

    for p in comma_expanson(c["patterns"])
      result[c["filetype"]][p] = c["description"]
    end
  end
  result
end

comments = get_comments()
autocommands = import_autocommands()
entries = generate_packages_entries(autocommands, comments)
print(entries.join(""))