Commits

Herbert Breunung committed 3b8e0ed

got IOUnit right $_ref is still no clean oop construction but dunno what to do with it now

Comments (0)

Files changed (5)

lib/Kephra/App/Editor.pm

 	Wx::Event::EVT_KEY_DOWN ($self, sub {
 		my ($ed, $event) = @_;
 		my $key = Kephra::App::Util::keycode_from_event($event);
-		Kephra::App::Panel::IOUnit::output('log',"pressed key $key\n");
+		Kephra::App::Panel::IOUnit::output('log',"pressed key $key");
 		if    ($key ==  &Wx::WXK_UP + 2000)  {$self->ParaUp() }
 		elsif ($key ==  &Wx::WXK_UP + 3000)  {$self->ParaUpExtend() }
 		elsif ($key ==  &Wx::WXK_DOWN + 2000){$self->ParaDown() }
 		elsif ($key ==  &Wx::WXK_F2)           {Kephra::App::Panel::FileBrowser::focus() } 
 		elsif ($key ==  &Wx::WXK_F11)          {Kephra::API::widget('win')->toggle_fullscreen() } 
 		elsif ($key ==  &Wx::WXK_ESCAPE)       { } 
-		elsif ($key ==  &Wx::WXK_TAB     +2000){Kephra::App::Panel::IOUnit::focus() }
+		elsif ($key ==  &Wx::WXK_TAB     +2000){Kephra::App::Panel::IOUnit::focus() } # shift lock
 		elsif ($key ==  ord('Q') + 2000)       {Kephra::File::close_active() }
 		elsif ($key ==  ord('Q') + 4000)       {Kephra::API::app()->close_save }
 		else {$event->Skip}

lib/Kephra/App/Panel/FileBrowser.pm

 			( $event->ShiftDown
 			+ $event->ControlDown * 2 
 			+ $event->AltDown     * 4);
-		if ($key ==  &Wx::WXK_ESCAPE) {Kephra::API::active_editor()->focus() }
-		if ($key ==  &Wx::WXK_F2)     {Kephra::API::active_editor()->focus() }
+		if    ($key ==  &Wx::WXK_ESCAPE) {Kephra::API::active_editor()->focus() }
+		elsif ($key ==  &Wx::WXK_F2)     {Kephra::API::active_editor()->focus() }
+		elsif ($key ==  &Wx::WXK_F11)    {Kephra::API::widget('win')->toggle_fullscreen() } 
 		else { $event->Skip }
 	});
 

lib/Kephra/App/Panel/IOUnit.pm

 
 package Kephra::App::Panel::IOUnit;
 our @ISA = 'Wx::Panel';
