How to properly link DCL to AutoLisp? - dialog

I'm trying to build a very basic AutoLisp interface. I'm a total beginner at this, so after failing to code this from scratch, I turned to studying DCL properly. I followed this tutorial:
http://www.afralisp.net/dialog-control-language/tutorials/dialog-boxes-and-autolisp-part-1.php
And I got the same error. AutoCAD basically exits from executing the function, as if the dcl file wasn't even there.
I tried typing the address completely into it, but I think it should be able to work simply like linking HTML to images found in the same folder.
Below you have my code:
DCL:
samp1 : dialog {
label = "Structural Holes";
ok_cancel;
}
Lisp:
(defun C:samp1()
(setq dcl_id (load_dialog "samp1.dcl"))
(if (not (new_dialog "samp1" dcl_id))
(exit)
)
(action_tile
"cancel"
"(done_dialog)(setq userclick nil)"
)
(action_tile
"accept"
"(done_dialog)(setq userclick T))"
)
(start_dialog)
(unload_dialog dcl_id)
(princ)
)
(princ)
Thanks to anyone who will take the time to help me out with this. I'm starting to be quite desperate and it's my first and only autolisp project, so I have no experience whatsoever...
LE: Please note that the dcl file and the lisp file are both found in the same folder, no other subfolders or anything else.

Could not find **.DCL file
error: quit / exit abort
error: LOAD failed
This usually means the autolisp file or DCL file could not be found. To solve this problem, make sure you put your autolisp and DCL files inside the AutoCAD search path. To be more specific, put them in a directory that is part of your "Support File and Search Path". To find the AutoCAD support file and search path list, do the following:
In AutoCAD, click on the TOOLS drop down menu.
Go to the OPTIONS menu item.
Click on the FILES tab.
Click on the plus sign + in front of SUPPORT FILE AND SEARCH PATH.
This is your search path location. The directories listed there are searched in order, from top to bottom for any autolisp program you try to load. It is also used to find blocks and DCL files.
Either add the directory you store your autolisp and DCL files, or move your autolisp and DCL files into one of the directories listed here. This should end the errors listed above.
I came across this piece of information by accident here:
http://www.jefferypsanders.com/autolisp_nodcl.html
HUGE THANKS to JefferyPSanders for that......

For what its worth, you can also create a dialog on the fly in a "known directory" (like the directory AutoCAD resides in for example). The following will demonstrate that.
(defun _make-getstring-dialog-on-the-fly ( / fn f dcl dcl_id userclick str)
(setq fn (strcat
(vl-filename-directory
(findfile "acad.exe")) "\\$vld$.dcl")
f (open fn "w")
dcl
'(
"stringdlg : dialog {"
"label = \"Charater Array\";"
": edit_box {"
"label = \">>:\";"
"edit_width = 20;"
"key = \"stringdlg\";"
"is_default = true;"
"}"
": row {"
"alignment = centered;"
"fixed_width = true;"
" : button {"
" label = \"OK\";"
" key = \"dcl_accept\";"
" width = 10;"
" allow_accept = true;"
" }"
"}"
"}"
)
)
(mapcar
(function
(lambda ( x )
(write-line x f)
(write-line "\n" f)))
dcl)
(close f)
(setq dcl_id (load_dialog fn))
(new_dialog "stringdlg" dcl_id)
(action_tile "stringdlg" "(setq str $value)(done_dialog)")
(setq userclick (start_dialog))
(unload_dialog dcl_id)
str
)

Related

Copy part of the file in the buffer

