File: miquire_plugin.rb

package info (click to toggle)
mikutter 3.0.7%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 9,396 kB
  • ctags: 1,916
  • sloc: ruby: 16,619; sh: 117; makefile: 27
file content (156 lines) | stat: -rw-r--r-- 5,334 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
149
150
151
152
153
154
155
156
# -*- coding: utf-8 -*-
miquire :core, "miquire", "plugin"

# プラグインのロードに関すること
module Miquire::Plugin
  class << self
    include Enumerable

    # ロードパスの配列を返す。
    # ロードパスに追加したい場合は、以下のようにすればいい
    #
    #  Miquire::Plugin.loadpath << 'pathA' << 'pathB'
    def loadpath
      @loadpath ||= [] end

    # プラグインのファイル名(フルパス)で繰り返す。
    def each
      iterated = Set.new
      detected = []
      loadpath.reverse.each { |path|
        Dir[File.join(File.expand_path(path), '*')].each { |file|
          if FileTest.directory?(file) and FileTest.exist?(File.join(file, File.basename(file))+'.rb')
            file = File.join(file, File.basename(file))+'.rb'
          elsif not file.end_with?('.rb'.freeze)
            next end
          plugin_name = File.basename(file, '.rb')
          if not iterated.include? plugin_name
            iterated << plugin_name
            detected << file end } }
      detected.sort_by{ |a|
        [:bundle == get_kind(a) ? 0 : 1, a]
      }.each(&Proc.new) end

    def each_spec
      each{ |path|
        spec = get_spec path
        yield spec if spec } end

    def to_hash
      result = {}
      each_spec{ |spec|
        result[spec[:slug]] = spec }
      result end

    # 受け取ったパスにあるプラグインのスラッグを返す
    # ==== Args
    # [path] パス(String)
    # ==== Return
    # プラグインスラッグ(Symbol)
    def get_slug(path)
      type_strict path => String
      spec = get_spec(path)
      if spec
        spec[:slug]
      else
        File.basename(path, ".rb").to_sym end end

    # specファイルがあればそれを返す
    # ==== Args
    # [path] パス(String)
    # ==== Return
    # specファイルの内容か、存在しなければnil
    def get_spec(path)
      type_strict path => String
      plugin_dir = FileTest.directory?(path) ? path : File.dirname(path)
      spec_filename = File.join(plugin_dir, ".mikutter.yml")
      deprecated_spec = false
      unless FileTest.exist? spec_filename
        spec_filename = File.join(plugin_dir, "spec")
        deprecated_spec = true end
      if FileTest.exist? spec_filename
        YAML.load_file(spec_filename).symbolize
          .merge(kind: get_kind(path),
                 path: plugin_dir,
                 deprecated_spec: deprecated_spec)
      elsif FileTest.exist? path
        { slug: File.basename(path, ".rb").to_sym,
          kind: get_kind(path),
          path: plugin_dir,
          deprecated_spec: false } end end

    def get_spec_by_slug(slug)
      type_strict slug => Symbol
      to_hash[slug] end

    # プラグインがthirdpartyかbundleかを返す
    def get_kind(path)
      type_strict path => String
      if path.start_with?(Environment::PLUGIN_PATH)
        :bundle
      else
        :thirdparty end end

    def load_all
      each_spec{ |spec|
        begin
          load spec
        rescue Miquire::LoadError => e
          ::Plugin.call(:modify_activity,
                        kind: "system",
                        title: "#{spec[:slug]} load failed",
                        date: Time.new,
                        exception: e,
                        description: e.to_s) end } end

    def load(spec)
      type_strict spec => tcor(Hash, Symbol, String)
      case spec
      when Symbol, String
        spec = spec.to_sym
        if ::Plugin.instance_exist?(spec)
          return true end
        spec = get_spec_by_slug(spec)
        if not spec
          return false end
      else
        if ::Plugin.instance_exist?(spec[:slug])
          return true end end

      if defined?(spec[:depends][:mikutter]) and spec[:depends][:mikutter]
        version = Environment::Version.new(*(spec[:depends][:mikutter].split(".").map(&:to_i) + ([0]*4))[0...4])
        if Environment::VERSION < version
          raise Miquire::LoadError, "plugin #{spec[:slug]}: #{Environment::NAME} version too old (#{spec[:depends][:mikutter]} required, but #{Environment::NAME} version is #{Environment::VERSION})"
          return false end end

      if defined? spec[:depends][:plugin]
        spec[:depends][:plugin].map(&:to_sym).each{ |depended_plugin_slug|
          begin
            ::Plugin.instance_exist?(depended_plugin_slug) or
              load(depended_plugin_slug) or
              raise Miquire::LoadError
          rescue Miquire::LoadError
            raise Miquire::LoadError, "plugin #{spec[:slug]}: dependency error: plugin #{depended_plugin_slug} was not loaded." end } end

      notice "plugin loaded: " + File.join(spec[:path], "#{spec[:slug]}.rb")
      ::Plugin.create(spec[:slug].to_sym) do
        self.spec = spec end
      Kernel.load File.join(spec[:path], "#{spec[:slug]}.rb")
      if spec[:deprecated_spec]
        title = "#{spec[:slug]}: specファイルは非推奨になりました。"
        Plugin.call(:modify_activity,
                    { plugin: spec[:slug],
                      kind: "error",
                      title: title,
                      date: Time.now,
                      spec: spec,
                      description: "#{title}\n代わりに.mikutter.ymlを使ってください。"}) end
      true end
  end
end