2006-08-15 22:18:16 -07:00
/*
2006-08-23 21:58:30 -07:00
* moocommand - exe - unix . c
2006-08-15 22:18:16 -07:00
*
2007-04-07 01:21:52 -07:00
* Copyright ( C ) 2004 - 2007 by Yevgen Muntyan < muntyan @ math . tamu . edu >
2006-08-15 22:18:16 -07:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* See COPYING file that comes with this distribution .
*/
2006-11-23 19:18:25 -08:00
# ifdef HAVE_CONFIG_H
2006-08-20 01:49:33 -07:00
# include "config.h"
2006-11-23 19:18:25 -08:00
# endif
2006-09-01 10:37:47 -07:00
# include "mooedit/moocommand-exe-private.h"
2006-08-20 01:49:33 -07:00
# include "mooedit/mooeditor.h"
# include "mooedit/mooedittools-glade.h"
# include "mooedit/moocmdview.h"
# include "mooutils/mooi18n.h"
# include "mooutils/mooglade.h"
2006-08-20 20:45:45 -07:00
# include "mooutils/mooutils-fs.h"
2006-09-02 00:34:01 -07:00
# include "mooutils/mooutils-misc.h"
2006-08-30 23:26:50 -07:00
# include "mooutils/moospawn.h"
2006-12-31 02:53:45 -08:00
# include "mooutils/mootype-macros.h"
2006-08-20 01:49:33 -07:00
# include <gtk/gtk.h>
# include <string.h>
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# endif
# define MOO_COMMAND_EXE_MAX_INPUT (MOO_COMMAND_EXE_INPUT_DOC + 1)
# define MOO_COMMAND_EXE_MAX_OUTPUT (MOO_COMMAND_EXE_OUTPUT_NEW_DOC + 1)
# define MOO_COMMAND_EXE_INPUT_DEFAULT MOO_COMMAND_EXE_INPUT_NONE
# define MOO_COMMAND_EXE_OUTPUT_DEFAULT MOO_COMMAND_EXE_OUTPUT_NONE
2006-09-02 00:34:01 -07:00
enum {
COLUMN_NAME ,
COLUMN_ID
} ;
2006-08-31 08:21:39 -07:00
enum {
KEY_INPUT ,
KEY_OUTPUT ,
2006-09-01 10:37:47 -07:00
KEY_FILTER ,
2006-08-31 08:21:39 -07:00
N_KEYS
} ;
static const char * data_keys [ ] = {
2006-09-01 10:37:47 -07:00
" input " , " output " , " filter " , NULL
2006-08-31 08:21:39 -07:00
} ;
2006-08-20 01:49:33 -07:00
struct _MooCommandExePrivate {
char * cmd_line ;
MooCommandExeInput input ;
MooCommandExeOutput output ;
2006-09-01 10:37:47 -07:00
char * filter ;
2006-08-20 01:49:33 -07:00
} ;
G_DEFINE_TYPE ( MooCommandExe , moo_command_exe , MOO_TYPE_COMMAND )
2007-02-27 20:23:57 -08:00
typedef MooCommandFactory MooCommandFactoryExe ;
typedef MooCommandFactoryClass MooCommandFactoryExeClass ;
MOO_DEFINE_TYPE_STATIC ( MooCommandFactoryExe , _moo_command_factory_exe , MOO_TYPE_COMMAND_FACTORY )
2006-08-20 01:49:33 -07:00
static void
moo_command_exe_init ( MooCommandExe * cmd )
{
cmd - > priv = G_TYPE_INSTANCE_GET_PRIVATE ( cmd ,
MOO_TYPE_COMMAND_EXE ,
MooCommandExePrivate ) ;
}
static void
moo_command_exe_finalize ( GObject * object )
{
MooCommandExe * cmd = MOO_COMMAND_EXE ( object ) ;
2006-09-01 10:37:47 -07:00
g_free ( cmd - > priv - > filter ) ;
2006-08-20 01:49:33 -07:00
g_free ( cmd - > priv - > cmd_line ) ;
G_OBJECT_CLASS ( moo_command_exe_parent_class ) - > finalize ( object ) ;
}
static char *
get_lines ( GtkTextView * doc )
{
GtkTextBuffer * buffer ;
GtkTextIter start , end ;
buffer = gtk_text_view_get_buffer ( doc ) ;
gtk_text_buffer_get_selection_bounds ( buffer , & start , & end ) ;
gtk_text_iter_set_line_offset ( & start , 0 ) ;
if ( ! gtk_text_iter_starts_line ( & end ) | | gtk_text_iter_equal ( & start , & end ) )
gtk_text_iter_forward_line ( & end ) ;
gtk_text_buffer_select_range ( buffer , & end , & start ) ;
return gtk_text_buffer_get_slice ( buffer , & start , & end , TRUE ) ;
}
static char *
get_input ( MooCommandExe * cmd ,
MooCommandContext * ctx )
{
GtkTextView * doc = moo_command_context_get_doc ( ctx ) ;
g_return_val_if_fail ( cmd - > priv - > input = = MOO_COMMAND_EXE_INPUT_NONE | | doc ! = NULL , NULL ) ;
switch ( cmd - > priv - > input )
{
case MOO_COMMAND_EXE_INPUT_NONE :
return NULL ;
case MOO_COMMAND_EXE_INPUT_LINES :
return get_lines ( doc ) ;
case MOO_COMMAND_EXE_INPUT_SELECTION :
return moo_text_view_get_selection ( doc ) ;
case MOO_COMMAND_EXE_INPUT_DOC :
return moo_text_view_get_text ( doc ) ;
}
g_return_val_if_reached ( NULL ) ;
}
static char *
save_temp ( const char * data ,
gssize length )
{
int fd ;
GError * error = NULL ;
char * filename ;
fd = g_file_open_tmp ( " medit-tmp-XXXXXX " , & filename , & error ) ;
if ( fd < 0 )
{
g_critical ( " %s: %s " , G_STRLOC , error - > message ) ;
g_error_free ( error ) ;
return NULL ;
}
close ( fd ) ;
2006-08-20 20:45:45 -07:00
/* XXX */
if ( ! _moo_save_file_utf8 ( filename , data , length , & error ) )
2006-08-20 01:49:33 -07:00
{
g_critical ( " %s: %s " , G_STRLOC , error - > message ) ;
g_error_free ( error ) ;
g_free ( filename ) ;
return NULL ;
}
return filename ;
}
static char *
make_cmd ( MooCommandExe * cmd ,
MooCommandContext * ctx )
{
char * input ;
char * cmd_line = NULL ;
gsize input_len ;
input = get_input ( cmd , ctx ) ;
input_len = input ? strlen ( input ) : 0 ;
if ( ! input )
return g_strdup ( cmd - > priv - > cmd_line ) ;
if ( input_len < 2048 )
{
char * quoted ;
quoted = g_shell_quote ( input ) ;
g_return_val_if_fail ( quoted ! = NULL , NULL ) ;
cmd_line = g_strdup_printf ( " echo -n %s | ( %s ) " , quoted , cmd - > priv - > cmd_line ) ;
g_free ( quoted ) ;
}
else
{
char * tmp_file = save_temp ( input , input_len ) ;
if ( tmp_file )
{
cmd_line = g_strdup_printf ( " ( %s ) < '%s' ; rm '%s' " ,
cmd - > priv - > cmd_line , tmp_file , tmp_file ) ;
g_free ( tmp_file ) ;
}
}
g_free ( input ) ;
return cmd_line ;
}
static void
run_in_pane ( MooCommandExe * cmd ,
MooCommandContext * ctx ,
2006-08-22 21:20:01 -07:00
const char * working_dir ,
2006-08-20 01:49:33 -07:00
char * * envp )
{
GtkTextView * doc ;
MooEditWindow * window ;
char * cmd_line ;
GtkWidget * output ;
doc = moo_command_context_get_doc ( ctx ) ;
window = moo_command_context_get_window ( ctx ) ;
g_return_if_fail ( cmd - > priv - > input = = MOO_COMMAND_EXE_INPUT_NONE | | doc ! = NULL ) ;
g_return_if_fail ( MOO_IS_EDIT_WINDOW ( window ) ) ;
output = moo_edit_window_get_output ( window ) ;
g_return_if_fail ( output ! = NULL ) ;
/* XXX */
if ( ! moo_cmd_view_running ( MOO_CMD_VIEW ( output ) ) )
{
2006-11-02 00:09:24 -08:00
MooOutputFilter * filter = NULL ;
2006-09-01 10:37:47 -07:00
2006-08-20 01:49:33 -07:00
cmd_line = make_cmd ( cmd , ctx ) ;
g_return_if_fail ( cmd_line ! = NULL ) ;
moo_line_view_clear ( MOO_LINE_VIEW ( output ) ) ;
moo_edit_window_present_output ( window ) ;
2006-09-02 02:01:26 -07:00
gtk_widget_grab_focus ( output ) ;
2006-09-01 10:37:47 -07:00
2006-11-02 00:09:24 -08:00
if ( cmd - > priv - > filter )
filter = moo_command_filter_create ( cmd - > priv - > filter ) ;
if ( filter )
{
const char * fn = MOO_IS_EDIT ( doc ) ? moo_edit_get_filename ( MOO_EDIT ( doc ) ) : NULL ;
moo_output_filter_set_active_file ( filter , fn ) ;
}
2006-09-01 10:37:47 -07:00
moo_cmd_view_set_filter ( MOO_CMD_VIEW ( output ) , filter ) ;
2006-08-20 01:49:33 -07:00
moo_cmd_view_run_command_full ( MOO_CMD_VIEW ( output ) ,
cmd_line , cmd - > priv - > cmd_line ,
2006-08-22 21:20:01 -07:00
working_dir , envp , " Command " ) ;
2006-08-20 01:49:33 -07:00
2006-09-01 10:37:47 -07:00
if ( filter )
g_object_unref ( filter ) ;
2006-11-02 00:09:24 -08:00
2006-08-20 01:49:33 -07:00
g_free ( cmd_line ) ;
}
}
static void
insert_text ( MooTextView * view ,
const char * text )
{
GtkTextBuffer * buffer ;
GtkTextIter start , end ;
buffer = gtk_text_view_get_buffer ( GTK_TEXT_VIEW ( view ) ) ;
gtk_text_buffer_begin_user_action ( buffer ) ;
if ( gtk_text_buffer_get_selection_bounds ( buffer , & start , & end ) )
gtk_text_buffer_delete ( buffer , & start , & end ) ;
gtk_text_buffer_insert ( buffer , & start , text , - 1 ) ;
gtk_text_buffer_end_user_action ( buffer ) ;
}
static void
set_variable ( const char * name ,
const GValue * gval ,
gpointer array )
{
2006-08-20 22:41:57 -07:00
char * freeme = NULL ;
const char * value = NULL ;
2006-08-20 01:49:33 -07:00
switch ( G_TYPE_FUNDAMENTAL ( G_VALUE_TYPE ( gval ) ) )
{
case G_TYPE_CHAR :
2006-08-20 22:41:57 -07:00
freeme = g_strdup_printf ( " %c " , g_value_get_char ( gval ) ) ;
2006-08-20 01:49:33 -07:00
break ;
case G_TYPE_UCHAR :
2006-08-20 22:41:57 -07:00
freeme = g_strdup_printf ( " %c " , g_value_get_uchar ( gval ) ) ;
2006-08-20 01:49:33 -07:00
break ;
case G_TYPE_INT :
2006-08-20 22:41:57 -07:00
freeme = g_strdup_printf ( " %d " , g_value_get_int ( gval ) ) ;
2006-08-20 01:49:33 -07:00
break ;
case G_TYPE_UINT :
2006-08-20 22:41:57 -07:00
freeme = g_strdup_printf ( " %u " , g_value_get_uint ( gval ) ) ;
2006-08-20 01:49:33 -07:00
break ;
case G_TYPE_LONG :
2006-08-20 22:41:57 -07:00
freeme = g_strdup_printf ( " %ld " , g_value_get_long ( gval ) ) ;
2006-08-20 01:49:33 -07:00
break ;
case G_TYPE_ULONG :
2006-08-20 22:41:57 -07:00
freeme = g_strdup_printf ( " %lu " , g_value_get_ulong ( gval ) ) ;
2006-08-20 01:49:33 -07:00
break ;
case G_TYPE_INT64 :
2006-08-20 22:41:57 -07:00
freeme = g_strdup_printf ( " % " G_GINT64_FORMAT , g_value_get_int64 ( gval ) ) ;
2006-08-20 01:49:33 -07:00
break ;
case G_TYPE_UINT64 :
2006-08-20 22:41:57 -07:00
freeme = g_strdup_printf ( " % " G_GUINT64_FORMAT , g_value_get_uint64 ( gval ) ) ;
2006-08-20 01:49:33 -07:00
break ;
case G_TYPE_STRING :
2006-08-20 22:41:57 -07:00
value = g_value_get_string ( gval ) ;
2006-08-20 01:49:33 -07:00
break ;
default :
g_message ( " ignoring value of type %s " , g_type_name ( G_VALUE_TYPE ( gval ) ) ) ;
}
2006-08-20 22:41:57 -07:00
if ( freeme )
value = freeme ;
2006-08-20 01:49:33 -07:00
if ( value )
2006-08-20 22:41:57 -07:00
g_ptr_array_add ( array , g_strdup_printf ( " %s=%s " , name , value ) ) ;
g_free ( freeme ) ;
2006-08-20 01:49:33 -07:00
}
2006-08-22 21:20:01 -07:00
static void
create_environment ( MooCommandContext * ctx ,
char * * working_dir ,
char * * * envp )
2006-08-20 01:49:33 -07:00
{
GPtrArray * array ;
2006-08-22 21:20:01 -07:00
MooEdit * doc ;
2006-08-20 01:49:33 -07:00
array = g_ptr_array_new ( ) ;
moo_command_context_foreach ( ctx , set_variable , array ) ;
2006-08-20 22:41:57 -07:00
if ( array - > len )
2006-08-20 01:49:33 -07:00
{
2006-08-20 22:41:57 -07:00
g_ptr_array_add ( array , NULL ) ;
2006-08-22 21:20:01 -07:00
* envp = ( char * * ) g_ptr_array_free ( array , FALSE ) ;
2006-08-20 01:49:33 -07:00
}
else
{
2006-08-20 22:41:57 -07:00
g_ptr_array_free ( array , TRUE ) ;
2006-08-22 21:20:01 -07:00
* envp = NULL ;
2006-08-20 01:49:33 -07:00
}
2006-08-22 21:20:01 -07:00
doc = moo_command_context_get_doc ( ctx ) ;
if ( doc & & moo_edit_get_filename ( doc ) )
* working_dir = g_path_get_dirname ( moo_edit_get_filename ( doc ) ) ;
else
* working_dir = NULL ;
2006-08-20 01:49:33 -07:00
}
static gboolean
run_command ( MooCommandExe * cmd ,
MooCommandContext * ctx ,
2006-08-22 21:20:01 -07:00
const char * working_dir ,
2006-08-20 01:49:33 -07:00
char * * envp ,
char * * output )
{
GError * error = NULL ;
gboolean result ;
const char * argv [ 4 ] = { " /bin/sh " , " -c " , NULL , NULL } ;
char * cmd_line ;
2006-08-30 23:26:50 -07:00
char * * real_env ;
2006-08-20 01:49:33 -07:00
cmd_line = make_cmd ( cmd , ctx ) ;
if ( ! cmd_line )
return FALSE ;
argv [ 2 ] = cmd_line ;
2006-08-30 23:26:50 -07:00
real_env = _moo_env_add ( envp ) ;
result = g_spawn_sync ( working_dir , ( char * * ) argv , real_env , 0 ,
2006-08-20 01:49:33 -07:00
NULL , NULL , output , NULL , NULL , & error ) ;
2006-08-30 23:26:50 -07:00
g_strfreev ( real_env ) ;
if ( ! result )
{
g_message ( " could not run command: %s " , error - > message ) ;
g_error_free ( error ) ;
}
g_free ( cmd_line ) ;
return result ;
}
static gboolean
run_command_async ( MooCommandExe * cmd ,
MooCommandContext * ctx ,
const char * working_dir ,
char * * envp )
{
GError * error = NULL ;
gboolean result ;
const char * argv [ 4 ] = { " /bin/sh " , " -c " , NULL , NULL } ;
char * cmd_line ;
char * * real_env ;
cmd_line = make_cmd ( cmd , ctx ) ;
if ( ! cmd_line )
return FALSE ;
argv [ 2 ] = cmd_line ;
real_env = _moo_env_add ( envp ) ;
2006-11-29 06:04:10 -08:00
_moo_message ( " Launching: \n %s \n " , cmd_line ) ;
2006-08-30 23:26:50 -07:00
result = g_spawn_async ( working_dir , ( char * * ) argv , real_env ,
0 , NULL , NULL , NULL , & error ) ;
g_strfreev ( real_env ) ;
2006-08-20 01:49:33 -07:00
if ( ! result )
{
g_message ( " could not run command: %s " , error - > message ) ;
g_error_free ( error ) ;
}
g_free ( cmd_line ) ;
return result ;
}
static void
moo_command_exe_run ( MooCommand * cmd_base ,
MooCommandContext * ctx )
{
MooEdit * doc ;
MooCommandExe * cmd = MOO_COMMAND_EXE ( cmd_base ) ;
char * * envp ;
char * output = NULL ;
2006-08-22 21:20:01 -07:00
char * working_dir ;
2006-08-20 01:49:33 -07:00
2006-08-22 21:20:01 -07:00
create_environment ( ctx , & working_dir , & envp ) ;
2006-08-20 01:49:33 -07:00
if ( cmd - > priv - > output = = MOO_COMMAND_EXE_OUTPUT_PANE )
{
2006-08-22 21:20:01 -07:00
run_in_pane ( cmd , ctx , working_dir , envp ) ;
2006-08-20 01:49:33 -07:00
goto out ;
}
if ( cmd - > priv - > output = = MOO_COMMAND_EXE_OUTPUT_NONE )
{
2006-08-22 21:20:01 -07:00
run_command ( cmd , ctx , working_dir , envp , NULL ) ;
2006-08-20 01:49:33 -07:00
goto out ;
}
2006-08-30 23:26:50 -07:00
if ( cmd - > priv - > output = = MOO_COMMAND_EXE_OUTPUT_NONE_ASYNC )
{
run_command_async ( cmd , ctx , working_dir , envp ) ;
goto out ;
}
2006-08-22 21:20:01 -07:00
if ( ! run_command ( cmd , ctx , working_dir , envp , & output ) )
2006-08-20 01:49:33 -07:00
goto out ;
if ( cmd - > priv - > output = = MOO_COMMAND_EXE_OUTPUT_INSERT )
{
doc = moo_command_context_get_doc ( ctx ) ;
g_return_if_fail ( MOO_IS_EDIT ( doc ) ) ;
}
else
{
MooEditWindow * window = moo_command_context_get_window ( ctx ) ;
doc = moo_editor_new_doc ( moo_editor_instance ( ) , window ) ;
g_return_if_fail ( MOO_IS_EDIT ( doc ) ) ;
}
insert_text ( MOO_TEXT_VIEW ( doc ) , output ) ;
out :
2006-08-22 21:20:01 -07:00
g_free ( working_dir ) ;
2006-08-20 01:49:33 -07:00
g_strfreev ( envp ) ;
g_free ( output ) ;
}
static gboolean
moo_command_exe_check_sensitive ( MooCommand * cmd_base ,
gpointer doc ,
gpointer window )
{
MooCommandExe * cmd = MOO_COMMAND_EXE ( cmd_base ) ;
MooCommandOptions options ;
options = cmd_base - > options ;
switch ( cmd - > priv - > input )
{
case MOO_COMMAND_EXE_INPUT_NONE :
break ;
case MOO_COMMAND_EXE_INPUT_LINES :
case MOO_COMMAND_EXE_INPUT_SELECTION :
case MOO_COMMAND_EXE_INPUT_DOC :
options | = MOO_COMMAND_NEED_DOC ;
break ;
}
switch ( cmd - > priv - > output )
{
case MOO_COMMAND_EXE_OUTPUT_NONE :
2006-08-30 23:26:50 -07:00
case MOO_COMMAND_EXE_OUTPUT_NONE_ASYNC :
2006-08-20 01:49:33 -07:00
case MOO_COMMAND_EXE_OUTPUT_NEW_DOC :
break ;
case MOO_COMMAND_EXE_OUTPUT_PANE :
options | = MOO_COMMAND_NEED_WINDOW ;
break ;
case MOO_COMMAND_EXE_OUTPUT_INSERT :
options | = MOO_COMMAND_NEED_DOC ;
break ;
}
moo_command_set_options ( cmd_base , options ) ;
return MOO_COMMAND_CLASS ( moo_command_exe_parent_class ) - > check_sensitive ( cmd_base , doc , window ) ;
}
static void
moo_command_exe_class_init ( MooCommandExeClass * klass )
{
2007-02-27 20:23:57 -08:00
MooCommandFactory * factory ;
2006-08-20 01:49:33 -07:00
G_OBJECT_CLASS ( klass ) - > finalize = moo_command_exe_finalize ;
MOO_COMMAND_CLASS ( klass ) - > run = moo_command_exe_run ;
MOO_COMMAND_CLASS ( klass ) - > check_sensitive = moo_command_exe_check_sensitive ;
g_type_class_add_private ( klass , sizeof ( MooCommandExePrivate ) ) ;
2007-02-27 20:23:57 -08:00
factory = g_object_new ( _moo_command_factory_exe_get_type ( ) , NULL ) ;
moo_command_factory_register ( " exe " , _ ( " Shell command " ) , factory , ( char * * ) data_keys ) ;
g_object_unref ( factory ) ;
2006-08-20 01:49:33 -07:00
}
static void
2007-02-27 20:23:57 -08:00
_moo_command_factory_exe_init ( G_GNUC_UNUSED MooCommandFactoryExe * factory )
2006-08-20 01:49:33 -07:00
{
}
2006-12-31 02:53:45 -08:00
static MooCommand *
_moo_command_exe_new ( const char * cmd_line ,
MooCommandOptions options ,
MooCommandExeInput input ,
MooCommandExeOutput output ,
const char * filter )
{
MooCommandExe * cmd ;
g_return_val_if_fail ( cmd_line & & cmd_line [ 0 ] , NULL ) ;
g_return_val_if_fail ( input < MOO_COMMAND_EXE_MAX_INPUT , NULL ) ;
g_return_val_if_fail ( output < MOO_COMMAND_EXE_MAX_OUTPUT , NULL ) ;
cmd = g_object_new ( MOO_TYPE_COMMAND_EXE , " options " , options , NULL ) ;
cmd - > priv - > cmd_line = g_strdup ( cmd_line ) ;
cmd - > priv - > input = input ;
cmd - > priv - > output = output ;
cmd - > priv - > filter = g_strdup ( filter ) ;
return MOO_COMMAND ( cmd ) ;
}
2006-08-20 01:49:33 -07:00
static gboolean
parse_input ( const char * string ,
int * input )
{
* input = MOO_COMMAND_EXE_INPUT_DEFAULT ;
if ( ! string | | ! string [ 0 ] )
return TRUE ;
if ( ! strcmp ( string , " none " ) )
* input = MOO_COMMAND_EXE_INPUT_NONE ;
else if ( ! strcmp ( string , " lines " ) )
* input = MOO_COMMAND_EXE_INPUT_LINES ;
else if ( ! strcmp ( string , " selection " ) )
* input = MOO_COMMAND_EXE_INPUT_SELECTION ;
else if ( ! strcmp ( string , " doc " ) )
* input = MOO_COMMAND_EXE_INPUT_DOC ;
else
{
g_warning ( " unknown input type %s " , string ) ;
return FALSE ;
}
return TRUE ;
}
static gboolean
parse_output ( const char * string ,
int * output )
{
* output = MOO_COMMAND_EXE_OUTPUT_DEFAULT ;
if ( ! string | | ! string [ 0 ] )
return TRUE ;
if ( ! strcmp ( string , " none " ) )
* output = MOO_COMMAND_EXE_OUTPUT_NONE ;
2006-08-30 23:26:50 -07:00
else if ( ! strcmp ( string , " async " ) )
* output = MOO_COMMAND_EXE_OUTPUT_NONE_ASYNC ;
2006-08-20 01:49:33 -07:00
else if ( ! strcmp ( string , " pane " ) )
* output = MOO_COMMAND_EXE_OUTPUT_PANE ;
else if ( ! strcmp ( string , " insert " ) )
* output = MOO_COMMAND_EXE_OUTPUT_INSERT ;
else if ( ! strcmp ( string , " new-doc " ) | |
! strcmp ( string , " new_doc " ) | |
! strcmp ( string , " new " ) )
* output = MOO_COMMAND_EXE_OUTPUT_NEW_DOC ;
else
{
g_warning ( " unknown output type %s " , string ) ;
return FALSE ;
}
return TRUE ;
}
static MooCommand *
2007-02-27 20:23:57 -08:00
exe_factory_create_command ( G_GNUC_UNUSED MooCommandFactory * factory ,
MooCommandData * data ,
const char * options )
2006-08-20 01:49:33 -07:00
{
MooCommand * cmd ;
const char * cmd_line ;
int input , output ;
2006-08-31 08:21:39 -07:00
cmd_line = moo_command_data_get_code ( data ) ;
2006-08-20 01:49:33 -07:00
g_return_val_if_fail ( cmd_line & & * cmd_line , NULL ) ;
2006-08-31 08:21:39 -07:00
if ( ! parse_input ( moo_command_data_get ( data , KEY_INPUT ) , & input ) )
2007-01-11 18:28:22 -08:00
return NULL ;
2006-08-31 08:21:39 -07:00
if ( ! parse_output ( moo_command_data_get ( data , KEY_OUTPUT ) , & output ) )
2007-01-11 18:28:22 -08:00
return NULL ;
2006-08-20 01:49:33 -07:00
2006-09-01 10:37:47 -07:00
cmd = _moo_command_exe_new ( cmd_line ,
moo_command_options_parse ( options ) ,
input , output ,
moo_command_data_get ( data , KEY_FILTER ) ) ;
2006-08-20 01:49:33 -07:00
g_return_val_if_fail ( cmd ! = NULL , NULL ) ;
return cmd ;
}
static void
init_combo ( GtkComboBox * combo ,
const char * * items ,
guint n_items )
{
GtkListStore * store ;
GtkCellRenderer * cell ;
guint i ;
cell = gtk_cell_renderer_text_new ( ) ;
gtk_cell_layout_pack_start ( GTK_CELL_LAYOUT ( combo ) , cell , TRUE ) ;
gtk_cell_layout_set_attributes ( GTK_CELL_LAYOUT ( combo ) , cell , " text " , 0 , NULL ) ;
store = gtk_list_store_new ( 1 , G_TYPE_STRING ) ;
gtk_combo_box_set_model ( combo , GTK_TREE_MODEL ( store ) ) ;
for ( i = 0 ; i < n_items ; + + i )
{
GtkTreeIter iter ;
gtk_list_store_append ( store , & iter ) ;
2007-03-26 21:27:56 -07:00
gtk_list_store_set ( store , & iter , 0 , Q_ ( items [ i ] ) , - 1 ) ;
2006-08-20 01:49:33 -07:00
}
g_object_unref ( store ) ;
}
2006-09-02 00:34:01 -07:00
static void
init_filter_combo ( GtkComboBox * combo )
{
GtkListStore * store ;
GtkCellRenderer * cell ;
GtkTreeIter iter ;
GSList * ids ;
cell = gtk_cell_renderer_text_new ( ) ;
gtk_cell_layout_pack_start ( GTK_CELL_LAYOUT ( combo ) , cell , TRUE ) ;
gtk_cell_layout_set_attributes ( GTK_CELL_LAYOUT ( combo ) , cell ,
" text " , COLUMN_NAME , NULL ) ;
store = gtk_list_store_new ( 2 , G_TYPE_STRING , G_TYPE_STRING ) ;
gtk_combo_box_set_model ( combo , GTK_TREE_MODEL ( store ) ) ;
gtk_list_store_append ( store , & iter ) ;
2007-02-27 20:23:57 -08:00
/* Translators: "None" means no filter for a shell command, do not translate the part before | */
gtk_list_store_set ( store , & iter , COLUMN_NAME , Q_ ( " Filter|None " ) , - 1 ) ;
2006-09-02 00:34:01 -07:00
ids = moo_command_filter_list ( ) ;
while ( ids )
{
const char * name ;
char * id = ids - > data ;
id = ids - > data ;
ids = g_slist_delete_link ( ids , ids ) ;
name = moo_command_filter_lookup ( id ) ;
if ( ! name )
{
g_critical ( " %s: oops " , G_STRLOC ) ;
continue ;
}
gtk_list_store_append ( store , & iter ) ;
gtk_list_store_set ( store , & iter ,
COLUMN_ID , id ,
COLUMN_NAME , _ ( name ) ,
- 1 ) ;
g_free ( id ) ;
}
g_object_unref ( store ) ;
}
static void
set_filter_combo ( GtkComboBox * combo ,
const char * id )
{
GtkTreeModel * model ;
GtkTreeIter iter ;
model = gtk_combo_box_get_model ( combo ) ;
if ( ! id )
{
gtk_combo_box_set_active ( combo , 0 ) ;
return ;
}
if ( gtk_tree_model_iter_nth_child ( model , & iter , NULL , 1 ) )
{
do {
char * id_here ;
gtk_tree_model_get ( model , & iter , COLUMN_ID , & id_here , - 1 ) ;
if ( ! strcmp ( id_here , id ) )
{
gtk_combo_box_set_active_iter ( combo , & iter ) ;
g_free ( id_here ) ;
return ;
}
g_free ( id_here ) ;
}
while ( gtk_tree_model_iter_next ( model , & iter ) ) ;
}
g_warning ( " unknown filter %s " , id ) ;
gtk_combo_box_set_active ( combo , - 1 ) ;
}
2006-08-20 01:49:33 -07:00
static GtkWidget *
2007-02-27 20:23:57 -08:00
exe_factory_create_widget ( G_GNUC_UNUSED MooCommandFactory * factory )
2006-08-20 01:49:33 -07:00
{
GtkWidget * page ;
MooGladeXML * xml ;
MooTextView * textview ;
2007-02-27 20:23:57 -08:00
/* Translators: these are kinds of input for a shell command, do not translate the part before | */
static const char * input_names [ 4 ] = { N_ ( " Input|None " ) , N_ ( " Input|Selected lines " ) , N_ ( " Input|Selection " ) , N_ ( " Input|Whole document " ) } ;
/* Translators: these are actions for output of a shell command, do not translate the part before | */
static const char * output_names [ 5 ] = { N_ ( " Output|None " ) , N_ ( " Output|None, asynchronous " ) , N_ ( " Output|Output pane " ) , N_ ( " Output|Insert into the document " ) , N_ ( " Output|New document " ) } ;
2006-08-20 01:49:33 -07:00
xml = moo_glade_xml_new_empty ( GETTEXT_PACKAGE ) ;
moo_glade_xml_map_id ( xml , " textview " , MOO_TYPE_TEXT_VIEW ) ;
moo_glade_xml_parse_memory ( xml , MOO_EDIT_TOOLS_GLADE_XML , - 1 , " exe_page " , NULL ) ;
page = moo_glade_xml_get_widget ( xml , " exe_page " ) ;
g_return_val_if_fail ( page ! = NULL , NULL ) ;
textview = moo_glade_xml_get_widget ( xml , " textview " ) ;
moo_text_view_set_font_from_string ( textview , " Monospace " ) ;
2006-08-31 08:21:39 -07:00
moo_text_view_set_lang_by_id ( textview , " sh " ) ;
2006-08-20 01:49:33 -07:00
init_combo ( moo_glade_xml_get_widget ( xml , " input " ) , input_names , G_N_ELEMENTS ( input_names ) ) ;
init_combo ( moo_glade_xml_get_widget ( xml , " output " ) , output_names , G_N_ELEMENTS ( output_names ) ) ;
2006-09-02 00:34:01 -07:00
init_filter_combo ( moo_glade_xml_get_widget ( xml , " filter " ) ) ;
2006-08-20 01:49:33 -07:00
g_object_set_data_full ( G_OBJECT ( page ) , " moo-glade-xml " , xml , g_object_unref ) ;
return page ;
}
static void
2007-02-27 20:23:57 -08:00
exe_factory_load_data ( G_GNUC_UNUSED MooCommandFactory * factory ,
GtkWidget * page ,
MooCommandData * data )
2006-08-20 01:49:33 -07:00
{
MooGladeXML * xml ;
GtkTextView * textview ;
GtkTextBuffer * buffer ;
const char * cmd_line ;
int index ;
g_return_if_fail ( data ! = NULL ) ;
xml = g_object_get_data ( G_OBJECT ( page ) , " moo-glade-xml " ) ;
g_return_if_fail ( xml ! = NULL ) ;
textview = moo_glade_xml_get_widget ( xml , " textview " ) ;
buffer = gtk_text_view_get_buffer ( textview ) ;
2006-08-31 08:21:39 -07:00
cmd_line = moo_command_data_get_code ( data ) ;
2006-08-20 01:49:33 -07:00
gtk_text_buffer_set_text ( buffer , cmd_line ? cmd_line : " " , - 1 ) ;
2006-08-31 08:21:39 -07:00
parse_input ( moo_command_data_get ( data , KEY_INPUT ) , & index ) ;
2006-08-20 01:49:33 -07:00
gtk_combo_box_set_active ( moo_glade_xml_get_widget ( xml , " input " ) , index ) ;
2006-08-31 08:21:39 -07:00
parse_output ( moo_command_data_get ( data , KEY_OUTPUT ) , & index ) ;
2006-08-20 01:49:33 -07:00
gtk_combo_box_set_active ( moo_glade_xml_get_widget ( xml , " output " ) , index ) ;
2006-09-02 00:34:01 -07:00
2006-11-02 00:25:50 -08:00
set_filter_combo ( moo_glade_xml_get_widget ( xml , " filter " ) ,
moo_command_data_get ( data , KEY_FILTER ) ) ;
2006-08-20 01:49:33 -07:00
}
static gboolean
2007-02-27 20:23:57 -08:00
exe_factory_save_data ( G_GNUC_UNUSED MooCommandFactory * factory ,
GtkWidget * page ,
MooCommandData * data )
2006-08-20 01:49:33 -07:00
{
MooGladeXML * xml ;
GtkTextView * textview ;
const char * cmd_line ;
char * new_cmd_line ;
gboolean changed = FALSE ;
int index , old_index ;
const char * input_strings [ 4 ] = { " none " , " lines " , " selection " , " doc " } ;
2006-08-30 23:26:50 -07:00
const char * output_strings [ 5 ] = { " none " , " async " , " pane " , " insert " , " new-doc " } ;
2006-08-20 01:49:33 -07:00
xml = g_object_get_data ( G_OBJECT ( page ) , " moo-glade-xml " ) ;
textview = moo_glade_xml_get_widget ( xml , " textview " ) ;
g_assert ( GTK_IS_TEXT_VIEW ( textview ) ) ;
new_cmd_line = moo_text_view_get_text ( textview ) ;
2006-08-31 08:21:39 -07:00
cmd_line = moo_command_data_get_code ( data ) ;
2006-08-20 01:49:33 -07:00
2006-09-02 00:34:01 -07:00
if ( ! _moo_str_equal ( cmd_line , new_cmd_line ) )
2006-08-20 01:49:33 -07:00
{
2006-08-31 08:21:39 -07:00
moo_command_data_set_code ( data , new_cmd_line ) ;
2006-08-20 01:49:33 -07:00
changed = TRUE ;
}
index = gtk_combo_box_get_active ( moo_glade_xml_get_widget ( xml , " input " ) ) ;
2006-08-31 08:21:39 -07:00
parse_input ( moo_command_data_get ( data , KEY_INPUT ) , & old_index ) ;
2006-08-20 01:49:33 -07:00
g_assert ( 0 < = index & & index < MOO_COMMAND_EXE_MAX_INPUT ) ;
if ( index ! = old_index )
{
2006-08-31 08:21:39 -07:00
moo_command_data_set ( data , KEY_INPUT , input_strings [ index ] ) ;
2006-08-20 01:49:33 -07:00
changed = TRUE ;
}
index = gtk_combo_box_get_active ( moo_glade_xml_get_widget ( xml , " output " ) ) ;
2006-08-31 08:21:39 -07:00
parse_output ( moo_command_data_get ( data , KEY_OUTPUT ) , & old_index ) ;
2006-08-20 01:49:33 -07:00
g_assert ( 0 < = index & & index < MOO_COMMAND_EXE_MAX_OUTPUT ) ;
if ( index ! = old_index )
{
2006-08-31 08:21:39 -07:00
moo_command_data_set ( data , KEY_OUTPUT , output_strings [ index ] ) ;
2006-08-20 01:49:33 -07:00
changed = TRUE ;
}
2006-09-02 00:34:01 -07:00
if ( index = = MOO_COMMAND_EXE_OUTPUT_PANE )
{
const char * old_filter ;
char * new_filter = NULL ;
GtkComboBox * combo = moo_glade_xml_get_widget ( xml , " filter " ) ;
GtkTreeIter iter ;
if ( gtk_combo_box_get_active_iter ( combo , & iter ) )
{
GtkTreeModel * model = gtk_combo_box_get_model ( combo ) ;
gtk_tree_model_get ( model , & iter , COLUMN_ID , & new_filter , - 1 ) ;
}
old_filter = moo_command_data_get ( data , KEY_FILTER ) ;
if ( ! _moo_str_equal ( old_filter , new_filter ) )
{
moo_command_data_set ( data , KEY_FILTER , new_filter ) ;
changed = TRUE ;
}
g_free ( new_filter ) ;
}
else
{
moo_command_data_set ( data , KEY_FILTER , NULL ) ;
}
2006-08-20 01:49:33 -07:00
g_free ( new_cmd_line ) ;
return changed ;
}
2006-08-23 00:38:16 -07:00
static gboolean
2007-02-27 20:23:57 -08:00
exe_factory_data_equal ( G_GNUC_UNUSED MooCommandFactory * factory ,
MooCommandData * data1 ,
MooCommandData * data2 )
2006-08-23 00:38:16 -07:00
{
guint i ;
2006-08-31 08:21:39 -07:00
for ( i = 0 ; i < N_KEYS ; + + i )
2006-08-23 00:38:16 -07:00
{
2006-08-31 08:21:39 -07:00
const char * val1 = moo_command_data_get ( data1 , i ) ;
const char * val2 = moo_command_data_get ( data2 , i ) ;
2006-09-02 00:34:01 -07:00
if ( ! _moo_str_equal ( val1 , val2 ) )
2006-08-23 00:38:16 -07:00
return FALSE ;
}
return TRUE ;
}
2006-08-20 01:49:33 -07:00
static void
2007-02-27 20:23:57 -08:00
_moo_command_factory_exe_class_init ( MooCommandFactoryExeClass * klass )
2006-08-20 01:49:33 -07:00
{
2007-02-27 20:23:57 -08:00
klass - > create_command = exe_factory_create_command ;
klass - > create_widget = exe_factory_create_widget ;
klass - > load_data = exe_factory_load_data ;
klass - > save_data = exe_factory_save_data ;
klass - > data_equal = exe_factory_data_equal ;
2006-08-20 01:49:33 -07:00
}