I need to copy part of the file (with re-search-forward) to another file under the marker. I know how to use re-search-forward, but I have problems with buffer.
Am i right with my logic?
1) open needed file with temp buffer
2) create new buffer
3) find needed lines with re-search-forward and copy them in this new
buffer
4) insert lines into opened file with insert-buffer-substring
Right now i have a function like this:
(defun my-insert-file-name (filename)
(interactive "*fInsert file name: ")
(save-excursion
(goto-char (point-min))
(when (re-search-forward "#here")
(forward-line 1)
(------something should be here-----)))
Your question is short on details, but maybe something like this?
(let (buf)
(with-temp-buffer
(setq buf (current-buffer))
(insert-file-contents "/file/to/insert")
(do-stuff-to-temp-buffer)
(with-current-buffer "buffer-to-insert-into"
(insert-buffer-substring buf))))

How to save manipulated WAV files in object list?

I have the following problem: I want to low-pass filter 240 WAV files. The script is running only till the low-pass filtered sounds are created and shown in the object list ("..._band"). However, Praat does not export them as WAV files. After choosing the output folder, I get the warning message "Command 'Get number of strings' not available for current selection".
In short, my question is how can I save the WAV sounds in the object list individually with their new file names? See also Screenshot.
Script see below.
Thank you very much for your help!
Greetings,
#determine praat version
ver1$ = left$(praatVersion$, (rindex(praatVersion$, ".")-1));
ver1 = 'ver1$'
if ver1 < 5.2
exit Please download a more recent version of Praat
endif
if ver1 == 5.2
ver2$ = right$(praatVersion$, length(praatVersion$) - (rindex(praatVersion$, ".")));
ver2 = 'ver2$'
if ver2 < 4
exit Please download a more recent version of Praat (minor)
endif
endif
beginPause ("Low-Pass Filter Instructions")
comment ("1. Select a folder containing the wave files to be low-pass filtered")
comment ("2. Wave files will be low-pass filtered (0 - 400 Hz)")
comment ("3. Select an output folder for the low-pass filtered wave files to be saved to")
comment ("Click 'Next' to begin")
clicked = endPause("Next", 1);
#wavefile folder path
sourceDir$ = chooseDirectory$ ("Select folder containing wave files")
if sourceDir$ == ""
exit Script exited. You did not select a folder.
else
sourceDir$ = sourceDir$ + "/";
endif
Create Strings as file list... list 'sourceDir$'/*.wav
numberOfFiles = Get number of strings
levels$ = ""
for ifile to numberOfFiles
select Strings list
currentList = selected ("Strings")
filename$ = Get string... ifile
Read from file... 'sourceDir$'/'filename$'
currentSound = selected ("Sound")
filterFreqRange = Filter (pass Hann band)... 0 400 20
select currentSound
Remove
endfor
select currentList
Remove
#output folder path - where the wave files get saved
outputDir$ = chooseDirectory$ ("Select folder to save wave files")
if outputDir$ == ""
exit Script exited. You did not select a folder.
else
outputDir$ = outputDir$ + "/";
endif
numberOfFiles = Get number of strings
for ifile to numberOfFiles
select Strings list
currentList = selected ("Strings")
filename$ = Get string... ifile
currentSound = selected ("Sound")
endif
Save as WAV file... 'outputDir$'/'filename$'
select currentSound
Remove
endfor
#clean up
select currentList
Remove
#clear the info window
clearinfo
#print success message
printline Successfully low-pass filtered 'numberOfFiles' wave files.
At a glance, the command is not available because when you get to that point in the script the selection is empty. It is empty because at the end of the first loop, you select your Strings object and then Remove it.
More generally, your script is not handling the object selection properly, which is a big problem in Praat because available commands change depending on the active selection.
So even if you remove the line where you Remove the list, you will bump into a problem the second time you run Get number of strings because by then you have changed the selection. And even if you remove that line (which you don't really need), you'll still bump into a problem when you run selected("Sound") after selecting the Strings object, because by then you won't have any selected Sound objects (you didn't have them before anyway).
A more idiomatic version of your script, which also runs on a single loop where sounds are read, filtered, and removed one by one (which is also more memory efficient) would look like this:
form Low-Pass Filter...
real From_frequency_(Hz) 0
real To_frequency_(Hz) 400
real Smoothing_(Hz) 20
comment Leave paths empty for GUI selectors
sentence Source_dir
sentence Output_dir
endform
if praatVersion < 5204
exitScript: "Please download a more recent version of Praat"
endif
if source_dir$ == ""
source_dir$ = chooseDirectory$("Select folder containing wave files")
if source_dir$ == ""
exit
endif
endif
if output_dir$ == ""
output_dir$ = chooseDirectory$("Select folder to save filtered files")
if output_dir$ == ""
exit
endif
endif
list = Create Strings as file list: "list", source_dir$ + "/*.wav"
numberOfFiles = Get number of strings
levels$ = ""
for i to numberOfFiles
selectObject: list
filename$ = Get string: i
sound = Read from file: source_dir$ + "/" + filename$
filtered = Filter (pass Hann band): from_frequency, to_frequency, smoothing
Save as WAV file: output_dir$ + "/" + selected$("Sound")
removeObject: sound, filtered
endfor
Although you might be interested to know that, if you do not need the automatic file reading and saving (ie, if you are OK with having your script work on objects from the list) your script could be reduced to
Filter (pass Hann band): 0, 400, 20
which works on multiple selected Sound objects.
If you absolutely need the looping (ie, if you'll be working on really large sets of files) you might also be interested in using the vieweach plugin, with was written to try and minimise this sort of boilerplate (full disclaimer: I wrote the plugin). I wrote a longer blog post about it as well.

Trying to scrub a file with AutoIt

I work with a piece of software that outputs a sql script during upgrades. I am trying to make a tool that will read the file and append " ON IndexDataFile" to the lines that contain "CREATE INDEX" or "CREATE UNIQUE INDEX"
I open that file and write each line to a new file using FileOpen and FileReadLine. Despite a good deal of searching via Google and specific forums I have not been able to figure out how to search each line and append to it when one of the two values are found.
Here is the loop I am using to write to the new file:
While 1
$line_read = FileReadLine($handle_read)
If #error Then ExitLoop
;Code to evaluate line and append text when true
FileWriteLine($handle_write, $line_read)
WEnd
Can someone give me a hint on how to test the string and append when needed or is there a better approach to this?
In one line it would be as easy as:
$line_read = StringRegExpReplace($line_read, "(CREATE\ (?:UNIQUE\ )?INDEX)", "\1 ON IndexData")
You can test your RegEx on regex101.com to make sure, it works as expected.
Or you can write your expression differently if you prefer it fo a better way of reading with an "or" symbol |:
$line_read = StringRegExpReplace($line_read, "(CREATE\ INDEX|CREATE\ UNIQUE\ INDEX)", "\1 ON IndexData")
I was able to resolve it with the following:
While 1
$line_read = FileReadLine($handle_read)
If #error Then ExitLoop
If StringRegExp ( $line_read, "CREATE INDEX") Then $line_read = $line_read & " ON IndexData"
If StringRegExp ( $line_read, "CREATE UNIQUE INDEX") Then $line_read = $line_read & " ON IndexData"
FileWriteLine($handle_write, $line_read)
WEnd

vim latex-suite Understand MainFileExpression

I want to dynamically change the way latex-suite determines the MainFile.
The main file is usually the latex header file which includes other tex files (like chapters and so on). Using the MainFile it is possible to hit compile on some chapter-file so that latex-suite automatically compiles the header file instead.
This should be possible with g:Tex_MainFileExpression:
http://vim-latex.sourceforge.net/documentation/latex-suite/latex-master-file.html
However, the expression is not documented at all and even the example (which imo should reflect the default behavior) does not work.
let g:Tex_MainFileExpression = 'MainFile(modifier)'
function! MainFile(fmod)
if glob('*.latexmain') != ''
return fnamemodify(glob('*.latexmain'), a:fmod)
else
return ''
endif
endif
Can somebody please shortly point out to me how this is supposed to be used?
What return expression is expected? Why does the example not work?
Background: I have a latexmain file in the project root. I also have a figure subdirectory. For this subdirectory the root latex main should not be ignored, so that the current file itself is compiled.
I just ran into the problem of not knowing how to set g:Tex_MainFileExpression as well. The documentation and the example were not clear to me either. Turns out, the source code defines a function Tex_GetMainFileName, which sets the variable modifier from its arguments before executing g:Tex_MainFileExpression (see source code here). Therefore, g:Tex_MainFileExpression needs to be a function that has the argument modifier (not called differently!). The vim-latex documentation says, that modifier is a filetype-modifier, therefore your function needs to return fnamemodify(filename, modifier). So it has to look like this:
let g:Tex_MainFileExpression = 'MainFile(modifier)'
function! MainFile(fmod)
" Determine the full path to your main latex file that you want to compile.
" Store it e.g. in the variable `path`:
" let path = some/path/to/main.tex
" Apply `modifier` to your `path` variable
return fnamemodify(path, a:fmod)
endif
Example
I used this in a project where I have a two main latex files, one for the main document and one for supplementary material. The project structure looks like this:
project/
main.tex
sup.tex
.local-vimrc
main-source/
input1.tex
input2.tex
sup-source/
input1.tex
input2.tex
I load a .local-vimrc file (using the plugin MarcWeber/vim-addon-local-vimrc), where I set g:Tex_MainFileExpression such that <leader>ll compiles main.tex if the file in the current buffer is located in the folder main-source and compiles sup.tex if it is in the folder sup-source. Below is my .local-vimrc file. I have very little experience with vimscript, so this is probably a littly hacky, but it might help to get an idea on how to use g:Tex_MainFileExpression. Also, I have modified it to be less messy and not tested the following code explicitly.
let g:Tex_MainFileExpression = 'g:My_MainTexFile(modifier)'
function! g:My_MainTexFile(fmod)
" Get absolute (link resolved) paths to this script and the open buffer
let l:path_to_script = fnamemodify(resolve(expand('<sfile>:p')), ':h')
let l:path_to_buffer = fnamemodify(resolve(expand('%:p')), ':h')
" Check if the buffer file is a subdirectory of `main-source` or `sup-source`
" stridx(a, b) returns -1 only if b is not substring of a
if stridx(l:path_to_buffer, 'main-source') != -1
let l:name = 'main.tex'
elseif stridx(l:path_to_buffer, 'sup-source') != -1
let l:name = 'sup.tex'
else
echom "Don't know what's the root tex file. '".#%."' is not in 'main-source/' or 'sup-source/' directory."
return ''
endif
" Concatenate this script path with main latex file name
" NOTE: this assumes that this script is located in the same folder as the
" main latex files 'main.tex' and 'sup.tex'
let l:path = l:path_to_script.'/'.l:name
return fnamemodify(l:abs_path_main, a:fmod)
endfunction

vim how to create a debug message fast

I am using ruby on rails but that does not matter much for this question. Let's say that i have a statement like this
error = 'this is an error message'
I have noticed that I end up doing this a lot
error = 'this is an error message'
puts "error = #{error.inspect}"
I am sure a macro can be written which would take the work on the left hand side of left most = and then create another line along with template shown above.
I am using mvim on mac. Any pointer in terms of where I should start to look for developing what I want.
Try snipmate:
http://www.vim.org/scripts/script.php?script_id=2540
I recorded a simple macro that does your sample. To record a macro type q followed by what register you want the macro to be put in (convention calls for qq). To play the macro type # then the macro register. You can view this at :help recording
To write the macro, use the following commands (and here is how is should look in the register)
^yEoputs "error = #{^Op.inspect}"^[
^ moves to the first non whitespace character of the line
yE yanks to the end of the space separated word.
o Puts you in insert mode on the next line
puts "error = #{ is the text that you type out
^O is ctrl+O (capital letter o) - this allows the next, and only the next command to be run in command mode, which is...
p Puts the yanked word, after this command is run you're still in insert mode
.inspect}" is the text that you type and finally...
^[ is Esc
I would go for:
nnoremap µ :s/^\s*\(\k\+\)\s*=.*/&\rputs "\1 = #{\1.inspect}"/<cr>
:s presents the advantage of doing the job plus matching the assigned variable if any. Doing the same thing with classical commands like yw, p, etc would be more cumbersome.
If the template become more complex, we can rely on template-file expanders as long as they easily permit to call viml function like matchstr(). Of course, in that case I would use mu-template with the following template-file:
VimL:" $Id: {rtp}/template/ruby/inspect.template
VimL: let s:value_start = '¡'
VimL: let s:value_end = '¡'
VimL: let s:reindent = 1
VimL: let s:marker_open = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:varname = matchstr(getline(line('.')-1), '^\s*\zs\k\+\ze\s*=')
VimL: if empty(s:varname) |throw "the previous line don't assign any variable" |endif
puts "¡s:varname¡ = #{¡s:varname¡.inspect}"<++>
VimL:"vim: encoding=utf-8
If you're doing these on the fly, a snipmate snippet could look like this:
${1:error} = '${2:error message here}'
puts "error = #{$1.inspect}"
If, on the other hand you're just wanting to output pre-existing variables for debugging purposes. Nick-Canzoneri's macro may be more useful.

Resources