; ;+ ; NAME: ; ; START ; ; PURPOSE: ; ; Generic procedure to automatically set the paths environment and run a procedure. ; By simply writing in a Configuration File the name of the procedure to run and the paths of ; the used libraries, the user can easily work with different projects, ; without to manually editing the IDL search and working directories at each time. ; The routine will work on any operative system. ; A GUI mode is also available to easily select the paths to write the configuration file. ; ; CATEGORY: ; ; Program Control. ; ; CALLING SEQUENCE: ; ; START [, /NO_START] [, CFG_FILE=CFG_FILE] [, /GUI] ; ; ; KEYWORD PARAMETERS: ; ; NO_START: Tells the program to don't run the procedure after setting the environment paths. ; ; CFG_FILE: Filename of the Configuration File in which to read the paths and the name of ; the procedure to run. ; If not set, a file named 'start,cfg' is searched in the same directory of START.PRO. ; If no configuration file at all has been prepared, the path will be restricted to the ; only directory of START.PRO. ; Hereafter an example of a Configuration File (it is an ASCII file): ; ; ------------------------------------------------------------------------------------ ; ##### Begin the paths with "+" if you want to include the subdirectories tree ###### ; ; # Procedure to run: ; procedure = "my_procedure" ; ; # Procedure related paths: ; programs_path = "+C:\my_procedure_directory" ; ; # Library path: ; library_path ="+C:\my_libraries_directory;+C:\other_libraries_directory" ; ------------------------------------------------------------------------------------ ; ; With the above example file, the user tells IDL to set 'C:\my_procedure_directory' as the working ; directory and to add all its subdirectory tree to the IDL search path (because of the '+' ; sign), then to add all the libraries in '+C:\my_libraries_directory' and in ; '+C:\other_libraries_directory' to the search path and finally to run the program 'my_procedure' ; (to be written whitout the .pro extension). ; No other directories, but the IDL system directories, will be added to the path defined in the file. ; ; ; GUI: if set, open a Widget from which the user can edit the procedure and paths values buy interactively ; browsing the directories. Useful to write the configuration file the first time a new project is started ; or to edit it when copying all the project on a different computer. ; ; ; SIDE EFFECTS: ; ; The common block: COMMON system, system is created with the structure 'system' of the following form: ; ; system = { os: !VERSION.OS_FAMILY, $ ;current operative system ; slash: '', $ ;directory separation character for the current operative system ; path_separator: '', $ ;IDL path separation character for the current operative system ; copy_command: '', $ ;shell COPY command for the current operative system ; move_command: '', $ ;shell MOVE / RENAME command for the current operative system ; delete_command: ''} ;shell DELETE command for the current operative system ; ; ; RESTRICTIONS: ; ; Needs al least IDL 5.6 ; ; MODIFICATION HISTORY: ; ; Feb 2004 - Gianluca Li Causi, INAF - Rome Astronomical Observatory ; licausi@mporzio.astro.it ; http://www.mporzio.astro.it/~licausi/ ; Mar 2004 - Gianluca Li Causi - added possibility to don't use any configuration file ; May 2005 - Gianluca Li Causi - fix a bug with multiple library paths ; June 2005 - Gianluca Li Causi - GUI mode ;- PRO Start, no_start=no_start, cfg_file_in=cfg_file_in, gui=gui COMMON system, system COMMON ___Start, Start, cfg_file FORWARD_FUNCTION ___str_subst, ___read_parameters, ___write_parameters ;Imposta i parametri per il sistema operativo corrente: system = { os: !VERSION.OS_FAMILY, $ slash: '', $ path_separator: '', $ copy_command: '', $ move_command: '', $ delete_command: ''} CASE StrUpCase(system.os) of 'WINDOWS': BEGIN system.slash = '\' system.path_separator = ';' system.copy_command = 'copy' system.move_command = 'move' system.delete_command = 'del' END 'UNIX': BEGIN system.slash = '/' system.path_separator = ':' system.copy_command = 'cp' system.move_command = 'mv' system.delete_command = 'rm' END 'MACOS': BEGIN system.slash = ':' system.path_separator = ':' system.copy_command = '' system.move_command = '' system.delete_command = '' END 'VMS': BEGIN system.slash = ']' system.path_separator = ',' system.copy_command = '' system.move_command = '' system.delete_command = '' END ELSE: BEGIN system.slash = '' system.path_separator = '' system.copy_command = '' system.move_command = '' system.delete_command = '' END ENDCASE ;Chiude tutti i file eventualmente lasciati aperti in sessioni precedenti: close, /all ;Legge la directory corrente: ;Ref: SourceRoot function Help, Calls = Calls UpperRoutine = (StrTok(Calls[0], ' ', /Extract))[0] Skip = 0 Catch, ErrorNumber If (ErrorNumber ne 0) then Begin Catch, /Cancel ThisRoutine = Routine_Info(UpperRoutine, /Source) Skip = 1 EndIf If (Skip eq 0) then Begin ThisRoutine = Routine_Info(UpperRoutine, /Source) EndIf current_dir = StrMid(ThisRoutine.Path, 0, StrPos(ThisRoutine.Path, system.slash, /Reverse_Search) + 1) print, 'DETECTED CURRENT DIRECTORY: ', current_dir ;il "+" per aggiungere le subdirectories deve essere messo in start.cfg Start = { procedure: '', $ programs_path: '', $ library_path: ''} ;Setta la directory corrente: CD, current_dir ;Definisce il PATH: !PATH = EXPAND_PATH('+' + !DIR) ;IDL path IF NOT KEYWORD_SET(cfg_file_in) THEN cfg_file_in = 'start.cfg' cfg_file = cfg_file_in ___update_paths, Start, cfg_file IF Start.programs_path EQ '' THEN Start.programs_path = EXPAND_PATH(current_dir) ;Current dir ;;;!PATH = !PATH + system.path_separator + Start.programs_path ;Widget GUI: IF KEYWORD_SET(GUI) THEN BEGIN base_id = Widget_Base(TITLE='Environment Settings:', row=4) row1_id = Widget_Base(base_id, column=2) row2_id = Widget_Base(base_id, column=2) row3_id = Widget_Base(base_id, column=2) program_name_id = Widget_Text(row1_id, Value=Start.procedure, XSIZE=100, UNAME='Program_Name') programs_path_id = Widget_Text(row2_id, Value=Start.programs_path, XSIZE=100, UNAME='Programs_Path') library_id = Widget_Text(row3_id, Value=Start.library_path, XSIZE=100, UNAME='Libraries') browse_program_id = Widget_Button(row1_id, Value='Procedure to start...', UVALUE='Browse_Procedure') browse_program_id = Widget_Button(row2_id, Value='Add Program Paths...', UVALUE='Browse_Programs_Path') browse_library_id = Widget_Button(row3_id, Value='Add Library Paths...', UVALUE='Browse_Library') ok_button_id = Widget_Button(base_id, Value='OK', Uvalue='OK') Widget_Control, base_id, /REALIZE XMANAGER, 'Start_GUI', base_id ENDIF ;Run the automatic procedure: IF NOT KEYWORD_SET(no_start) THEN IF Start.Procedure NE '' THEN Call_Procedure, strlowcase(Start.Procedure) END PRO ___update_paths, Start, cfg_file COMMON system, system ;Aggiunge i paths descritti dal file 'start.cfg' IF FILE_TEST(cfg_file) THEN BEGIN ;Legge i parametri nel file installation.cfg: ___read_parameters, cfg_file, start n_paths = N_TAGS(Start) FOR i = 1, n_paths-1 DO BEGIN this_path = strsplit(Start.(i), system.path_separator, /EXTRACT) this_path = STRTRIM(this_path, 2) IF MIN(FILE_TEST(___str_subst(this_path, '+', ''), /DIR)) EQ 0 AND STRTRIM(Start.(i),2) NE '' THEN $ message, 'The path number ' + string(i) + 'in the configuration file does not exist!' !PATH = !PATH + system.path_separator + EXPAND_PATH(Start.(i)) ENDFOR ENDIF END PRO Start_GUI_event, Event COMMON system, system COMMON ___Start, Start, cfg_file Widget_Control, Event.id, GET_UVALUE=uvalue IF uvalue EQ 'Browse_Procedure' THEN BEGIN procedure_path = DIALOG_PICKFILE(FILTER='*.pro', TITLE='Select the Procedure to Start automatically...', /FIX_FILTER) IF procedure_path EQ '' THEN RETURN pos = strpos(procedure_path, system.slash, /REVERSE_SEARCH) IF pos LT 0 THEN Start.procedure = procedure_path ELSE BEGIN Start.procedure = strmid(procedure_path, pos+1) pos = strpos(Start.procedure, '.pro', /REVERSE_SEARCH) IF pos GE 0 THEN Start.procedure = strmid(Start.procedure, 0, pos) text_id = Widget_Info(Event.top, FIND_BY_UNAME='Program_Name') Widget_Control, text_id, Set_Value=Start.procedure ENDELSE ENDIF IF uvalue EQ 'Browse_Programs_Path' THEN BEGIN programs_path = DIALOG_PICKFILE(TITLE='Select a Directory of the current project...', /DIRECTORY) IF programs_path NE '' THEN BEGIN IF strlen(Start.programs_path) GT 0 THEN char = system.path_separator ELSE char = '' Start.programs_path = Start.programs_path + char + '+' + programs_path text_id = Widget_Info(Event.top, FIND_BY_UNAME='Programs_Path') Widget_Control, text_id, Set_Value=Start.programs_path ENDIF ENDIF IF uvalue EQ 'Browse_Library' THEN BEGIN library_path = DIALOG_PICKFILE(TITLE='Select a Library Directory...', /DIRECTORY) IF library_path NE '' THEN BEGIN IF strlen(Start.library_path) GT 0 THEN char = system.path_separator ELSE char = '' Start.library_path = Start.library_path + char + '+' + library_path text_id = Widget_Info(Event.top, FIND_BY_UNAME='Libraries') Widget_Control, text_id, Set_Value=Start.library_path ENDIF ENDIF IF uvalue EQ 'OK' THEN BEGIN Widget_Control, Event.top, /DESTROY ___write_parameters, cfg_file, Start ___update_paths, Start, cfg_file ENDIF END FUNCTION ___str_subst, s, in, out, start = start ;Sostituisce tutte le occorrenze della sottostringa IN ;con la stringa OUT nelle stringhe S IF KEYWORD_SET(start) THEN inizio = start ELSE inizio = 0 ns = n_elements(s) result = s ;IF ns EQ 1 THEN s = strarr(ns) + s FOR i = 0, ns-1 DO BEGIN pos = strpos(result[i], in, inizio) IF pos LT 0 THEN GOTO, next REPEAT BEGIN s1 = strmid(result[i], inizio, pos) s2 = strmid(result[i], pos+strlen(in), strlen(result[i])) result[i] = s1 + out + s2 pos = strpos(result[i], in, pos+strlen(out)) ENDREP UNTIL pos EQ (-1) next: ENDFOR RETURN, result END PRO ___Read_Parameters, filename, structure ON_ERROR, 2 IF N_PARAMS() LT 2 THEN MESSAGE, 'Both Filename and Structure must be given!' IF n_elements(structure) EQ 0 THEN structure = 0 IF size(structure, /type) LT 8 THEN BEGIN Read_Parameters_Number, filename, number, tags=tags structure = CREATE_STRUCT(tags[0], '') FOR i = 1, number-1 DO structure = CREATE_STRUCT(structure, tags[i], '') ENDIF tags = tag_names(structure) tags = strlowcase(tags) ntags = n_elements(tags) OPENR, unit, filename, /GET_LUN line = "" i = 0 WHILE i LT ntags DO BEGIN IF NOT EOF(unit) THEN BEGIN READF, unit, line line = strtrim(line, 2) ;elimina eventuali spazi iniziali o finali pos_equal = strpos(line, "=") IF pos_equal GE 0 THEN BEGIN tag_side = strmid(line, 0, pos_equal) ;parte prima dell'uguale pos = strpos(strlowcase(tag_side), tags[i]) ;posizione del tag cercato tag_string = strtrim(strlowcase(tag_side), 2) ;elimina gli spazi iniziali e finali IF tag_string EQ tags[i] AND pos EQ 0 AND strlen(line) GE 3 THEN BEGIN ;il tag deve essere la prima scritta sulla riga pos = strpos(line, '=', pos) value_string = strmid(line, pos+1, strlen(line)) value_string = ___str_subst(value_string, '"', '') ;elimina eventuali virgolette value_string = strtrim(value_string, 2) ;elimina eventuali spazi iniziali o finali size = size([structure.(i)]) n_el = n_elements(structure.(i)) IF n_el GT 1 THEN BEGIN ;array di piu' elementi value_string = ___str_subst(value_string, '[', '') ;elimina eventuali "[" value_string = ___str_subst(value_string, ']', '') ;elimina eventuali "]" value_string = strsplit(value_string, ',', /extract) ;elementi separati da virgola ENDIF value = structure.(i) IF size[size[0]+1] EQ 1 THEN BEGIN ;dato booleano --> byte per idl FOR j = 0, n_el-1 DO value[j] = where(strupcase(value_string[j]) EQ ['NO', 'YES']) ENDIF ELSE BEGIN value[*] = value_string[*] ENDELSE structure.(i) = value i = i + 1 ;next tag point_lun, unit, 0 ;rewind the file ENDIF ENDIF ENDIF ELSE BEGIN i = i + 1 ;next tag point_lun, unit, 0 ;rewind the file ENDELSE ENDWHILE FREE_LUN, unit, /FORCE END PRO ___write_parameters, filename, structure, no_first=no_first tags = tag_names(structure) tags = strlowcase(tags) ntags = n_elements(tags) ;close, /all openr, 1, filename ;Reads all the file into a string array: rows = [' '] line = '' WHILE NOT EOF(1) DO BEGIN READF, 1, line line = strtrim(line, 2) ;elimina eventuali spazi iniziali o finali rows = [rows, line] ;aggiunge la riga all'array ENDWHILE rows = rows[1:n_elements(rows)-1] ;elimina il primo spazio vuoto nrows = n_elements(rows) ;nmero di righe nel file close, 1 free_lun, 1 new_rows = rows line = "" i = 0 WHILE i LT ntags DO BEGIN ;Ciclo sui TAG r = 0 WHILE r LE (nrows-1) DO BEGIN ;Ciclo sulle righe line = rows[r] pos_equal = strpos(line, "=") IF pos_equal GE 0 THEN BEGIN ;Se trova il segno "=" tag_side = strmid(line, 0, pos_equal) ;parte prima dell'uguale pos = strpos(strlowcase(tag_side), tags[i]) ;posizione del tag cercato ;tag_string = strtrim(strlowcase(tag_side), 2) ;elimina gli spazi iniziali e finali ;IF tag_string EQ tags[i] AND ((n_elements(NO_FIRST) EQ 0 AND pos EQ 0 AND strlen(line) GE 3) OR (Keyword_Set(NO_FIRST) AND pos GE 0)) THEN BEGIN ;il tag deve essere la PRIMA SCRITTA sulla riga IF ((n_elements(NO_FIRST) EQ 0 AND pos EQ 0 AND strlen(line) GE 3) OR (Keyword_Set(NO_FIRST) AND pos GE 0)) THEN BEGIN ;il tag deve essere la PRIMA SCRITTA sulla riga old_value_string = strmid(line, pos_equal + 1) old_len = strlen(old_value_string) value = structure.(i) sz = size(value) tipo = sz[sz[0] + 1] elementi = n_elements(value) ;numero elementi se e' un vettore value_string = '' FOR e = 0, elementi-1 DO BEGIN v_string = string(value[e]) v_string = strtrim(v_string, 2) ;elimina eventuali spazi iniziali o finali IF tipo EQ 7 THEN v_string = '"' + v_string + '"' ;tipo stringa: aggiunge le virgolette per iraf IF tipo EQ 1 THEN v_string = (['no', 'yes'])[value NE 0] ;tipo byte: sostituisce con booleano per iraf IF e GT 0 THEN value_string = value_string + ',' value_string = value_string + v_string ENDFOR newline = strmid(line, 0, pos_equal + 1) + value_string new_rows[r] = newline ;Legge il resto del file ;reminder = '' ;WHILE NOT EOF(1) DO BEGIN ; READF, 1, line ; reminder = reminder + line ;ENDWHILE ENDIF ENDIF r = r +1 ENDWHILE i = i + 1 ;next tag ENDWHILE ;Sovrascrive il nuovo file openw, 1, filename FOR r = 0, nrows-1 DO printf, 1, new_rows[r] close, 1 free_lun, 1 END