TMGIOUTL ;TMG/kst/IO Utilities -- File browser ;05/16/09 ;;1.0;TMG-LIB;**1**;05/16/09 ;"TMG IO UTILITIES ;"Kevin Toppenberg MD ;"GNU General Public License (GPL) applies ;"5/16/09 ;"======================================================================= ;" API -- Public Functions. ;"======================================================================= ;"FBrowse(Option,OutPath,OutName) query the user to select a filename ;"======================================================================= ;"Private API calls ;"======================================================================= ;"LoadDir(pArray,curDir,TMGMask,Option) -- load curDir entries into pArray ;"HndOnSel(pArray,Option,Info) -- handle ON SELECT event from Scroller ;"HndlOnCmd(pArray,Option,Info) -- handle ON SELECT event from Scroller ;"ShowHelp -- show help for file browser ;"======================================================================= test new option set option("MSG")="Hello there!" set option("PATH")="/home/kdt0p" set option("SELECT DIR")=0 write $$FBrowse(.option) quit FBrowse(Option,OutPath,OutName) ;"SCOPE: PUBLIC ;"Purpose: To query the user, to get a filename back ;" Supplies optional directory listing. ;"Input: Option [OPTIONAL]. Format as follows. All entries are optional ;" Option("MSG") A message to show user prior to name prompt. ;" May contain "\n" character for line wrapping. ;" Option("PATH") Initial default path ;" Option("NAME") Initial default filename ;" Option("NodeDiv") The character that separates folders (e.g. "/") ;" If not supplied, then default value is "/" ;" Option("MATCH","*.m")="" -- e.g. use filter '*.m' ;" Option("MATCH","*.txt")="" -- e.g. use filter '*.txt" ;" NOTE: Filters are combined by AND, i.e. files matching one of the specified matches ;" Option("PROMPT") A prompt for user to enter filename/directory name ;" Option("SHOW HIDDEN")=1 Show files hidden (e.g. '.name') ;" Option("SELECT DIR")=1 if 1 then mode is to select directories, not files ;" OutPath: [OPTIONAL] Pass by reference, filled with selected path ;" OutName: [OPTIONAL] Pass by reference, filled with selected name ;"Result: returns user specified filename (with path), or "" if aborted write # ;"clear screen new ScrlFiles,done new selDir set selDir=+$get(Option("SELECT DIR")) new width set width=60 new line set $piece(line,"-",width-2)="-" set Option("HEADER",1)="+"_line_"+" new banner set banner="--== Please Select "_$select(selDir:"Directory",1:"File")_" ==--" set Option("HEADER",2)="|"_$$CJ^XLFSTR(banner,width-2)_"|" set Option("FOOTER",1)="Enter ? for help" if $get(Option("PROMPT"))'="" set Option("FOOTER",2)=Option("PROMPT") set Option("SCRN WIDTH")=width set Option("ON SELECT")="HndOnSel^TMGIOUT2" ;"code to call based on user input set Option("ON CMD")="HndlOnCmd^TMGIOUT2" ;"code to execute for number entry new msg set msg=$get(Option("MSG")) if msg'="" do . do PopupBox^TMGUSRIF("Message:",msg) . do PressToCont^TMGUSRIF new StackCaller set StackCaller=$$Caller^TMGMISC new nodeDiv set nodeDiv=$get(Option("nodeDiv"),"/") set Option("nodeDiv")=nodeDiv ;" in case it wasn't there initially new curDir set curDir=$get(Option("PATH")) if (curDir="")&($data(^TMG("TMP","SETTINGS","FBrowse",StackCaller))) do . set curDir=$get(^TMG("TMP","SETTINGS","FBrowse",StackCaller)) if curDir="" set curDir=nodeDiv set curDir=$$EnsureTrailDiv^TMGIOUTL(curDir,nodeDiv) if $$IsDir^TMGKERNL(curDir)=0 set curDir=nodeDiv new TMGSelect set TMGSelect="" L1 do LoadDir("ScrlFiles",curDir,.Option) set Option("HEADER",3)="|"_$$CJ^XLFSTR("Current Dir: "_curDir,width-2)_"|" set TMGSelect="" do Scroller^TMGUSRIF("ScrlFiles",.Option) ;"Event handler should set TMGSelect if TMGSelect="" goto LQ if selDir set done=0 do goto:done LQ . new Menu,UsrSlct . set Menu(0)="What do you want to do with this directory?" . set Menu(1)="Choose "_TMGSelect_" as selected directory"_$char(9)_"done" . set Menu(2)="Browse INTO it"_$char(9)_"into" . write ! . set UsrSlct=$$Menu^TMGUSRIF(.Menu,2) . write # . if UsrSlct="done" set done=1 if $$IsDir^TMGKERNL(TMGSelect) set curDir=TMGSelect goto L1 ;"browse into directory do SplitFNamePath^TMGIOUTL(TMGSelect,.OutPath,.OutName,nodeDiv) set ^TMG("TMP","SETTINGS","FBrowse",StackCaller)=OutPath ;"store for future use. LQ write # ;"clear screen quit TMGSelect LoadDir(pArray,curDir,Option) ;"Purpose: load curDir entries into pArray ;"Input: pArray -- PASS BY NAME. An OUT PARAMETER. Filled in as follows ;" @pArray@(1,DisplayText)=Return Text <-- note: must be numbered 1,2,3 etc. ;" @pArray@(2,DisplayText)=Return Text ;" @pArray@(3,DisplayText)=Return Text ;" curDir -- the directory to get files from ;" TMGMask -- PASS BY REFERENCE. The mask array (See FBrowse) ;" Option [OPTIONAL]. Format as follows. All entries are optional ;" Option("MATCH","*.m")="" -- e.g. use filter '*.m' ;" Option("MATCH","*.txt")="" -- e.g. use filter '*.txt" ;" NOTE: Filters are combined by AND, i.e. files matching one of the specified matches ;" Option("NodeDiv") The character that separates folders (e.g. "/") ;" If not supplied, then default value is "/" ;" Option("SHOW HIDDEN")=1 Show files hidden (e.g. '.name') ;" Option("SELECT DIR")=1 if 1 then mode is to select directories, not files ;" nodeDiv -- The character that separates folders (e.g. "/") ;" ShowHidden -- OPTIONAL. Default=0 If 1, then show hidden files ;"Results: none ; new TMGFiles,tempFiles new count set count=1 kill @pArray new nodeDiv set nodeDiv=$get(Option("nodeDiv"),"/") set nodeDiv=$get(nodDiv,"/") set ShowHidden=+$get(Option("SHOW HIDDEN")) new selDir set selDir=+$get(Option("SELECT DIR")) set curDir=$get(curDir,nodeDiv) set curDir=$$EnsureTrailDiv^TMGIOUTL(curDir,nodeDiv) if $$IsDir^TMGKERNL(curDir)=0 goto LDQuit ;"Note: Filter/Mask would apply to directory names too, so must ;" ask for list of files with mask applied **AND** also with ;" a mask of '*' to be sure to get directory names new tempMask set tempMask("*")="" if $$LIST^%ZISH(curDir,"tempMask","TMGFiles")=0 goto LDQuit new index set index="" for set index=$order(TMGFiles(index)) quit:(index="") do . if ($extract(index,1)=".")&(ShowHidden=0) quit . new FName,FPName . set FName=index . set FPName=curDir_FName . if $$IsDir^TMGKERNL(FPName) set tempFiles("DIRS","<"_FName_">")=FPName . else set tempFiles("FILES",FName)=FPName ; ;"Now get files again with user-supplied filter merge TMGMask=Option("MATCH") if $data(TMGMask)=0 goto LD2 ;"use FILES node already created kill tempFiles("FILES") ;"needs to be reloaded with mask applied. if $$LIST^%ZISH(curDir,"TMGMask","TMGFiles")=0 goto LDQuit new index set index="" for set index=$order(TMGFiles(index)) quit:(index="") do . if ($extract(index,1)=".")&(ShowHidden=0) quit . new FName,FPName . set FName=index . set FPName=curDir_FName . if $get(tempFiles("DIRS","<"_FName_">"))'="" quit . set tempFiles("FILES",FName)=FPName ; LD2 set index="" if curDir'=nodeDiv do . set @pArray@(count,".. ")=$$UpPath^TMGIOUTL(curDir) . set count=count+1 for set index=$order(tempFiles("DIRS",index)) quit:(index="") do . set @pArray@(count,index)=$get(tempFiles("DIRS",index)) . set count=count+1 if selDir=1 goto LDQuit ;"skip showing files. ; set index="" for set index=$order(tempFiles("FILES",index)) quit:(index="") do . set @pArray@(count,index)=$get(tempFiles("FILES",index)) . set count=count+1 ; LDQuit quit HndOnSel(pArray,Option,Info) ;"Purpose: handle ON SELECT event from Scroller ;"Input: pArray,Option,Info -- see documentation in Scroller ;" Info has this: ;" Info("CURRENT LINE","NUMBER")=number currently highlighted line ;" Info("CURRENT LINE","TEXT")=Text of currently highlighted line ;" Info("CURRENT LINE","RETURN")=return value of currently highlighted line ;"Globally-scoped var used: TMGSelect,TMGSCLRMSG new text set text=$get(Info("CURRENT LINE","TEXT")) set TMGSelect=$get(Info("CURRENT LINE","RETURN")) set TMGSCLRMSG="^" quit HndlOnCmd(pArray,Option,Info) ;"Purpose: handle ON SELECT event from Scroller ;"Input: pArray,Option,Info -- see documentation in Scroller ;" Info has this: ;" Info("USER INPUT")=input ;" Info("CURRENT LINE","NUMBER")=number currently highlighted line ;" Info("CURRENT LINE","TEXT")=Text of currently highlighted line ;" Info("CURRENT LINE","RETURN")=return value of currently highlighted line new done set done=0 new rtn set rtn=$get(Info("CURRENT LINE","RETURN")) new path set path=rtn new UsrInput set UsrInput=$get(Info("USER INPUT")) new cmd set cmd=$$UP^XLFSTR($piece(UsrInput," ",1)) if $extract(path,$length(path))'=nodeDiv do . set path=$$UpPath^TMGIOUTL(path) ;"Trim off filename if cmd="CD" do goto:done HOCDone . new newDir set newDir=$piece(UsrInput," ",2) . if newDir=".." set UsrInput=".." quit . set done=1 . if $extract(newDir,1)'="/" set newDir=path_newDir . if $$IsDir^TMGKERNL(newDir)=0 do quit . . write newDir," is not a valid existing directory.",! . . do PressToCont^TMGUSRIF . set TMGSelect=newDir . set TMGSCLRMSG="^" if cmd="MKDIR" do goto:done HOCDone . new newDir set newDir=$piece(UsrInput," ",2) . set done=1 . if $extract(newDir,1)'="/" set newDir=path_newDir . write !,"Create NEW directory: ",newDir . new % set %=2 . do YN^DICN write ! . if %=1 if $$mkdir^TMGKERNL(newDir) . write # . set TMGSelect=path . set TMGSCLRMSG="^" if cmd="RMDIR" do goto:done HOCDone . new newDir set newDir=$piece(UsrInput," ",2) . set done=1 . if $extract(newDir,1)'="/" set newDir=path_newDir . write !,"DELETE directory: ",newDir . new % set %=2 . do YN^DICN write ! . if %=1 if $$rmdir^TMGKERNL(newDir) . set TMGSelect=path . set TMGSCLRMSG="^" . write # if (UsrInput="{LEFT}")!(UsrInput="..") do goto HOCDone . new nodeDiv set nodeDiv=$get(Option("nodeDiv"),"/") ;"extra info passed . set TMGSelect=$$UpPath^TMGIOUTL(path) . set TMGSCLRMSG="^" if UsrInput="{RIGHT}" do goto HOCDone . set TMGSelect=$get(Info("CURRENT LINE","RETURN")) . set TMGSCLRMSG="^" ;"Later, I could put some stuff here to let the command line choose filters etc. ;"or perhaps jump to a given directory etc. Perhaps later... if UsrInput["?" do goto HOCDone . do ShowHelp(.Option) else do . new newName set newName=path_UsrInput . new % set %=2 . if $$FileExists^TMGIOUTL(newName) set %=1 . else do . . write !,"Use NEW filename: ",newName . . do YN^DICN write ! . . if %'=1 write # . if %=1 do . . set TMGSelect=newName . . set TMGSCLRMSG="^" HOCDone quit ShowHelp(Option) ;"Purpose: show help for file browser ;"Input: Option -- see documentation in Scroller write ! write "Use [UP], [DOWN], [PgUp], or [PgDown] keys to scroll",! write "Use [ENTER] to select file name",! write "Use [ENTER] or [RIGHT] key to browse into a directory",! write "Use [LEFT] key to back up one level",! write "Use ^ to abort without selecting a file",! if $get(Option("SELECT DIR"))'=1 do . write "To create/select a NEW file, just type new name and [ENTER]",! write "type: 'cd ' to change directory",! write "type: 'mkdir ' to create a NEW directory",! write "type: 'rmdir ' to DELETE a new directory",! do PressToCont^TMGUSRIF write # quit