-
-# input line, panel of output pages, refs to ladder
-my ($input, $output, %outputtext);
-my @slot_name = qw/drum perl shell output log all/;
-my $active_slot = 'drum';
-my $process;
+my $_ref;
 
 sub new {
 	my( $class, $parent) = @_;
-	my $self = $class->SUPER::new($parent, -1);
+	my $self = $_ref = $class->SUPER::new($parent, -1);
+	$self->{'input'} = my $input = Wx::TextCtrl->new
+		($self, -1, '', [-1,-1], [-1, -1], &Wx::wxTE_PROCESS_ENTER );
+	$self->{'output_book'} = my $output_book = Wx::AuiNotebook->new (
+		$self, -1, [-1,-1], [-1, -1],
+		&Wx::wxAUI_NB_TOP | &Wx::wxAUI_NB_TAB_MOVE
+	);
+	$self->{'output_slots'} = {};
+	$self->{'master_slot_name'} = 'all';
+	$self->{'active_slot_name'} = 'drum';
+	$self->{'process'} = '';
 
-	$input = Wx::TextCtrl->new($self, -1, '', [-1,-1], [-1, -1], &Wx::wxTE_PROCESS_ENTER );
-	$output = Wx::AuiNotebook->new(
-		$self, -1, [-1,-1], [-1, -1],
-	&Wx::wxAUI_NB_TOP | &Wx::wxAUI_NB_TAB_MOVE
-	);
-	for my $slot (@slot_name) {
-		$outputtext{ $slot } = Wx::RichTextCtrl->new(
-			$output, -1, '', [-1,-1], [-1,-1],
-			&Wx::wxTE_MULTILINE | &Wx::wxTE_READONLY
-		);
-		$output->AddPage ( $outputtext{ $slot }, $slot, 0 );
-		Wx::Event::EVT_SET_FOCUS($outputtext{ $slot }, \&focus);
-	}
-	$output->SetSelection( $output->GetPageIndex( $outputtext{$active_slot} ) );
+	$self->create_slot($_)
+		for ($self->{'master_slot_name'}, qw/drum perl shell output log/);
+	my $active_slot = $self->{'output_slots'}{ $self->{'active_slot_name'} };
+	$output_book->SetSelection( $output_book->GetPageIndex( $active_slot ) );
 
-	Wx::Event::EVT_AUINOTEBOOK_BEGIN_DRAG  ( $output, -1, sub { });
-	Wx::Event::EVT_AUINOTEBOOK_END_DRAG    ( $output, -1, sub { });
-	Wx::Event::EVT_AUINOTEBOOK_PAGE_CHANGED( $output, -1, sub {
+	Wx::Event::EVT_AUINOTEBOOK_BEGIN_DRAG  ( $output_book, -1, sub { });
+	Wx::Event::EVT_AUINOTEBOOK_END_DRAG    ( $output_book, -1, sub { });
+	Wx::Event::EVT_AUINOTEBOOK_PAGE_CHANGED( $output_book, -1, sub {
 		my ($nb, $event ) = @_;
-		$active_slot = $nb->GetPageText( $event->GetSelection );
+		$self->{'active_slot_name'} = $nb->GetPageText( $event->GetSelection );
 	});
 	Wx::Event::EVT_TEXT_ENTER($input, -1, sub {
 		my ($txt, $event ) = @_;
 		my $cmd = $txt->GetValue;
 		$input->Clear;
-		return unless $active_slot eq 'drum' or $active_slot eq 'perl' or $active_slot eq 'shell';
-		&say('log',"$active_slot command $cmd");
-		my $outxt = $outputtext{$active_slot};
+		return unless $self->{'active_slot_name'} eq 'drum'
+				   or $self->{'active_slot_name'} eq 'perl'
+				   or $self->{'active_slot_name'} eq 'shell';
+		output_line('log',"$active_slot command $cmd");
+		my $outxt = $self->{'output_slots'}{$active_slot};
 		if    ($active_slot eq 'drum')  { 
 		}
-		elsif ($active_slot eq 'perl')  { &say ('perl',  "\"$cmd\" => \"".eval($cmd) . '"' ) }
+		elsif ($active_slot eq 'perl')  { output_line ('perl',  "\"$cmd\" => \"".eval($cmd) . '"' ) }
 		elsif ($active_slot eq 'shell') { 
-			$process = Wx::Perl::ProcessStream->OpenProcess
-				(qq~bash "$cmd"~ , __PACKAGE__, $outputtext{'output'});
+			$self->{'process'} = Wx::Perl::ProcessStream->OpenProcess
+				(qq~bash "$cmd"~ , __PACKAGE__, $self->{'output_slots'}{'output'});
 		}
 	});
-	Wx::Perl::ProcessStream::EVT_WXP_PROCESS_STREAM_STDOUT( $outputtext{'output'}, sub {
-		my ($txt, $event) = @_;
-		$event->Skip(1);
-		&say( $event->GetLine );
+	Wx::Perl::ProcessStream::EVT_WXP_PROCESS_STREAM_STDOUT(
+		$self->{'output_slots'}{'output'}, sub {
+			my ($txt, $event) = @_;
+			$event->Skip(1);
+			output_line('shell', $event->GetLine );
 	} );
 
 	Wx::Event::EVT_KEY_DOWN ($input, sub {
-		my ($ed, $event) = @_;
+		my ($input, $event) = @_;
 		my $key = Kephra::App::Util::keycode_from_event($event);
-		my $txt = $outputtext{$active_slot};
+		my $slot = $self->{'output_slots'}{ $self->{'active_slot_name'} };
 
-		if    ($key ==  0)  { }
+		if    ($key ==  0)                     {  }
 		elsif ($key ==  &Wx::WXK_UP     + 2000){
 		#$txt->MoveUp(1,0);
 		#print $txt->HitTest([12,5]),"\n";
 		#$txt->SetCaretPosition(  ); 
 		#$txt->ScrollIntoView( $txt->HitTest([12,5])-1, &Wx::WXK_UP);
-			$txt->PageUp( 1, &Wx::WXK_UP);
-			$txt->ShowPosition( $txt->GetCaretPosition )
+			$slot->PageUp( 1, &Wx::WXK_UP);
+			$slot->ShowPosition( $slot->GetCaretPosition )
 		}
-		elsif ($key ==  &Wx::WXK_UP     + 3000){$txt->ShowPosition(0)}
-		elsif ($key ==  &Wx::WXK_DOWN   + 2000){$txt->PageDown(1,0) }
-		elsif ($key ==  &Wx::WXK_DOWN   + 3000){$txt->ShowPosition($txt->GetLastPosition-1) }
-		elsif ($key ==  &Wx::WXK_PAGEUP + 2000){$output->AdvanceSelection(0)}
+		elsif ($key ==  &Wx::WXK_UP     + 3000){$slot->ShowPosition(0)}
+		elsif ($key ==  &Wx::WXK_DOWN   + 2000){$slot->PageDown(1,0) }
+		elsif ($key ==  &Wx::WXK_DOWN   + 3000){$slot->ShowPosition($slot->GetLastPosition-1) }
+		elsif ($key ==  &Wx::WXK_PAGEUP + 2000){$output_book->AdvanceSelection(0)}
 		#elsif ($key ==  &Wx::WXK_PAGEUP + 3000){Kephra::App::Panel::Editor::select_tab_leftmost()  }
 		#elsif ($key ==  &Wx::WXK_PAGEUP + 4000){Kephra::App::Panel::Editor::move_tab_left()  }
 		#elsif ($key ==  &Wx::WXK_PAGEUP + 5000){Kephra::App::Panel::Editor::move_tab_leftmost()  }
-		elsif ($key ==  &Wx::WXK_PAGEDOWN+2000){$output->AdvanceSelection(1)}
+		elsif ($key ==  &Wx::WXK_PAGEDOWN+2000){$output_book->AdvanceSelection(1)}
 		#elsif ($key ==  &Wx::WXK_PAGEDOWN+3000){Kephra::App::Panel::Editor::select_tab_rightmost()}
 		#elsif ($key ==  &Wx::WXK_PAGEDOWN+4000){Kephra::App::Panel::Editor::move_tab_right()}
 		#elsif ($key ==  &Wx::WXK_PAGEDOWN+5000){Kephra::App::Panel::Editor::move_tab_rightmost()}
 		elsif ($key ==  &Wx::WXK_F2)           {Kephra::App::Panel::FileBrowser::focus() } 
 		elsif ($key ==  &Wx::WXK_F11)          {Kephra::API::widget('win')->toggle_fullscreen() } 
 		elsif ($key ==  &Wx::WXK_ESCAPE)       {Kephra::API::active_editor()->focus() } 
-		elsif ($key ==  &Wx::WXK_TAB    + 2000){Kephra::API::active_editor()->focus() }
+		elsif ($key ==  &Wx::WXK_TAB    + 2000){Kephra::API::active_editor()->focus() } # SHIFT LOCK
 		elsif ($key ==  ord('Q')        + 2000){Kephra::File::close_active() }
 		elsif ($key ==  ord('Q')        + 4000){Kephra::API::app()->close_save }
 		else {$event->Skip}
 	});
 
 	my $sizer = Wx::BoxSizer->new( &Wx::wxVERTICAL );
-	$sizer->Add( $output, 1, &Wx::wxGROW);
+	$sizer->Add( $output_book, 1, &Wx::wxGROW);
 	$sizer->Add( $input,  0, &Wx::wxGROW);
 	$self->SetSizer( $sizer );
 
 	return $self;
 }
 
-sub output_and_activate {
-	my ($slot, $msg) = @_;
-	return unless defined $outputtext{$slot};
-	$output->SetSelection( $output->GetPageIndex( $outputtext{$slot} ) );
+sub create_slot {
+	my ($self, $slot_name) = @_;
+	die __PACKAGE__ . "::create_slot: wanted to creat already existing output slot"
+		if exists $self->{'output_slots'}{ $slot_name };
+	my $slot = $self->{'output_slots'}{ $slot_name } = Wx::RichTextCtrl->new(
+		$self->{'output_book'}, -1, '', [-1,-1], [-1,-1],
+		&Wx::wxTE_MULTILINE | &Wx::wxTE_READONLY
+	);
+	# put new pages on second last pos, because all is on last
+	my $pos = $self->{'output_book'}->GetPageCount;
+	$pos-- if $pos;
+	$self->{'output_book'}->InsertPage ( $pos, $slot, $slot_name, 0 );
+	Wx::Event::EVT_SET_FOCUS($slot, \&focus);
+}
+
+sub output {
+	my ($slot_name, $msg) = @_;
+	my $self = $_ref;
+	return unless defined $self->{'output_slots'}{ $slot_name };
+	my $slot = $self->{'output_slots'}{ $slot_name };
+	my $stamped_msg = timestamp() . ' ' . $msg;
+	if ($slot_name eq 'log') {
+		$slot->AppendText("\n") if $slot->GetValue;
+		$slot->AppendText($stamped_msg);
+	}
+	else                     {$slot->AppendText($msg)}
+	$slot->ShowPosition( $slot->GetCaretPosition );
+	unless ($slot_name eq $self->{'master_slot_name'}) {
+		my $masterslot =  $self->{'output_slots'}{ $self->{'master_slot_name'} };
+		$masterslot->AppendText("\n") if $masterslot->GetValue;
+		$masterslot->AppendText("<$slot_name> $stamped_msg");
+		$masterslot->ShowPosition( $masterslot->GetCaretPosition);
+	}
+}
+sub output_string { output(@_) }
+sub output_line {
+	my ($slot_name, $msg) = @_;
+	my $self = $_ref;
+	return unless defined $self->{'output_slots'}{ $slot_name };
+	my $slot = $self->{'output_slots'}{ $slot_name };
+	my ($x, $y) = $slot->GetLastPosition;
+	$slot->AppendText("\n") , print "$slot\n"
+		if ($slot_name ne 'log' and $slot_name ne $self->{'master_slot_name'})
+		and $slot->GetValue     and $x > 0;
 	output(@_);
 }
-sub output {
-	my ($slot, $msg) = @_;
-	return unless defined $outputtext{$slot};
-	$outputtext{$slot}->AppendText($msg);
-	$outputtext{$slot}->ShowPosition( $outputtext{$slot}->GetCaretPosition);
-	unless ($slot eq 'all') {
-		$outputtext{'all'}->AppendText("<$slot> $msg");
-		$outputtext{'all'}->ShowPosition( $outputtext{'all'}->GetCaretPosition);
-	}
-}
-sub say { 
-	$_[1] = "\n".$_[1] if $_[0]->GetValue;
+sub output_on_clear_and_activate {
+	my ($slot_name, $msg) = @_;
+	my $self = $_ref;
+	return unless defined $self->{'output_slots'}{ $slot_name };
+	my $slot = $self->{'output_slots'}{ $slot_name };
+	$self->{'output_book'}->SetSelection( $self->{'output_book'}->GetPageIndex($slot) );
+	$slot->Clear;
 	output(@_);
 }
 
-sub focus { Wx::Window::SetFocus( $input ) }
+
+sub timestamp { sprintf("[%02u:%02u:%02u]", (localtime)[2,1,0]) }
+sub focus { Wx::Window::SetFocus( $_ref->{'input'} ) }
 
 1;

lib/Kephra/App/Window.pm

 my $title_end = "$Kephra::NAME $Kephra::VERSION";
 
 sub new {
-    my( $class, $title ) = @_;
-    my( $self ) = $_ref = $class->SUPER::new ( undef, -1, $title, [-1,-1],[1000, 800] );
-    $self->SetIcon( Wx::GetWxPerlIcon() );
+	my( $class, $title ) = @_;
+	my( $self ) = $_ref = $class->SUPER::new ( undef, -1, $title, [-1,-1],[1000, 800] );
+	$self->SetIcon( Wx::GetWxPerlIcon() );
 
-    # container var for all panel, sizer and splitter
-    my (%panel, %sizer, %splitter);
-    $splitter{'left'}  = Wx::SplitterWindow->new( $self,             -1 );
-    $splitter{'right'} = Wx::SplitterWindow->new( $splitter{'left'}, -1 );
-    $splitter{'below'} = Wx::SplitterWindow->new( $splitter{'right'},-1 );
-    $panel   {'above'} = Wx::Panel         ->new( $splitter{'below'});
-    $splitter{'edit'}  = Wx::SplitterWindow->new( $panel   {'above'},-1 );
+	# container var for all panel, sizer and splitter
+	my (%panel, %sizer, %splitter);
+	$splitter{'left'}  = Wx::SplitterWindow->new( $self,             -1 );
+	$splitter{'right'} = Wx::SplitterWindow->new( $splitter{'left'}, -1 );
+	$splitter{'below'} = Wx::SplitterWindow->new( $splitter{'right'},-1 );
+	$panel   {'above'} = Wx::Panel         ->new( $splitter{'below'});
+	$splitter{'edit'}  = Wx::SplitterWindow->new( $panel   {'above'},-1 );
 
-    for my $name (qw /left right above below edit/) {
-        $panel{ $name } = Wx::Panel->new( $splitter{ $name } ) unless $name eq 'above';
-        $sizer{ $name } = Wx::BoxSizer->new( &Wx::wxHORIZONTAL );
-        $sizer{ $name } = Wx::BoxSizer->new( &Wx::wxVERTICAL ) if $name eq 'above'
-                                                               or $name eq 'below';
-        $panel{ $name }->SetSizer( $sizer{ $name } );
-    }
-    my $editor      = Kephra::App::Panel::Editor     ->new( $panel{'edit'} );
-    my $searchbar   = Kephra::App::Bar::Search       ->new( $panel{'above'} );
-    my $iounit      = Kephra::App::Panel::IOUnit     ->new( $panel{'below'} );
-    my $filebrowser = Kephra::App::Panel::FileBrowser->new( $panel{'left'} );
-    #my $projectman  = Kephra::App::Panel::ProjectManarger->new( $panel{'left'} );
-    my $treelib     = Kephra::App::Panel::TreeLib    ->new( $panel{'right'} );
-    #my $orgpad      = Kephra::App::Panel::OrgPad     ->new( $panel{'right'} );
-    #my $scratchsheet= Kephra::App::Panel::ScratchSheet->new( $panel{'right'} );
-    my $statusbar   = Kephra::App::Bar::Status       ->new( $self );
+	for my $name (qw /left right above below edit/) {
+		$panel{ $name } = Wx::Panel->new( $splitter{ $name } ) unless $name eq 'above';
+		$sizer{ $name } = Wx::BoxSizer->new( &Wx::wxHORIZONTAL );
+		$sizer{ $name } = Wx::BoxSizer->new( &Wx::wxVERTICAL ) if $name eq 'above'
+															   or $name eq 'below';
+		$panel{ $name }->SetSizer( $sizer{ $name } );
+	}
+	my $editor      = Kephra::App::Panel::Editor     ->new( $panel{'edit'} );
+	my $searchbar   = Kephra::App::Bar::Search       ->new( $panel{'above'} );
+	my $iounit      = Kephra::App::Panel::IOUnit     ->new( $panel{'below'} );
+	my $filebrowser = Kephra::App::Panel::FileBrowser->new( $panel{'left'} );
+	#my $projectman  = Kephra::App::Panel::ProjectManarger->new( $panel{'left'} );
+	my $treelib     = Kephra::App::Panel::TreeLib    ->new( $panel{'right'} );
+	#my $orgpad      = Kephra::App::Panel::OrgPad     ->new( $panel{'right'} );
+	#my $scratchsheet= Kephra::App::Panel::ScratchSheet->new( $panel{'right'} );
+	my $statusbar   = Kephra::App::Bar::Status       ->new( $self );
 
-    $splitter{'left'}->SplitVertically( $panel{'left'}, $splitter{'right'}, 200);
-    $splitter{'left'}->SetSashGravity(0);
-    $splitter{'left'}->SetSashPosition(200);
-    $splitter{'left'}->SetMinimumPaneSize(140);
-    $splitter{'right'}->SplitVertically( $splitter{'below'}, $panel{'right'}, -200);
-    $splitter{'right'}->SetSashGravity(1);
-    $splitter{'right'}->SetSashPosition(-200);
-    $splitter{'right'}->SetMinimumPaneSize(140);
-    $splitter{'below'}->SplitHorizontally( $panel{'above'}, $panel{'below'}, -200);
-    $splitter{'below'}->SetSashGravity(1);
-    $splitter{'below'}->SetSashPosition(-200);
-    $splitter{'below'}->SetMinimumPaneSize(100);
-    $splitter{'edit'}->Initialize( $panel{'edit'} );
+	$splitter{'left'}->SplitVertically( $panel{'left'}, $splitter{'right'}, 200);
+	$splitter{'left'}->SetSashGravity(0);
+	$splitter{'left'}->SetSashPosition(200);
+	$splitter{'left'}->SetMinimumPaneSize(140);
+	$splitter{'right'}->SplitVertically( $splitter{'below'}, $panel{'right'}, -200);
+	$splitter{'right'}->SetSashGravity(1);
+	$splitter{'right'}->SetSashPosition(-200);
+	$splitter{'right'}->SetMinimumPaneSize(140);
+	$splitter{'below'}->SplitHorizontally( $panel{'above'}, $panel{'below'}, -200);
+	$splitter{'below'}->SetSashGravity(1);
+	$splitter{'below'}->SetSashPosition(-200);
+	$splitter{'below'}->SetMinimumPaneSize(100);
+	$splitter{'edit'}->Initialize( $panel{'edit'} );
 
-    $sizer{'edit'} ->Add( $editor,          1, &Wx::wxGROW );
-    $sizer{'above'}->Add( $splitter{'edit'},1, &Wx::wxGROW );
-    $sizer{'above'}->Add( $searchbar,       0, &Wx::wxGROW );
-    $sizer{'below'}->Add( $iounit,          1, &Wx::wxGROW );
-    $sizer{'right'}->Add( $treelib,         1, &Wx::wxGROW );
-    $sizer{'left'} ->Add( $filebrowser,     1, &Wx::wxGROW );
+	$sizer{'edit'} ->Add( $editor,          1, &Wx::wxGROW );
+	$sizer{'above'}->Add( $splitter{'edit'},1, &Wx::wxGROW );
+	$sizer{'above'}->Add( $searchbar,       0, &Wx::wxGROW );
+	$sizer{'below'}->Add( $iounit,          1, &Wx::wxGROW );
+	$sizer{'right'}->Add( $treelib,         1, &Wx::wxGROW );
+	$sizer{'left'} ->Add( $filebrowser,     1, &Wx::wxGROW );
 
-    $sizer{'main'} = Wx::BoxSizer->new( &Wx::wxVERTICAL );
-    $sizer{'main'}->Add( $splitter{'left'}, 1, &Wx::wxGROW);
-    $sizer{'main'}->Add( $statusbar,        0, &Wx::wxGROW);
-    $self->SetSizer( $sizer{'main'} );
+	$sizer{'main'} = Wx::BoxSizer->new( &Wx::wxVERTICAL );
+	$sizer{'main'}->Add( $splitter{'left'}, 1, &Wx::wxGROW);
+	$sizer{'main'}->Add( $statusbar,        0, &Wx::wxGROW);
+	$self->SetSizer( $sizer{'main'} );
 
-    $self->SetMenuBar( Kephra::App::Bar::Menu::get() );
-    $self->GetMenuBar->SetAcceleratorTable( Wx::AcceleratorTable->new() );
-    
-    
-    #Wx::Event::EVT_SPLITTER_DCLICK( ,sub {});  #&Wx::wxSP_NOBORDER  );
-    Wx::Event::EVT_CLOSE( $self, sub{ Kephra::App::close_save() });
+	$self->SetMenuBar( Kephra::App::Bar::Menu::get() );
+	$self->GetMenuBar->SetAcceleratorTable( Wx::AcceleratorTable->new() );
 
-    return $self;
+	#Wx::Event::EVT_SPLITTER_DCLICK( ,sub {});  #&Wx::wxSP_NOBORDER  );
+	Wx::Event::EVT_CLOSE( $self, sub{ Kephra::App::close_save() });
+
+	return $self;
 }
 
 sub close   { $_ref->Close() }

lib/Kephra/File.pm

 		next unless $file and -e $file;
 
 		# raise tab if doc is alread open
-		next Kephra::App::Panel::Editor::raise_document($file)
+		Kephra::App::Panel::Editor::raise_document($file), next
 		  if Kephra::DocumentStash::file_loaded($file);
 
 		my $doc = Kephra::App::Panel::Editor::create_document($file);