Can ack be coerced into searching a complicated project - makefile

ack is a great tool for searching, especially if everything you want to find is in nested directories below a top project dir.
I'd like to search a number of different directory trees, in order to search my whole project.
I could do something like this (there are 5 or 6 more directories I'd include):
ack sometext . ../../Libraries/CMSIS/Device/ST/STM32F4xx/ ../../Libraries/CMSIS/
I've also tried doing it via the makefile, where I'd make ack a phony target, invoking ack on the directories Makefile knows about. This works, but the syntax to invoke it is unfortunate:
gmake ack SVAL=sometext
where in the Makefile:
ack:
$(ACK) $(SVAL) $(LIB_DIRS) $(DEVICE_DIRS) $(OTHER_PROJECT_DIRS)
Ideally, there would be something I could embed in the .ackrc to define the directories that ack searches. Anyone have a favorite way to use ack to search a complicated project directory structure?

Since ack can do what I want, with a complicated command line. My best answer to date is to embed it in a bash script, so I would type:
./pack foobar
To search my entire project for foobar.
The script pack would look like this:
#!/bin/bash
CONTEXT=-C1
c:/bin/ack $CONTEXT $* . ../../Libraries/CMSIS/Device/ST/STM32F4xx/ \
../../Libraries/CMSIS/
Still would prefer a .ackrc solution.

Sack: wrapper for grep, ack and/or ag (silver searcher)
http://sampsonchen.com/sack/
Can switch your `search environment' using pre-set profiles, sets up the CL flags and preset target (MULTIPLE) top-level starting-point directorieS

Related

Print all ongoing targets in Makefile

I have written a makefile which has pretty complicated dependency, and executes with multiple jobs in parallel (make -j100 for example). I am trying to find a way to print all the current running target names. Any idea? Thanks in advance.
If what you want is a kind of command that you can run from time to time while make is running, and that shows all currently executing recipes, you could slightly modify your recipes such that they first create a temporary file with the name of the target, do whatever they are supposed to do and delete the temporary file. Listing these temporary files anytime will then show you the currently executing recipes.
Example if all targets are located under the directory from which make is called (or sub-directories of it):
TAGSDIR := .tags
MKTAG = mkdir -p "$(TAGSDIR)/$(#D)" && touch "$(TAGSDIR)/$#"
RMTAG = rm -f "$(TAGSDIR)/$#"
<target>: <prerequisites>
#$(MKTAG)
<regular recipe>
#$(RMTAG)
And list all files under .tags to get the names of all currently running recipes. Example with find:
find .tags -type f -printf '%P\n'
You could even encapsulate this in an infinite loop and refresh the list e.g. every second:
while true; do clear; find -type f -printf '%P\n'; sleep 1; done
EDIT
Andreas noticed that this works only if the targets are all located under the directory from which make is called. If a target is ../foobar, for instance, the temporary tag file would be .tags/../foobar, which is not what we want.
Andreas suggests to substitute .. with \.\. and / with \/. We could maybe find a way to do something like this under GNU/Linux and macOS (but not exactly, you cannot have a slash in a file name) but there could still be other issues under Windows (C:, backslashes...).
We could also store the name of the target in a text file and use mktemp or an equivalent to generate the text file with a unique name. But we would then need a way to propagate this unique name from MKTAG to RMTAG. This is doable with a shell variable and a one-line recipe (or the .ONESHELL special target) but not very nice.
As you use GNU make we could also use abspath and create temporary files named $(TAGSDIR)/$(abspath $#) but I do not know what abspath does under Windows with drive letters, nor do I know if you can name a file something\c:\something under Windows...
So, if your targets are not all located under the directory from which make is called, the best is to use another solution.

How to remove a reoccuring word/character and what comes after, from the filenames of multiple files?

I have several folders of video files where, due to the download manager I use, they are all named in the following format "FILENAME.mp4; filename= FILENAME.mp4" All I've been trying to do is to remove everything after (and including) ".mp4; filename". However, I haven't found a way to do this.
I have tried some free software (such as Renamer, Namechanger, Name Munger for Mac, Transnomino) but I failed to do what I need to.
I'm working on Mac OSX 10.13.6.
Any help with this issue would be appreciated.
You can achieve it using Terminal. Go to the folder where you want to rename files using this cd command, for example:
cd ~/Documents/Videos
And run this command to rename all files recursively:
find . -iname "*.mp4;*" | sed -E 's/(\.[^\.]*)(\.mp4)(.*)/mv "\1\2\3" "\1\2"/' | sh
This command will keep only FILENAME.mp4 part from FILENAME.mp4; filename= FILENAME.mp4 file name
I used to extensively use a windows Rename tool called Renamer 6.0, and it had a "pattern rename" facility called "Multi change" that could have handled this.
In the context of that tool it would be asking for a source pattern like %a= %b and a destination pattern (like %b), everything after the = would be stored in %b variable and then renaming the file to just %b would lose everything after the =
See if your preferred rename tool has a similar facility?
If your tool supports regex, then find: .*?=(.*) and replace with $1
I'm also minded that asking this question on https://unix.stackexchange.com/ might elicit some help crafting a shell script that will perform this rename (though also plenty of shell capable people here, one of them may see it - it's just that it's not quite as hardcore programmer-y a question as most).
If you're willing to learn/use java, then that could be another good way to get the problem solved. It would (at a guess) look something like this:
for (final File f : new File("C:\\temp").listFiles()) {
if (f.isFile()) {
string n = f.getName();
if (n.contains("=")) {
f.renameTo(new File(n.substring(n.indexOf("=")+1));
}
}
}

Shell script to verify data packages

I need to make shell script to check my algorithms with loads of data(tests packages saved in .in files, every package contains folder with .in file and the other one with .out file where supposed to be correct result)
Sometimes It's about 1000 files in one packages so there's no point of doing it manually. I need some kind of loop which opens this .in file then redirect input of my c++ program and also redirect output of this program(save result to .out files) But the point is I can't get this language as quick as I need.
And I would like this script to compare results of my algorithm to .out files from packages
for f in ExternalIn/*.in; do//part of code which opens process with my algorithm and compare its .out file to .out file from package
Skipping checks for missing files, whitespace-safety, etc., you probably need something like:
for f in ExternalIn/*.in; do
# diff the result of my_cpp_app eating file.in with file.out
# and store the comparison result in file.diff
diff ${f/.in/.out} <(my_cpp_app <$f 2>/dev/null) > ${f/.in/.diff}
done
Although I would probably do it with find / xargs pipeline which is not only safer but also allows parallel execution.
Or even write a Makefile for this and use make, which after all is a tool for exactly this kind of work.

Organizing asset files in a Go project

I have a project that contains a folder to manage file templates, but it doesn't look like Go provides any support for non-Go-code project files. The project itself compiles to an executable, but it needs to know where this template folder is in order to operate correctly. Right now I do a search for $GOPATH/src/<templates>/templates, but this feels like kind of a hack to me because it would break if I decided to rename the package or host it somewhere else.
I've done some searching and it looks like a number of people are interested in being able to "compile" the asset files by embedding them in the final binary, but I'm not sure how I feel about this approach.
Any ideas?
Either pick a path (or a list of paths) that users are expected to put the supporting data in (/usr/local/share/myapp, ...) or just compile it into the binary.
It depends on how you are planning to distribute the program. As a package? With an installer?
Most of my programs I enjoy just having a single file to deploy and I just have a few templates to include, so I do that.
I have an example using go-bindata where I build the html template with a Makefile, but if I build with the 'devel' flag it will read the file at runtime instead to make development easier.
I can think of two options, use a cwd flag, or infer from cwd and arg 0:
-cwd path/to/assets
path/to/exe -cwd=$(path/to/exe/assets)
Internally, the exectable would chdir to wherever cwd points to, and then it can use relative paths throughout the application. This has the added benefit that the user can change the assets without having to recompile the program.
I do this for config files. Basically the order goes:
process cmd arguments, looking for a -cwd variable (it defaults to empty)
chdir to -cwd
parse config file
reparse cmd arguments, overwriting the settings in the config file
I'm not sure how many arguments your app has, but I've found this to be very useful, especially since Go doesn't have a standard packaging tool that will compile these assets in.
infer from arg 0
Another option is to use the first argument and get the path to the executable. Something like this:
here := path.Dir(os.Args[0])
if !path.IsAbs(os.Args[0]) {
here = path.Join(os.Getwd(), here)
}
This will get you the path to where the executable is. If you're guaranteed the user won't move this without moving the rest of your assets, you can use this, but I find it much more flexible to use the above -cwd idea, because then the user can place the executable anywhere on their system and just point it to the assets.
The best option would probably be a mixture of the two. If the user doesn't supply a -cwd flag, they probably haven't moved anything, so infer from arg 0 and the cwd. The cwd flag overrides this.

Join multiple Coffeescript files into one file? (Multiple subdirectories)

I've got a bunch of .coffee files that I need to join into one file.
I have folders set up like a rails app:
/src/controller/log_controller.coffee
/src/model/log.coffee
/src/views/logs/new.coffee
Coffeescript has a command that lets you join multiple coffeescripts into one file, but it only seems to work with one directory. For example this works fine:
coffee --output app/controllers.js --join --compile src/controllers/*.coffee
But I need to be able to include a bunch of subdirectories kind of like this non-working command:
coffee --output app/all.js --join --compile src/*/*.coffee
Is there a way to do this? Is there a UNIXy way to pass in a list of all the files in the subdirectories?
I'm using terminal in OSX.
They all have to be joined in one file because otherwise each separate file gets compiled & wrapped with this:
(function() { }).call(this);
Which breaks the scope of some function calls.
From the CoffeeScript documentation:
-j, --join [FILE] : Before compiling, concatenate all scripts together in the order they were passed, and write them into the specified file. Useful for building large projects.
So, you can achieve your goal at the command line (I use bash) like this:
coffee -cj path/to/compiled/file.js file1 file2 file3 file4
where file1 - fileN are the paths to the coffeescript files you want to compile.
You could write a shell script or Rake task to combine them together first, then compile. Something like:
find . -type f -name '*.coffee' -print0 | xargs -0 cat > output.coffee
Then compile output.coffee
Adjust the paths to your needs. Also make sure that the output.coffee file is not in the same path you're searching with find or you will get into an infinite loop.
http://man.cx/find |
http://www.rubyrake.org/tutorial/index.html
Additionally you may be interested in these other posts on Stackoverflow concerning searching across directories:
How to count lines of code including sub-directories
Bash script to find a file in directory tree and append it to another file
Unix script to find all folders in the directory
I've just release an alpha release of CoffeeToaster, I think it may help you.
http://github.com/serpentem/coffee-toaster
The most easy way to use coffee command line tool.
coffee --output public --join --compile app
app is my working directory holding multiple subdirectories and public is where ~output.js file will be placed. Easy to automate this process if writing app in nodejs
This helped me (-o output directory, -j join to project.js, -cw compile and watch coffeescript directory in full depth):
coffee -o web/js -j project.js -cw coffeescript
Use cake to compile them all in one (or more) resulting .js file(s). Cakefile is used as configuration which controls in which order your coffee scripts are compiled - quite handy with bigger projects.
Cake is quite easy to install and setup, invoking cake from vim while you are editing your project is then simply
:!cake build
and you can refresh your browser and see results.
As I'm also busy to learn the best way of structuring the files and use coffeescript in combination with backbone and cake, I have created a small project on github to keep it as a reference for myself, maybe it will help you too around cake and some basic things. All compiled files are in www folder so that you can open them in your browser and all source files (except for cake configuration) are in src folder. In this example, all .coffee files are compiled and combined in one output .js file which is then included in html.
Alternatively, you could use the --bare flag, compile to JavaScript, and then perhaps wrap the JS if necessary. But this would likely create problems; for instance, if you have one file with the code
i = 0
foo = -> i++
...
foo()
then there's only one var i declaration in the resulting JavaScript, and i will be incremented. But if you moved the foo function declaration to another CoffeeScript file, then its i would live in the foo scope, and the outer i would be unaffected.
So concatenating the CoffeeScript is a wiser solution, but there's still potential for confusion there; the order in which you concatenate your code is almost certainly going to matter. I strongly recommend modularizing your code instead.

Resources