Is there any way to list out all user defined proc calls in a Tcl file. ?
I have a TCL file, I want to list out all procs that has been called by that file.
Regards
keerthan
To get a message when a specific command is called, we can use an enter execution trace:
trace add execution $theCommand enter {apply {{call op} {
puts "Called [lindex $call 0]"
}}
To select which command to attach that trace to, we can use various approaches. The easiest is if you can identify a namespace whose procedures you want to attach to:
foreach p [info procs ::theNamespace::*] {
trace add execution $p enter {apply {{call op} {
puts "Called [lindex $call 0]"
}}
}
You can also attach it to every procedure created when a particular file is sourced. This is a bit more complex:
# Need to keep this script fragment so we can remove it again after the source
set tracer {apply {{proccall args} {
set cmd [uplevel 1 [list namespace origin [lindex $proccall 1]]]
trace add execution $cmd enter {apply {{call args} {
puts "Called [lindex $call 0]"
}}
}}
trace add execution ::proc leave $tracer
source /the/script.tcl
trace remove execution ::proc leave $tracer
You can get pretty complicated this way (and be aware that it also can affect procedures created by the loading of packages by the script; you can stop that, but it's a lot more work). Just attaching to all procedures that are currently in a namespace is simpler.
Related
I have a CSV file that looks like this:
CountryCode,CountryName
AD,Andorra
AE,United Arab Emirates
AF,Afghanistan
AG,Antigua and Barbuda
// -- snip -- //
and a class that looks like this:
module OpenData
class Country
def initialize(#code : String, #name : String)
end
end
end
and I want to have a class variable within the module automatically loaded at compile time like this:
module OpenData
##countries : Array(Country) = {{ run "./sources/country_codes.cr" }}
end
I tried to use the "run" macro above with the following code:
require "csv"
require "./country"
content = File.read "#{__DIR__}/country-codes.csv"
result = [] of OpenData::Country
CSV.new(content, headers: true).each do |row|
result.push OpenData::Country.new(row["CountryCode"], row["CountryName"])
end
result
but this results in
##countries : Array(Country) = {{ run "./sources/country_codes.cr" }}
^
Error: class variable '##countries' of OpenData must be Array(OpenData::Country), not Nil
All my other attempts somehow failed due to various reasons, like not being able to call .new within a macro or stuff like that. This is something I regularly do in Elixir and other languages that support macros and is something I would suspect Crystal can also achieve... I'd also take any other way that accomplishes the task at compile time!
Basically there are several more files I want to process this way, and they`re longer/more complex... thanks in advance!
EDIT:
Found the issue. It seems that I have to return a string that includes actual crystal code from the "run" macro. So, the code in the "run" file becomes:
require "csv"
content = File.read "#{__DIR__}/country-codes.csv"
lines = [] of String
CSV.new(content, headers: true).each do |row|
lines << "Country.new(\"#{row["CountryCode"]}\", \"#{row["CountryName"]}\")"
end
puts "[#{lines.join(", ")}]"
and everything works!
You already found your answer, but for completeness, here are the docs, from: https://crystal-lang.org/api/1.2.2/Crystal/Macros.html#run%28filename%2C%2Aargs%29%3AMacroId-instance-method
Compiles and execute a Crystal program and returns its output
as a MacroId.
The file denoted by filename must be a valid Crystal program.
This macro invocation passes args to the program as regular
program arguments. The program must output a valid Crystal expression.
This output is the result of this macro invocation, as a MacroId.
The run macro is useful when the subset of available macro methods
are not enough for your purposes and you need something more powerful.
With run you can read files at compile time, connect to the internet
or to a database.
A simple example:
# read.cr
puts File.read(ARGV[0])
# main.cr
macro read_file_at_compile_time(filename)
{{ run("./read", filename).stringify }}
end
puts read_file_at_compile_time("some_file.txt")
The above generates a program that will have the contents of some_file.txt.
The file, however, is read at compile time and will not be needed at runtime.
In my .zshrc file I have the following lines that parse my current git branch and display it in the terminal, the .zshrc file looks like this:
# Load version control information
autoload -Uz vcs_info
precmd() { vcs_info }
# Set up the prompt (with git branch name)
setopt PROMPT_SUBST
PROMPT='%n in ${PWD/#$HOME/~} ${vcs_info_msg_0_} > '
# Format the vcs_info_msg_0_ variable
zstyle ':vcs_info:git:*' formats '(%b)'
So my terminal ends up looking like this:
me in ~/repos/myrepo (feat/MYISSUE-123/fix-the-broken-stuff) >
I would like to modify the script above so MYISSUE-123 has a different colour to the rest of the branch name.
How can I do that?
Try this ... change precmd to:
precmd() {
vcs_info
psvar=(${(s:/:)vcs_info_msg_0_})
# in case there are more than three components:
psvar[3]=${(j:/:)psvar[3,-1]}
}
Make sure precmd() is being called prior to each prompt display by adding it to the hook:
autoload -Uz add-zsh-hook
add-zsh-hook precmd precmd
And change PROMPT to:
PROMPT='%n in ${PWD/#$HOME/~} %1v/%F{red}%2v%f/%3v > '
There are some notes about psvar in this answer: https://stackoverflow.com/a/64094551/9307265.
The (s) and (j) parameter expansion flags are documented in the zshexpn man page.
Please let me know if there are any issues.
My expect script connects to several remote servers successfully and echos commands, but I can't manage to have it echo an item from a list.
For example, when sshing to server1 I'd like to output to terminal fruit:apple
But apple is saved in expect while the send sends it to a local terminal where the list is not defined. Is it possible to send expect variable to bash?
In particular the lines relevant to this from the code:
set counter 0
set types {apple orange}
set var $types($counter)
send -- "echo 'fruit:$var'\r"
set $counter [expr $counter+1]
Full code:
#!/usr/bin/expect -f
# ./sshlogin.exp uptime
#declare hosts array"
set hosts {server1 server2}
set types {apple orange}
# setting credentials
set user jack
set password welcome
set counter 0
foreach vm $hosts {
set var $types($counter)
set timeout -1
# now ssh
spawn ssh $user#$vm -o StrictHostKeyChecking=no
match_max 100000 # Look for passwod prompt
expect "*?assword:*"
# Send password aka $password
send -- "$password\r"
# send blank line (\r) to make sure we get back to gui
expect "$ "
send -- "echo 'fruit:$var'\r"
expect "$ "
send -- "exit\r"
set $counter [expr $counter+1]
expect eof }
This is wrong
set counter 0
set types {apple orange}
set var $types($counter)
Tcl has lists which are numerically indexed arrays, and arrays which are associative arrays (hashes).
You access elements of a list with, typically, the lindex command.
You access elements of an array with the $arrname($key) syntax
To address the immediate problem with those 3 lines: you want
set var [lindex $types $counter]
Your answer is the perfect way to iterate over 2 lists, pulling out elements with the same numeric index.
Running through the Tcl tutorial would be beneficial.
Added the second list to the foreach loop, and since both are of the same length it works great.
foreach looks like this now:
foreach vm $hosts fruit $types {....
This link contains an example:
http://wiki.tcl.tk/1018
i am trying to execute an iMacro script using a VBS script. I am using play() method. but it seems play() doesn't support the loop functionality. I searched through the iMacros wiki and Google and unable to find an answer.
Here is the code
Set iim1 = CreateObject ("IMacros")
i = iim1.iimInit()
i = iim1.iimPlay("amazon_search")
i = iim1.iimExit()
Can anyone help? Thanks in advance.
//Scripts by Talon
var nameoffile = "my100.csv"
var numberOfUrls = 101
for(var i=1;i<numberOfUrls;i++){
//sets basic requirements
//do what you want here
var macro = "CODE: "
macro+= "SET !ERRORIGNORE YES"+"\n"
macro+= "SET !REPLAYSPEED fast"+"\n"
macro+= "SET !TIMEOUT_STEP 1"+"\n"
macro+= "SET !DATASOURCE "+nameoffile+"\n"
macro+= "SET !LOOP "+i+"\n"
macro+= "SET !DATASOURCE_LINE {{!LOOP}}"+"\n"
macro+= "URL GOTO={{!COL1}}"+"\n"
//Add what you want to do at each site here if using macro format
iimPlay(macro)
Or add your new iimPlay code here , or add more jscript
}
The above code uses jscript to call imacros script, in this example I'm first calling a file named my100.csv. my 100 has 100 urls, or website that I go to to pull different information, or to set different information.
the numberOfUrls variable tells my code how many times to run my code.
I then dimension the variable "macro" and build the imacros script, one line at a time, setting the predefined builtin variables how I want them.
Once everything is set I call my first url, and manipulate the data how I want.
NOTE: you do not have to use Urls in you .csv file, you could place your data in the .csv file and go to a site them run your information whatever way you want.
I need to get the entire (visible) contents of a folder and its subfolders as a list. Is this possible?
see how easy this can be
tell application "Finder"
set file_list to entire contents of (choose folder with prompt "Please select directory.")
end tell
if you want a list of file names then you could do this
tell application "Finder"
set file_list to name of every file of entire contents of (choose folder with prompt "Please select directory.")
end tell
Yes, entire contents does exactly what you say -- but it easily chokes on
large folders, and takes forever. It's OK for
small things, like extracting all the files of one kind out of a folder you
know will only contain a small number of files.
The recursive method also works well -- but it's using "list folder", and
the dictionary listing for it says it's deprecated and we shouldn't use it
any more.
I'm sure there is a shell command that can do this faster, but here is one way in pure Applescript that gives you total control over formatting what info you would like displayed.
property kFileList : {}
tell application "Finder"
set source_folder to choose folder with prompt "Please select directory."
my createList(source_folder)
end tell
on createList(item_list)
set the the_items to list folder item_list without invisibles
set item_list to item_list as string
repeat with i from 1 to number of items in the the_items
set the_item to item i of the the_items
set the_item to (item_list & the_item) as alias
set this_info to info for the_item
set file_name to name of this_info
set end of kFileList to file_name
if folder of this_info is true then
my createList(the_item)
end if
end repeat
end createList
On a side note, there are also a number file listing applications that can do this faster than Applescript.
UPDATE: As a result of this discussion, here is the function again, but this time using the updated API. This could probably could use some cleaning up, but it works cataloging my Desktop handily enough (and that's a deep, deep folder for me):
property kFileList : {}
tell application "Finder"
set source_folder to choose folder with prompt "Please select directory."
my createList(source_folder)
end tell
return kFileList
on createList(mSource_folder)
set item_list to ""
tell application "System Events"
set item_list to get the name of every disk item of mSource_folder
end tell
set item_count to (get count of items in item_list)
repeat with i from 1 to item_count
set the_properties to ""
set the_item to item i of the item_list
set the_item to ((mSource_folder & the_item) as string) as alias
tell application "System Events"
set file_info to get info for the_item
end tell
if visible of file_info is true then
set file_name to displayed name of file_info
set end of kFileList to file_name
if folder of file_info is true then
my createList(the_item)
end if
end if
end repeat
end createList
Wow this is quite late but I checked and it works.
tell application "Finder" to set folder_root to (choose folder with prompt "Please select directory.")
set fl to {}
dump_folder(folder_root)
on dump_folder(f)
global fl
tell application "System Events" to set end of fl to (get the POSIX path of f)
tell application "Finder" to set nfl to (the items of the contents of f)
repeat with nf in nfl
dump_folder(nf as alias)
end repeat
end dump_folder
fl