Difference between revisions of "Using a linux editor inside VistA"

From VistApedia
Jump to: navigation, search
 
(Added glossary link to Record~)
 
(5 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 +
Back to [[Programming VistA Issues]]
 +
 +
 
The screen editor in VistA lacks some of the features provided by linux editors.   
 
The screen editor in VistA lacks some of the features provided by linux editors.   
 
But how to have VistA use your favorite editor?  Here's how...
 
But how to have VistA use your favorite editor?  Here's how...
  
First, make new record in the ALTERNATE EDITOR file like this:
+
First, make new [[record~|Record]] in the ALTERNATE EDITOR file like this:
 
                                                                                  
 
                                                                                  
 
   NAME: JOE - LINUX EDITOR
 
   NAME: JOE - LINUX EDITOR
 
   ACTIVATION CODE FROM DIWE: DO EDIT^TMGEDIT("joe")
 
   ACTIVATION CODE FROM DIWE: DO EDIT^TMGEDIT("joe")
 
   DESCRIPTION: This will evoke the linux editor 'joe'
 
   DESCRIPTION: This will evoke the linux editor 'joe'
 +
 +
Then, in the user's entry/[[record~|Record]] in file 200 (NEW PERSON), in field PREFERRED EDITOR (#31.3), enter this new editor (e.g. "JOE - LINUX EDITOR")
 
                                                                                  
 
                                                                                  
 
Next, put the following code into a file named TMGEDIT.m
 
Next, put the following code into a file named TMGEDIT.m
Line 42: Line 47:
 
         set result=$ZSYSTEM&255  ;"get result of execution. (low byte only). 0=success
 
         set result=$ZSYSTEM&255  ;"get result of execution. (low byte only). 0=success
 
         if result>0 goto EditDone
 
         if result>0 goto EditDone
 
+
 
         ;"read file back into global WP         
 
         ;"read file back into global WP         
 
         set result=$$HFS2WPfp^TMGIOUTL(Filename,GlobalP)   
 
         set result=$$HFS2WPfp^TMGIOUTL(Filename,GlobalP)   
Line 49: Line 54:
 
  EditDone         
 
  EditDone         
 
         new temp set temp=$$DelFile^TMGIOUTL(Filename)
 
         new temp set temp=$$DelFile^TMGIOUTL(Filename)
 +
        set temp=$$DelFile^TMGIOUTL(Filename_"~") ;"delete joe backup file
 
         set temp=$$DelFile^TMGIOUTL(EditErrFile)
 
         set temp=$$DelFile^TMGIOUTL(EditErrFile)
 
  EditAbort         
 
  EditAbort         
Line 87: Line 93:
 
  SPNDone
 
  SPNDone
 
         quit
 
         quit
       
+
 
       
 
 
  WP2HFS(GlobalP,path,filename)
 
  WP2HFS(GlobalP,path,filename)
 
         ;"Purpose: To write a WP field to a Host-File-System file
 
         ;"Purpose: To write a WP field to a Host-File-System file
Line 114: Line 119:
 
         quit result
 
         quit result
  
WP2HFSfp(GlobalP,pathfilename)
+
WP2HFSfp(GlobalP,pathfilename)
 
         ;"Purpose: To provide an interface to WP2HFS for cases when filename is not already separated from path
 
         ;"Purpose: To provide an interface to WP2HFS for cases when filename is not already separated from path
 
         ;"Result: 0 if failure, 1 if success
 
         ;"Result: 0 if failure, 1 if success
Line 123: Line 128:
 
         set result=$$WP2HFS(.GlobalP,.path,.filename)
 
         set result=$$WP2HFS(.GlobalP,.path,.filename)
 
         quit result
 
         quit result
       
+
 
     
+
HFS2WP(path,filename,GlobalP)
HFS2WP(path,filename,GlobalP)
 
 
         ;"Purpose: To read a WP field from a Host-File-System file
 
         ;"Purpose: To read a WP field from a Host-File-System file
 
         ;"Input: path: for the output file, the path up to, but not including, the filename
 
         ;"Input: path: for the output file, the path up to, but not including, the filename
Line 144: Line 148:
 
          
 
          
 
         if $data(GlobalP)&($data(path))&($data(filename)) do
 
         if $data(GlobalP)&($data(path))&($data(filename)) do
         . new TMGWP  
+
         . new TMGWP,WP
 
         . set result=$$FTG^%ZISH(path,filename,"TMGWP(1,0)",1)
 
         . set result=$$FTG^%ZISH(path,filename,"TMGWP(1,0)",1)
 
         . if result=0 quit
 
         . if result=0 quit
Line 174: Line 178:
 
         quit result
 
         quit result
  
     
+
HFS2WPfp(pathfilename,GlobalP)
HFS2WPfp(pathfilename,GlobalP)
 
 
         ;"Purpose: To provide an interface to HFS2WP for cases when filename is not already separated from path
 
         ;"Purpose: To provide an interface to HFS2WP for cases when filename is not already separated from path
 
         ;"Result: 0 if failure, 1 if success
 
         ;"Result: 0 if failure, 1 if success
Line 184: Line 187:
 
         set result=$$HFS2WP(.path,.filename,.GlobalP)
 
         set result=$$HFS2WP(.path,.filename,.GlobalP)
 
         quit result
 
         quit result
       
+
 
             
+
DelFile(pathfilename)
DelFile(pathfilename)
 
 
         ;"Purpose: to delete one file on host file system
 
         ;"Purpose: to delete one file on host file system
 
          
 
          
Line 197: Line 199:
 
          
 
          
 
         quit result
 
         quit result
 +
 +
 +
That should do it...
 +
 +
Good luck and happy editing.
 +
Kevin Toppenberg

Latest revision as of 21:41, 10 March 2012

Back to Programming VistA Issues


The screen editor in VistA lacks some of the features provided by linux editors. But how to have VistA use your favorite editor? Here's how...

First, make new Record in the ALTERNATE EDITOR file like this:

 NAME: JOE - LINUX EDITOR
 ACTIVATION CODE FROM DIWE: DO EDIT^TMGEDIT("joe")
 DESCRIPTION: This will evoke the linux editor 'joe'

Then, in the user's entry/Record in file 200 (NEW PERSON), in field PREFERRED EDITOR (#31.3), enter this new editor (e.g. "JOE - LINUX EDITOR")

Next, put the following code into a file named TMGEDIT.m

EDIT(Editor)
       ;"Purpose: This will be a shell for a linux editor 
       ;"Input: Editor -- the name of the linux editor to use (i.e. vim, joe, pico etc)
       ;"              Allowed values: joe,vim,pico
       ;"Note: When this function gets called, VistA sets up some variables
       ;"      first to tell what should be edited etc.
       ;"      DIC=The global root of the WP field where the text to be edited is
       ;"              stored (or where new text should be stored)
       ;"              e.g. "^TMG(22702,27,DV,"
       ;"      (DV is also predefined, so reference to DV in DIC is covered.)
       ;"      There are other variables set up re margins etc.  I will be ignoring these.
       
       new result set result=0
       new GlobalP
       
       ;"By limiting value to certain values, it prevents a rouge user from putting a wedged
       ;"linux command into "Editor" and executing a system command through zsystem.
       set Editor=$get(Editor,"vim")
       if (Editor'="vim")&(Editor'="joe")&(Editor'="pico") goto EditAbort
       
       new EditErrFile set EditErrFile="/tmp/trashjoeoutput.txt"
       
       set GlobalP=$extract(DIC,1,$length(DIC)-1)_")"  ;"convert to closed form
       new Filename set Filename=$$UNIQUE^%ZISUTL("/tmp/vistaedit.tmp")
       set result=$$WP2HFSfp^TMGIOUTL(GlobalP,Filename)
       if result=0 goto EditDone
       
       new HookCmd
       set HookCmd=Editor_" "_Filename_" 2>"_EditErrFile
       zsystem HookCmd
       set result=$ZSYSTEM&255  ;"get result of execution. (low byte only). 0=success
       if result>0 goto EditDone

       ;"read file back into global WP         
       set result=$$HFS2WPfp^TMGIOUTL(Filename,GlobalP)   
       if result=1 do
       
EditDone        
       new temp set temp=$$DelFile^TMGIOUTL(Filename)
       set temp=$$DelFile^TMGIOUTL(Filename_"~") ;"delete joe backup file
       set temp=$$DelFile^TMGIOUTL(EditErrFile)
EditAbort        
       quit
       
  

Next, put the following functions into a file named TMGIOUTL.m

SplitFNamePath(FullNamePath,OutPath,OutName,NodeDiv)
       ;"SCOPE: Public
       ;"Purpose: Take FullNamePath, and split into name and path.
       ;"Input: FullNamePath: String to process.  
       ;"                e.g.: "/tmp/myfilename.txt"
       ;"                NOTICE: IF PASSED BY REFERENCE, WILL BE CHANGED TO FILENAME!
       ;"        OutName: MUST BE PASSED BY REFERENCE.  This is an OUT parameter
       ;"        OutPath: MUST BE PASSED BY REFERENCE.  This is an OUT parameter
       ;"        NodeDiv: [OPTIONAL] -- the character that separates folders (e.g. "/")
       ;"                if not supplied, then default value is "/"
       ;"Output: The resulting file name is put into OutName, 
       ;"                e.g.: "myfilename.txt"
       ;"        and the path is put into OutPath.
       ;"                e.g.: "/tmp/"
       ;"Result: None.
       
       set OutPath=""
       set OutName=""
       new PathNode
       set NodeDiv=$get(NodeDiv,"/")   
       set FullNamePath=$get(FullNamePath)
SPN1
       if (FullNamePath[NodeDiv)=0 set OutName=FullNamePath goto SPNDone
       set PathNode=$piece(FullNamePath,NodeDiv,1)
       set OutPath=OutPath_PathNode_NodeDiv
       set $piece(FullNamePath,NodeDiv,1)=""
       set FullNamePath=$extract(FullNamePath,2,255)
       goto SPN1
       
SPNDone
       quit
WP2HFS(GlobalP,path,filename)
       ;"Purpose: To write a WP field to a Host-File-System file
       ;"Input: GlobalP -- The reference to the header node (e.g.  ^TMG(22702,99,1) in example below)
       ;"         path: for the output file, the path up to, but not including, the filename
       ;"         filename -- the filename to save to in the host file system. 
       ;"         If file already exists, it will be overwritten.
       ;"Note:  The format of a WP field is as follows:
       ;"      e.g.    ^TMG(22702,99,1,0) = ^^4^4^3050118^
       ;"               ^TMG(22702,99,1,1,0) = Here is the first line of text
       ;"               ^TMG(22702,99,1,2,0) = And here is another line
       ;"               ^TMG(22702,99,1,3,0) =
       ;"               ^TMG(22702,99,1,4,0) = And here is a final line
       ;"  And the format of the 0 node is: ^^<line count>^<linecount>^<fmdate>^^
       ;"Result: 0 if failure, 1 if success
       ;"Assumptions: That GlobalP is a valid reference to a WP field
       
       new result set result=0 ;"default to failure
       
       if $data(GlobalP)&($data(path))&($data(filename)) do
       . new TMGWP 
       . merge TMGWP=@GlobalP
       . set result=$$GTF^%ZISH("TMGWP(1,0)",1,path,filename)

       quit result
WP2HFSfp(GlobalP,pathfilename)
       ;"Purpose: To provide an interface to WP2HFS for cases when filename is not already separated from path
       ;"Result: 0 if failure, 1 if success
       
       new path,filename,result
               
       do SplitFNamePath(.pathfilename,.path,.filename)
       set result=$$WP2HFS(.GlobalP,.path,.filename)
       quit result
HFS2WP(path,filename,GlobalP)
       ;"Purpose: To read a WP field from a Host-File-System file
       ;"Input: path: for the output file, the path up to, but not including, the filename
       ;"         filename -- the filename to save to in the host file system. 
       ;"If file already exists, it will be overwritten.
       ;"         GlobalP -- The reference to the header node (e.g.  ^TMG(22702,99,1) in example below)
       ;"Note:  The format of a WP field is as follows:
       ;"      e.g.    ^TMG(22702,99,1,0) = ^^4^4^3050118^
       ;"               ^TMG(22702,99,1,1,0) = Here is the first line of text
       ;"               ^TMG(22702,99,1,2,0) = And here is another line
       ;"               ^TMG(22702,99,1,3,0) =
       ;"               ^TMG(22702,99,1,4,0) = And here is a final line
       ;"  And the format of the 0 node is: ^^<line count>^<linecount>^<fmdate>^^
       ;"Result: 0 if failure, 1 if success
       ;"Assumptions: That GlobalP is a valid reference to a WP field

       new result set result=0 ;"default to failure
       
       if $data(GlobalP)&($data(path))&($data(filename)) do
       . new TMGWP,WP
       . set result=$$FTG^%ZISH(path,filename,"TMGWP(1,0)",1)
       . if result=0 quit
       . ;"Scan for overflow nodes, and integrate into main body
       . new i set i=$order(TMGWP(""))
       . if i'="" for  do  quit:(i="")
       . . if $data(TMGWP(i,"OVF")) do
       . . . new j set j=$order(TMGWP(i,"OVF",""))
       . . . if j'="" for  do  quit:(j="")
       . . . . new n set n=i+(j/10)
       . . . . set TMGWP(n,0)=TMGWP(i,"OVF",j)
       . . . . set j=$order(TMGWP(i,"OVF",j))
       . . . kill TMGWP(i,"OVF")
       . . set i=$order(TMGWP(i))
       . ;"Now copy into another variable, renumbering lines (in case there were overflow lines)
       . set i=$order(TMGWP(""))
       . set j=0
       . if i'="" for  do  quit:(i="")
       . . set j=j+1
       . . set WP(j,0)=TMGWP(i,0)
       . . set i=$order(TMGWP(i))
       . ;"now create a header node
       . do NOW^%DTC  ;"returns result in X
       . set WP(0)="^^"_j_"^"_j_"^"_X_"^^"
       . ;"now put WP into global reference.
       . kill @GlobalP
       . merge @GlobalP=WP
       
       quit result
HFS2WPfp(pathfilename,GlobalP)
       ;"Purpose: To provide an interface to HFS2WP for cases when filename is not already separated from path
       ;"Result: 0 if failure, 1 if success
       
       new path,filename,result
               
       do SplitFNamePath(.pathfilename,.path,.filename)
       set result=$$HFS2WP(.path,.filename,.GlobalP)
       quit result
DelFile(pathfilename)
       ;"Purpose: to delete one file on host file system
       
       new path,filename,result
       new TMGFile
       
       do SplitFNamePath(.pathfilename,.path,.filename)
       set TMGFile(filename)=""
       set result=$$DEL^%ZISH(path,"TMGFile")
       
       quit result


That should do it...

Good luck and happy editing. Kevin Toppenberg