I would like to open a .4gl file in VI terminal and write to it, this is the code I have currently:
let p_command = "test -f ", MTGENDIR CLIPPED,"/",p_prog clipped,".4gl"
run p_command returning p_status
let p_command = "vi ",p_prog clipped,".4gl"
--let p_command = "w ",p_prog clipped,".4gl"
--let p_command = ":w ",p_prog clipped,".4gl"
run p_command
This is the error I get in the debugger once it gets to the step vi and then it hangs:
(fgldb) next
376 let p_command = "vi ",p_prog clipped,".4gl"
(fgldb) next
377 run p_command
(fgldb) next
Vim: Warning: Output is not to a terminal
Vim: Warning: Input is not from a terminal
if i try writing with the commented code above (w or :w) it crashes and display this error:
The DVM process crashed. Please contact FourJs support.
DVM has encountered a problem. Execution of 'mt_gen' stopped
Is there any other way i can write to .4gl file in Genero?
To answer the very last sentence "Is there any other way I can write to .4gl file in Genero?" then you can use base.Channel class to write to a file ...
MAIN
DEFINE ch base.Channel
LET ch = base.Channel.create()
CALL ch.openFile("example.4gl","w")
CALL ch.writeLine("MAIN")
CALL ch.writeLine(" DISPLAY 'Hello World'")
CALL ch.writeLine("END MAIN")
CALL ch.close()
END MAIN
... the key bit being the use of base.Channel.openFile and w (or a) as the opening mode http://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_ClassChannel_openFile.html
Alternatively you can build up the file inside a STRING or base.StringBuffer variable and use the TEXT writeFile method http://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_datatypes_TEXT_writeFile.html ...
MAIN
DEFINE s STRING
DEFINE t TEXT
LET s =
"MAIN", ASCII(13),
" DISPLAY 'Hello World'", ASCII(13),
"END MAIN"
LOCATE t IN MEMORY
LET t = s
CALL t.writeFile("example2.4gl")
END MAIN
I'm not sure why you think you need vi/vim in your solution to write to a .4gl file.
Related
I would like to run an external .bat file using groovy script in soapUI. also would like to use the output generated from the external file as the value for the header
here is the script that I am using to run the bat file
String line
def p = "cmd /c C:\\Script\\S1.bat".execute()
def bri = new BufferedReader (new InputStreamReader(p.getInputStream()))
while ((line = bri.readLine()) != null) {log.info line}
here is the content of the bat file
java -jar SignatureGen.jar -pRESOURCE -nRandomString -mGET -d/api/discussion-streams/metadata -teyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJjbGllbnQiOiIxIiwicm9sZSI6IllGQURNSU4iLCJleHAiOjI3NTgzMjU2MDIsInRpIjo3MjAwNiwiaWF0IjoxNTU4MzI1NjAyLCJwZXJzb24iOiI1In0.bbci7ZBWmPsANN34Ris9H0-mosKF2JLTZ-530Rex2ut1kjCwprZr_196N-K1alFBH_A9pbG0MPspaDOnvOKOjA
The following code:
def p = "ls -la".execute()
def err = new StringBuffer()
def out = new StringBuffer()
p.waitForProcessOutput(out, err)
p.waitForOrKill(5000)
int ret = p.exitValue()
// optionally check the exit value and err for errors
println "ERR: $err"
println "OUT: $out"
// if you want to do something line based with the output
out.readLines().each { line ->
println "LINE: $line"
}
is based on linux, but translates to windows by just replacing the ls -la with your bat file invocation cmd /c C:\\Script\\S1.bat.
This executes the process, calls waitForProcessOutput to make sure the process doesn't block and that we are saving away the stdout and stderr streams of the process, and then waits for the process to finish using waitForOrKill.
After the waitForOrKill the process has either been terminated because it took too long, or it has completed normally. Whatever the case, the out variable will contain the output of the command. To figure out whether or not there was an error during bat file execution, you can inspect the ret and err variables.
I chose the waitForOrKill timeout at random, adjust to fit your needs. You can also use waitFor without a timeout which will wait until the process completes, but it is generally better to set some timeout to make sure your command doesn't execute indefinitely.
I am beginning to think my search skills are lacking.
I trying to find any articles on how with Groovy, to open an interactive process, read its output and then write to the process depending on the output text. All I can find is how printing, reading and writing with files. Nothing about how to Write to a interactive process.
The process is asking for a password
Write the password to process
Something like this if possible:
def process = "some-command.sh".execute()
process.in.eachLine { line ->
if (line.contains("enter password")) {
process.out.write("myPassword")
}
}
This here works reading from the process output:
def process = "some-command.sh".execute()
process.in.eachLine { line ->
println line
}
Though it stops when the process is asking for input. It does not print out the line with the question.
Edit: Found out why it did not print the line with the ask password. It was not a new line. The question was a simple print (not println). How do I read when there is not yet a new line?
I have been told expect can be used, but I am looking for a solution which does not require a dependency.
1.bat
#echo off
echo gogogo
set /P V=input me:
echo V=%V%
this script waits for input just after :
gogogo
input me:
this means that eachLine not triggered for input me because no new line after it
however the previous line gogogo could be caught
and following script works for gogogo but does not work for input me
groovy
def process = "1.bat".execute()
process.in.eachLine { line ->
if (line.contains("gogogo")) {
process.out.write("myPassword\n".getBytes("UTF-8"))
process.out.flush()
}
}
groovy2
probably this could be optimized.. following script works without new line:
def process = "1.bat".execute()
def pout = new ByteArrayOutputStream()
def perr = new ByteArrayOutputStream()
process.consumeProcessOutput(pout, perr) //starts listening threads and returns immediately
while(process.isAlive()){
Thread.sleep(1234)
if(pout.toString("UTF-8").endsWith("input me:")){
process.out.write("myPassword\n".getBytes("UTF-8"))
process.out.flush()
}
}
Connecting to switch using expect spawn
child = pexpect.spawn('telnet ' + self.device_ip, timeout = 30)
When trying to run the below line, Im getting nothing as output
child.sendline('python script.py')
Can someone help me to run the python file over here?
I used
print("%s"%(child.before))
to print the output but it prints nothing
Make sure when you are using child.before that you have a child.expect statement beforehand. To put simply expect defines the text buffer that before references. Ex.
child = pexpect.spawn('telnet ' + self.device_ip, timeout = 30)
child.sendline('python script.py')
child.expect('user#abcd1234>')
remotehostoutput = (child.before)
I'm having trouble printing a table to a file with lua (and I'm new to lua).
Here's some code I found here to print the table;
function print_r ( t )
local print_r_cache={}
local function sub_print_r(t,indent)
if (print_r_cache[tostring(t)]) then
print(indent.."*"..tostring(t))
else
print_r_cache[tostring(t)]=true
if (type(t)=="table") then
for pos,val in pairs(t) do
if (type(val)=="table") then
print(indent.."["..pos.."] => "..tostring(t).." {")
sub_print_r(val,indent..string.rep(" ",string.len(pos)+8))
print(indent..string.rep(" ",string.len(pos)+6).."}")
elseif (type(val)=="string") then
print(indent.."["..pos..'] => "'..val..'"')
else
print(indent.."["..pos.."] => "..tostring(val))
end
end
else
print(indent..tostring(t))
end
end
end
if (type(t)=="table") then
print(tostring(t).." {")
sub_print_r(t," ")
print("}")
else
sub_print_r(t," ")
end
print()
end
I have no idea where the 'print' command goes to, I'm running this lua code from within another program. What I would like to do is save the table to a .txt file. Here's what I've tried;
function savetxt ( t )
local file = assert(io.open("C:\temp\test.txt", "w"))
file:write(t)
file:close()
end
Then in the print-r function I've changed everywhere it says 'print' to 'savetxt'. This doesn't work. It doesn't seem to access the text file in any way. Can anyone suggest an alternative method?
I have a suspicion that this line is the problem;
local file = assert(io.open("C:\temp\test.txt", "w"))
Update;
I have tried the edit suggested by Diego Pino but still no success. I run this lua script from another program (for which I don't have the source), so I'm not sure where the default directory of the output file might be (is there a method to get this programatically?). Is is possible that since this is called from another program there's something blocking the output?
Update #2;
It seems like the problem is with this line:
local file = assert(io.open("C:\test\test2.txt", "w"))
I've tried changing it "C:\temp\test2.text", but that didn't work. I'm pretty confident it's an error at this point. If I comment out any line after this (but leave this line in) then it still fails, if I comment out this line (and any following 'file' lines) then the code runs. What could be causing this error?
I have no idea where the 'print' command goes to,
print() output goes to default output file, you can change that with io.output([file]), see Lua manuals for details on querying and changing default output.
where do files get created if I don't specify the directory
Typically it will land in current working directory.
Your print_r function prints out a table to stdout. What you want is to print out the output of print_r to a file. Change the print_r function so instead of printing to stdout, it prints out to a file descriptor. Perhaps the easiest way to do that is to pass a file descriptor to print_r and overwrite the print function:
function print_r (t, fd)
fd = fd or io.stdout
local function print(str)
str = str or ""
fd:write(str.."\n")
end
...
end
The rest of the print_r doesn't need any change.
Later in savetxt call print_r to print the table to a file.
function savetxt (t)
local file = assert(io.open("C:\temp\test.txt", "w"))
print_r(t, file)
file:close()
end
require("json")
result = {
["ip"]="192.168.0.177",
["date"]="2018-1-21",
}
local test = assert(io.open("/tmp/abc.txt", "w"))
result = json.encode(result)
test:write(result)
test:close()
local test = io.open("/tmp/abc.txt", "r")
local readjson= test:read("*a")
local table =json.decode(readjson)
test:close()
print("ip: " .. table["ip"])
2.Another way:
http://lua-users.org/wiki/SaveTableToFile
Save Table to File
function table.save( tbl,filename )
Load Table from File
function table.load( sfile )
I'm trying to populate the quickfix list using an autoload function, i.e.:
function! myplugin#myfunc(msg)
" this doesn't work from *inside* an autoload function
let filename = fnamemodify(resolve(expand('<sfile>:p')))
" not sure if it's possible to get the line number from where
" a function was called
let linenum = '?#'
" create qf dict object
" set filename, line number, bufnr, text, etc
" add dict to qflist
" setqflist(qfdictlist)
endfunction!
The problem I've run into is I can't figure out a way to get the filename and line number from the code that called the autoload function. Any suggestions?
Out of the box. This is not possible.
However, depending on the exact scenario, here are a few leads.
I've attempted to write a function that decodes the callstack from v:throwpoint when an exception is caught. It's still experimental. See https://github.com/LucHermitte/lh-vim-lib/blob/master/autoload/lh/exception.vim
From my test unit framework, I know precisely which test-file/line is failing. To do so, I had to parse the UT file in order to inject the line number of the caller into the :Assert* commands.
As you see, none of these solutions is very good. But there are none other right now. The callstack isn't available, except from v:throwpoint in an exception context. The only other solution is to have callers inject their references (~__FILE__ + ~__LINE__) when calling. And the only way to automate this is to compile the caller script into another script that automatically injects the missing information.
By right now, understand there had been a proposal on vim-dev mailing list this last month in order to permit to have access to the call stack, but alas, only during debugging sessions: https://github.com/vim/vim/pull/433
If this is accepted, may be it could be extended later to offer a viml function that'll export this information.
EDIT: Your question inspired me to write a simplistic logging facility for vim:
" Function: lh#log#new(where, kind) {{{3
" - where: "vert"/""/...
" - kind: "qf"/"loc" for loclist
" NOTE: In order to obtain the name of the calling function, an exception is
" thrown and the backtrace is analysed.
" In order to work, this trick requires:
" - a reasonable callstack size (past a point, vim shortens the names returned
" by v:throwpoint
" - named functions ; i.e. functions defined on dictionaries (and not attached
" to them) will have their names mangled (actually it'll be a number) and
" lh#exception#callstack() won't be able to decode them.
" i.e.
" function s:foo() dict abort
" logger.log("here I am");
" endfunction
" let dict.foo = function('s:foo')
" will work correctly fill the quicklist/loclist, but
" function dict.foo() abort
" logger.log("here I am");
" endfunction
" won't
" TODO: add verbose levels
function! lh#log#new(where, kind) abort
let log = { 'winnr': bufwinnr('%'), 'kind': a:kind, 'where': a:where}
" open loc/qf window {{{4
function! s:open() abort dict
try
let buf = bufnr('%')
exe 'silent! '.(self.where). ' '.(self.kind == 'loc' ? 'l' : 'c').'open'
finally
call lh#buffer#find(buf)
endtry
endfunction
" add {{{4
function! s:add_loc(msg) abort dict
call setloclist(self.winnr, [a:msg], 'a')
endfunction
function! s:add_qf(msg) abort dict
call setqflist([a:msg], 'a')
endfunction
" clear {{{4
function! s:clear_loc() abort dict
call setloclist(self.winnr, [])
endfunction
function! s:clear_qf() abort dict
call setqflist([])
endfunction
" log {{{4
function! s:log(msg) abort dict
let data = { 'text': a:msg }
try
throw "dummy"
catch /.*/
let bt = lh#exception#callstack(v:throwpoint)
if len(bt) > 1
let data.filename = bt[1].script
let data.lnum = bt[1].pos
endif
endtry
call self._add(data)
endfunction
" reset {{{4
function! s:reset() dict abort
call self.clear()
call self.open()
return self
endfunction
" register methods {{{4
let log.open = function('s:open')
let log._add = function('s:add_'.a:kind)
let log.clear = function('s:clear_'.a:kind)
let log.log = function('s:log')
let log.reset = function('s:reset')
" open the window {{{4
call log.reset()
return log
endfunction
Which use this other function of mine that decodes the callstack.
Well, if you can't get the file and line from inside the autoload function, you have to pass that into your function.
Your autoloaded function is invoked somehow, either by a custom mapping, command, or on an :autocmd event. From there, you can resolve the current file (expand('%') and line number ('line('.')) and pass that in.
But why do you need that?! For normal editing tasks, I can't imagine why. If you're writting a custom Vim debugging plugin, okay, that might be useful. But debugging via Vimscript is difficult (as you've found out), the callstack isn't exposed. Better stick with the built-in :debug and :breakadd; I've so far found them sufficient.