aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/lib/retriever.rb1
-rw-r--r--core/lib/retriever/model.rb4
-rw-r--r--core/mui/cairo_cell_renderer_message.rb8
-rw-r--r--core/plugin/intent/intent.rb53
-rw-r--r--core/plugin/intent/model/intent_token.rb33
-rw-r--r--core/plugin/openimg/window.rb2
-rw-r--r--core/system/message.rb4
-rw-r--r--core/user.rb2
8 files changed, 82 insertions, 25 deletions
diff --git a/core/lib/retriever.rb b/core/lib/retriever.rb
index 20da1288..9c557065 100644
--- a/core/lib/retriever.rb
+++ b/core/lib/retriever.rb
@@ -4,6 +4,7 @@ module Retriever
# _model_slug_ をslugとして持つModelクラスを返す。
# 見つからない場合、nilを返す。
def self.Model(model_slug)
+ model_slug = model_slug.to_sym
ObjectSpace.each_object(Retriever::Model.singleton_class) do |klass|
return klass if klass.slug == model_slug
end
diff --git a/core/lib/retriever/model.rb b/core/lib/retriever/model.rb
index 7fbf1d09..0519307a 100644
--- a/core/lib/retriever/model.rb
+++ b/core/lib/retriever/model.rb
@@ -85,7 +85,7 @@ class Retriever::Model
end
define_method("#{field_name}=") do |value|
- @value[field_name] = value
+ @value[field_name] = Retriever::Model.cast(value, type, required)
self.class.store_datum(self)
value
end
@@ -372,7 +372,7 @@ class Retriever::Model
self.class.keys.each{ |column|
key, type, required = *column
begin
- Retriever::Model.cast(self.fetch(key), type, required)
+ @value[key.to_sym] = Retriever::Model.cast(self.fetch(key), type, required)
rescue Retriever::InvalidTypeError=>e
estr = e.to_s + "\nin #{self.fetch(key).inspect} of #{key}"
warn estr
diff --git a/core/mui/cairo_cell_renderer_message.rb b/core/mui/cairo_cell_renderer_message.rb
index 4ecfb9d4..e93bf2a7 100644
--- a/core/mui/cairo_cell_renderer_message.rb
+++ b/core/mui/cairo_cell_renderer_message.rb
@@ -128,10 +128,10 @@ module Gtk
return render_message(record.message)
else
self.pixbuf = GdkPixbuf::Pixbuf.new(file: Skin.get('notfound.png')) end
- rescue Exception => e
- error e
- if Mopt.debug
- raise e end
+ rescue Exception => err
+ error "#{err.class} by uri: #{uri} model: #{record ? record.message.inspect : nil}"
+ raise if Mopt.debug
+ error err
self.pixbuf = GdkPixbuf::Pixbuf.new(file: Skin.get('notfound.png')) end
private
diff --git a/core/plugin/intent/intent.rb b/core/plugin/intent/intent.rb
index 12cc69fc..4d3d9bf6 100644
--- a/core/plugin/intent/intent.rb
+++ b/core/plugin/intent/intent.rb
@@ -20,6 +20,11 @@ Plugin.create(:intent) do
defevent :intent_select,
prototype: [Enumerable, tcor(URI, String, Retriever::Model)]
+ # IntentTokenの次にあたるintentを発生させる。
+ defevent :intent_forward,
+ priority: :ui_response,
+ prototype: [Plugin::Intent::IntentToken]
+
# _model_ を開く方法を新しく登録する。
# ==== Args
# [model] サポートするModelのClass
@@ -63,30 +68,43 @@ Plugin.create(:intent) do
end
end
+ on_intent_forward do |intent_token|
+ case intent_token[:source]
+ when Retriever::Model
+ open_model(intent_token[:source], token: intent_token)
+ else
+ open_uri(intent_token.uri, token: intent_token)
+ end
+ end
+
# _uri_ をUI上で開く。
# このメソッドが呼ばれたらIntentTokenを生成して、開くことを試みる。
# open_modelのほうが高速なので、modelオブジェクトが存在するならばopen_modelを呼ぶこと。
# ==== Args
# [uri] 対象となるURI
- def open_uri(uri)
+ # [token:] 親となるIntentToken
+ def open_uri(uri, token: nil)
model_slugs = Plugin.filtering(:model_of_uri, uri.freeze, Set.new).last
if model_slugs.empty?
error "model not found to open for #{uri}"
return
end
- intents = model_slugs.inject(Set.new) do |memo, model_slug|
- memo.merge(Plugin.filtering(:intent_select_by_model_slug, model_slug, Set.new).last)
+ intents = model_slugs.lazy.flat_map{|model_slug|
+ Plugin.filtering(:intent_select_by_model_slug, model_slug, []).last
+ }
+ if token
+ intents = intents.reject{|intent| token.intent_ancestors.include?(intent) }
end
- if intents.empty?
+ head = intents.first(2)
+ case head.size
+ when 0
error "intent not found to open for #{model_slugs.to_a}"
return
- end
- if intents.size == 1
- intent = intents.to_a.first
+ when 1
Plugin::Intent::IntentToken.open(
uri: uri,
- intent: intent,
- parent: nil)
+ intent: head.first,
+ parent: token)
else
Plugin.call(:intent_select, intents, uri)
end
@@ -98,16 +116,23 @@ Plugin.create(:intent) do
# このメソッドはヒントとして _model_ を与えるため、探索が発生せず高速に処理できる。
# ==== Args
# [model] 対象となるRetriever::Model
- def open_model(model)
+ def open_model(model, token: nil)
intents = Plugin.filtering(:intent_select_by_model_slug, model.class.slug, Set.new).last
- # TODO: intents をユーザに選択させる
- if intents.size == 1
- intent = intents.to_a.first
+ if token
+ intents = intents.reject{|intent| token.intent_ancestors.include?(intent) }
+ end
+ head = intents.first(2)
+ case head.size
+ when 0
+ type_strict model.uri => URI
+ open_uri(model.uri, token: token)
+ when 1
+ intent = head.first
Plugin::Intent::IntentToken.open(
uri: model.uri,
model: model,
intent: intent,
- parent: nil)
+ parent: token)
else
Plugin.call(:intent_select, intents, model)
end
diff --git a/core/plugin/intent/model/intent_token.rb b/core/plugin/intent/model/intent_token.rb
index 2279c0ce..f22b0fa8 100644
--- a/core/plugin/intent/model/intent_token.rb
+++ b/core/plugin/intent/model/intent_token.rb
@@ -2,15 +2,21 @@
module Plugin::Intent
class IntentToken < Retriever::Model
- field.string :uri, required: true
+ field.uri :uri, required: true
field.has :model, Retriever::Model
field.has :intent, Plugin::Intent::Intent, required: true
+ field.has :parent, Plugin::Intent::IntentToken
# 引数の情報からIntentTokenを作成し、それを開く
def self.open(*args)
self.new(*args).open
end
+ def initialize(*rest)
+ super
+ self[:source] = self[:model]
+ end
+
# 設定された情報を使ってURI又はModelを開く
def open
if model?
@@ -25,5 +31,30 @@ module Plugin::Intent
end
self
end
+
+ def forward
+ Plugin.call(:intent_forward, self)
+ end
+
+ # _self_ から親のIntentTokenを再帰的に遡って、そのIntentTokenを引数に繰り返すEnumeratorを返す。
+ # ==== Return
+ # [Enumerator] IntentTokenを列挙する
+ def ancestors
+ Enumerator.new do |yielder|
+ cur = self
+ loop do
+ break unless cur
+ yielder << cur
+ cur = cur.parent
+ end
+ end
+ end
+
+ # ancestorsと同じようなもの。ただし、IntentToken#intentに関して繰り返す。
+ # ==== Return
+ # [Enumerator] Intentを列挙する
+ def intent_ancestors
+ ancestors.lazy.map(&:intent)
+ end
end
end
diff --git a/core/plugin/openimg/window.rb b/core/plugin/openimg/window.rb
index ee57f07a..1d5517d3 100644
--- a/core/plugin/openimg/window.rb
+++ b/core/plugin/openimg/window.rb
@@ -142,7 +142,7 @@ module Plugin::Openimg
def gen_browser_clicked
proc do
- Plugin.call(:open, @next_opener)
+ @next_opener.forward
false
end
end
diff --git a/core/system/message.rb b/core/system/message.rb
index 10cbe864..3f0389a1 100644
--- a/core/system/message.rb
+++ b/core/system/message.rb
@@ -11,8 +11,8 @@ class Mikutter::System::Message < Retriever::Model
field.string :description, required: true
field.has :user, Mikutter::System::User, required: true
- field.string :created
- field.string :modified
+ field.time :created
+ field.time :modified
entity_class Retriever::Entity::URLEntity
diff --git a/core/user.rb b/core/user.rb
index 7d247c82..6c4e7976 100644
--- a/core/user.rb
+++ b/core/user.rb
@@ -20,7 +20,7 @@ class User < Retriever::Model
# detail | detail
# profile_image_url | icon
- field.string :id
+ field.int :id
field.string :idname
field.string :name
field.string :location