File: spec.rb

package info (click to toggle)
mikutter 5.0.4%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 9,700 kB
  • sloc: ruby: 21,307; sh: 181; makefile: 19
file content (148 lines) | stat: -rw-r--r-- 4,876 bytes parent folder | download | duplicates (2)
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# -*- coding: utf-8 -*-
# specファイル自動生成

require "boot/delayer"
require "userconfig"

require "fileutils"
require 'ripper'

# イカサマ依存関係自動解決クラス。
# あまり頼りにしないでくれ、Rubyのパース面倒なんだよ
class Depend < Ripper::Filter
  attr_reader :spec
  def initialize(*args)
    @last_const = ""
    super end

  def set_spec(spec)
    @spec = spec
    self end

  # シンボル開始の:。次のidentをシンボルと見る
  def on_symbeg(tok, f)
    :symbol end

  def on_ident(tok, f)
    if f == :symbol
      on_ex_symbol(tok)
    else
      on_ex_ident(tok) end end

  # 定数。Gtk::TimeLine みたいなのが出てきた場合、on_const Gtk, on_op ::, on_const NestedQuote
  # の順番でイベントが発生するみたい…。
  def on_const(tok, f)
    if f == :op
      @last_const += '::' + tok
    else
      @last_const = tok end
    case @last_const
    when /\AG[td]k\Z/             # GtkクラスとかGdkクラス使ってたらgtkプラグインに依存してるだろう
      depend :gtk3
    when /\APlugin::(\w+)/       # Plugin::なんとか は、プラグインスラッグのキャメルケース名なので、使ってたら依存してる
      depend $1.gsub(/([a-z])([A-Z])/, '\1_\2').downcase.to_sym end end

  def on_op(tok, f)
    case tok
    when "::"
      :op end end

  # シンボル
  def on_ex_symbol(tok)
  end

  # 変数とかメソッド的なやつ。
  # command DSLを検出してもcommandプラグインには依存させない。
  # commandプラグインは基本的なmikutterコマンドを定義するだけで、mikutterコマンドの仕組み自体には関係ないから。
  # commandプラグインで使われている条件クラスを使っていたら、on_constで依存してると判断される。
  def on_ex_ident(tok)
    case tok
    when 'defactivity'
      depend :activity
    when 'tab', 'timeline', 'nativewidget' # UIっぽい単語があったらguiに依存してそう
      depend :gui
    when 'profiletab'         # profiletabはプロフィールにも依存する
      depend :gui
      depend :profile
    when 'settings'            # 設定DSLの開始。settingsプラグイン。
      depend :settings
    end end

  # slug に依存していることを登録する
  # ==== Args
  # [slug] 依存しているプラグイン (Symbol)
  def depend(slug)
    if spec['slug'].to_sym != slug and not spec["depends"]["plugin"].include?(slug.to_s)
      spec["depends"]["plugin"] << slug.to_s end end
end

def spec_generate(dir)
  dir = File.expand_path(dir)
  specfile = File.join(dir, ".mikutter.yml")
  legacy_specfile = File.join(dir, "spec")
  spec = if FileTest.exist?(specfile)
           YAML.load_file(specfile)
         elsif FileTest.exist?(legacy_specfile)
           YAML.load_file(legacy_specfile)
         else
           user = UserConfig[:verify_credentials] || {}
           idname = user[:idname]
           {"slug" => File.basename(dir).to_sym, "depends" => {"mikutter" => Environment::VERSION.to_s}, "version" => "1.0", "author" => idname} end
  slug = spec["slug"].to_sym
  basefile = File.join(dir, "#{slug}.rb")
  unless FileTest.exist? basefile
    puts "file #{basefile} notfound. select plugin slug."
    expects = Dir.glob(File.join(dir, "*.rb")).map{ |filename| File.basename(filename, '.rb') }
    if expects.empty?
      puts "please create #{basefile}."
    end
    expects.each_with_index{ |filename, index|
      puts "[#{index}] #{filename}"
    }
    print "input number or slug [q:quit, s:skip]> "
    number = STDIN.gets(chomp: true)
    case number
    when /q/i
      abort
    when /s/i
      return
    when /\A[0-9]+\Z/
      slug = expects[number.to_i].to_sym
    else
      slug = number.to_sym end
    spec["slug"] = slug
    basefile = File.join(dir, "#{slug}.rb") end
  source = File.open(basefile){ |io| io.read }

  if not spec.has_key?("name")
    print "#{slug}: name> "
    spec["name"] = STDIN.gets(chomp: true)
  end
  if not spec.has_key?("description")
    print "#{slug}: description> "
    spec["description"] = STDIN.gets(chomp: true)
  end
  spec["depends"] = {"version" => "1.0", "plugin" => []} if not spec.has_key?("depends")
  spec["depends"]["plugin"] = [] if not spec["depends"].has_key?("plugin")
  depend = Depend.new(source).set_spec(spec)
  depend.parse
  content = YAML.dump(depend.spec)
  File.open(specfile, "w"){ |io| io.write content }
  puts content
end

target = ARGV[1]
if target == "all"
  unless ARGV[2]
    puts "directory is not specified."
    puts "usage: mikutter.rb spec all directory"
    exit end
  Dir.glob(File.join(ARGV[2], "*/")).each{ |dir|
    spec_generate(dir) }
else
  unless ARGV[1]
    puts "directory is not specified."
    puts "usage: mikutter.rb spec directory"
    exit end
  spec_generate(target)
end