+sub local_context {
+ return unless @_ >= 2;
+ my $code = pop;
+ my $new_cxt = (@_ == 1) ? $_[0] : find_context(@_);
+ my $cur_cxt = get_context;
+ if (set_context $new_cxt) {
+ my $guard = bless \$cur_cxt, 'Xchat::XPI::Utils::ContextGuard';
+ return $code->();
+ } else {
+ return undef;
+ }
+}
+
+sub Xchat::XPI::Utils::ContextGuard::DESTROY {
+ set_context ${$_[0]};
+}
+
+sub called_from_script (&) {
+ my $code = shift;
+ my $level = 0;
+ my ($package, $filename);
+ while (1) {
+ my @frame = caller $level;
+ last unless @frame;
+ if ($frame[0] !~ /^(?:Xchat|HexChat)::XPI\b/) {
+ ($package, $filename) = @frame[0, 1];
+ last;
+ }
+ ++$level;
+ }
+ if (defined $filename) {
+ my $internal_package = Xchat::Embed::file2pkg($filename);
+ my $mock = sub { $internal_package, $package };
+ no warnings 'redefine';
+ local *Xchat::Embed::find_pkg = $mock;
+ local *HexChat::Embed::find_pkg = $mock;
+ $code->();
+ }
+}
+
+use base qw<Exporter>;
+