emacs ff-find-other-file does not find my header - emacs

Somehow I can't make emacs' ff-find-other-file to get my header file. Here is what I have (minimal example):
cd ~/tmp
mkdir test
cd test
mkdir -p src/a/b inc/a/b
echo "aaaa" > src/a/b/a.cpp
echo "bbbb" > inc/a/b/a.hpp
tree
gives:
.
├── inc
│   └── a
│   └── b
│   └── a.hpp
└── src
└── a
└── b
└── a.cpp
This is similar to my project structure.
emacs -Q src/a/b/a.cpp
Then copying this in *scratch* and executing it with C-x C-e:
(setq cc-search-directories '("." "../inc" "../inc/*" "../../inc/*" "../../../inc/*" "/usr/include"))
and running ff-find-other-file in buffer a.cpp, only results in a prompt in the minibuffer:
Find or create a.hpp in: ~/tmp/test/src/a/b/
C-h v on ff-search-directories returns cc-search-directories, and on cc-search-directories I get the list above.
I expect ff-find-other-file to look in ../../../inc/*, and find a.hpp. Why doesn't it?
Edit: it seems to be the recursive part that doesn't work here.
After:
cp inc/a/b/a.hpp inc/
a.hpp is found from a.cpp.
The help about ff-search-directories says:
The stars are not wildcards: they are searched for together with
the preceding slash. The star represents all the subdirectories except
`..', and each of these subdirectories will be searched in turn.
Note that this quote if from the help for ff-search-directories, while the list I modified is cc-search-directories. I can't see why that would make a difference though.
This and other threads on SO made me believe * would recursively search the directory tree. Wrong?

* represents every immediate sub-directory of its parent; nothing more.
The commentary has it worded slightly more clearly:
The star is not a general wildcard character: it just indicates that the subdirectories of this directory must each be searched in turn.
i.e. For this specific example I would expect "../../../inc/*/b" to work. Or indeed "../../../inc/*/*" (as you've ended up using).
See also https://stackoverflow.com/a/23662870/324105 and note in particular that you can define functions to dynamically generate the target file path(s).
I suspect you want the a/b to be determined based on the original path, so a function to return the appropriate path to the other file would be your best solution here.

Another options is to use Projectile and execute the projectile-find-other-file command. Since projectile knows about your project structure, it will match your cpp/h files automatically. It is a little slower than ff-find-other-file, but it seems to do the job pretty well.

Oh, the search turns out not to be recursive after all. These other questions and answers here made me misread the help (quoted in the question).
"Each of these subdirectories will be searched in turn", does not imply that their subdirectories also will be searched.
Since the depth of my tree is limited, I just modified my cc-search-directories:
(setq cc-search-directories '("."
"../inc" "../inc/*" "../../inc/*" "../../../inc/*"
"../../inc/*/*" "../../../inc/*/*/*"
"../src" "../src/*" "../../src/*" "../../../src/*"
"../../src/*/*" "../../../src/*/*/*"
"/usr/include" "/usr/local/include/*"))

Related

How to only include some directories in ctags?

there is an --exclude option but that to exclude the directories/files. I work on a big project and want to only include the directories that has source code and not build stuff.
How to do that? What should I include in my .ctags file?
I use:
find FILES | ctags -L -
where FILES is the appropriate arguments to make find return only the files I want to index.
Exuberant Ctags (5.8) is now old and unmaintained, though. It still works for me, so I've not switched; but the last time I checked "Universal Ctags" appeared to be the way forwards, so I would suggest starting there:
https://ctags.io
https://github.com/universal-ctags/ctags
n.b. I experienced a curious bug with Exuberant Ctags 5.8 whereby find . resulted in some corrupted tag entries, but find * did not; so you might want to use the latter if using this approach. I didn't need to index any dot files at the root level, so I'm not sure offhand what happens for .* -- I don't think I tried it. Absolute paths were also fine, but then the TAGS file isn't portable. Potentially not an issue in the newer fork.

Emacs and cscope with multiple directories

How do I set up cscope in Emacs when my source code lives in multiple directories?
Say I have several paths for my C++ project:
/path/to/my/code (and subdirectories)
/path/to/other/code (and subdirectories)
/path/to/static/linking/include/files (and subdirectories)
/path/to/static/linking/lib/files' (and subdirectories)
I would like to use xcscope to navigate/look up symbols in my code and the library that I am linking to.
The instructions for xcscope.el say that I should first run C-c s (Cscope->Create list and index) at /path/to/my/code, but I am then confused about how I to have the other paths indexed by cscope.
The documentation says I should go to the other directories and run cscope -b, but what I am supposed to do after that?
I looked at the cscope.files file that C-c s built. I think I am supposed to add my other paths to this file, but this file includes a list of source code files (not directories).
Do I have to manually edit cscope.files to add every single file that I want to index that is outside of my project's root directory?
The documentation is confusing.
I got one sol'n from http://cscope.sourceforge.net/large_projects.html. Still confusing.
cscope.files is aptly named. It is NOT directories. It is files, only files. Which is as daunting as it sounds. What if you have hundreds of files. Then you have to write hundreds of lines, one per file, into cscope.files. No joke.
Automate it with some scripting. E.g., on linux, use bash scripts and redirection (>,>>,|) operators to select and filter files from any and all directories into that cscope.files.
What about the directory where cscope.files resides? IF you don't include those files, it'll only find them when you open your project (in emacs, but probably applicable to any IDE) in that source directory. So, include them, too, for easy opening of your project from anywhere.
The option "recursive/-R" seems obvious to send to cscope-indexer. Nope, not with many root directories. Does nothing (probably could do something with scripts or elisp or who knows). Just feed those files, absolute path, into cscope.files. And you might have to make sure you have only one cscope.files per project. Don't split them up relative to each diretory. Or maybe you can, something to look into.
Remember, include the /path/to/each/file/ before the file if you want cscope.files to point to it from anywhere. cscope isn't "smart", it's dumb, it just takes directions for where to look and it won't know where to look for "filename", without knowing where it is. You're just asking it to call locate filename, which it can't do anyway, when you give it a lonely filename without a dir path outside of the directory that a particular cscope.files resides.
I hope there's a way to use xcscope inside emacs, just adding directories which it will catalog and index, as the xcscope docs and emacs menu suggest. But I didn't succeed in making it work that way.
Wouldn't a soft link (ln -s) work? Worked for me.

Issue with doxygen .dox files

I am trying to run doxygen on some source files for a project that I downloaded source files for. The files are located in the following directories:
doc/ - Documentation files, such as .dox files.
src/ - Source files
My settings in my doxygen.config file are:
INPUT = ../ .
FILE_PATTERNS = *.h *.dox *.dxx
When I run doxygen (doxygen doxygen.config), it generates all of the documentation from the .h files correctly, but it does not generate the mainpage correctly. I have a file titled intro.dox in the doc folder, with a command \mainpage Documentation Index, and a bunch of text, but doxygen is not using this to generate the main page.
What am I doing wrong?
There are (at least) two possible reasons for this:
You are not including the /doc directory in you INPUT list. Try modifying this to
INPUT = ../ . ../doc
Did you mean to write ../doc instead of ../? I am guessing that your doxygen.config file is in your src directory. If this is not the case can you make this clear in the question.
Doxygen requires that your documentation files (your .dox files) are plain text with your text wrapped with Doxygen C++ comments (i.e. /** ... */).
Without knowing where doxygen.config is located, and since you are using relative paths in INPUT, it is difficult to determine what might cause this, however since the files you are looking for are in parallel directories, it is possible that doxygen is not search recursively for your files. You may want to confirm that RECURSIVE is set to YES in doxygen.config.

How to search a text among c files under a directory

I've looked through several similar questions, but either I didn't understand their answer or my question is different than theirs. So, I have a project contains many subdirecties and different type of files. I would like to search a function name among those .C files only.
Some information on the web suggest to use "Esc x dired-do-query-replace-regexp". However, this will search not just C files, but also other file like .elf which isn't helpfule in my case. Other people sugget to use TAG function, but it will require me to type "etags *.c" for every subdirectory which is also impossible.
How should I do this while working on those large scale software project?
Thanks
Lee
Use ack-grep on linux
ack-grep "keyword" -G *.c
My favorite: igrep-find, found in the package igrep.el. Usage is:
M-x igrep-find some_thing RET *.C
There's the built in grep-find, docs here, but I find it awkward to use.
For a more general answer, see this similar question: Using Emacs For Big Big Projects.
if you're on linux, you can use grep to find files with a certain text in them. you would then do this outside of emacs, in your shell/command prompt. here's a nice syntax:
grep --color=auto --include=*.c -iRnH 'string to search for' /dir/to/search/
the directory to search can be specified relative, so if you're in the directory you want to use as the root directory for your recursive search, you can just skip the whole directory address and specify a single dot.
grep --color=auto --include=*.c -iRnH 'string to search for' .
the part --color=auto makes some text highlighted. --include=*.c is the part that specifies what files to search. in this case, only files with the c-extension. the flag i makes stuff case insensitive, the flag R makes the search recursive, the flag n adds the line number to the report, and the flag H adds the file path to the report.
To breed find and grep there is find-grep function, there you can change the invocation string to find . -name *.c etc. Make it a function, if You like. Then You use eg. C-x` et al. to navigate the results.
To search among the files in one directory i use lgrep, it prompts you in which files to search.
You can use cscope and xcscope.el : http://www.emacswiki.org/emacs/CScopeAndEmacs
Try with dired: place the cursor on the directory name to search, type A and in the minibuffer the text to find.

Difference in the paths in .gitignore file?

I've been using git but still having confusion about the .gitignore file paths.
So, what is the difference between the following two paths in .gitignore file?
tmp/*
public/documents/**/*
I can understand that tmp/* will ignore all the files and folders inside it. Am I right?
But what does that second line path mean?
This depends on the behavior of your shell. Git doesn't do any work to determine how to expand these. In general, * matches any single file or folder:
/a/*/z
matches /a/b/z
matches /a/c/z
doesn't match /a/b/c/z
** matches any string of folders:
/a/**/z
matches /a/b/z
matches /a/b/c/z
matches /a/b/c/d/e/f/g/h/i/z
doesn't match /a/b/c/z/d.pr0n
Combine ** with * to match files in an entire folder tree:
/a/**/z/*.pr0n
matches /a/b/c/z/d.pr0n
matches /a/b/z/foo.pr0n
doesn't match /a/b/z/bar.txt
Update (08-Mar-2016)
Today, I am unable to find a machine where ** does not work as claimed. That includes OSX-10.11.3 (El Capitan) and Ubuntu-14.04.1 (Trusty). Possibly git-ignore as been updated, or possibly recent fnmatch handles ** as people expect. So the accepted answer now seems to be correct in practice.
Original post
The ** has no special meaning in git. It is a feature of bash >= 4.0, via
shopt -s globstar
But git does not use bash. To see what git actually does, you can experiment with git add -nv and files in several levels of sub-directories.
For the OP, I've tried every combination I can think of for the .gitignore file, and nothing works any better than this:
public/documents/
The following does not do what everyone seems to think:
public/documents/**/*.obj
I cannot get that to work no matter what I try, but at least that is consistent with the git docs. I suspect that when people add that to .gitignore, it works by accident, only because their .obj files are precisely one sub-directory deep. They probably copied the double-asterisk from a bash script. But perhaps there are systems where fnmatch(3) can handle the double-asterisk as bash can.
If you're using a shell such as Bash 4, then ** is essentially a recursive version of *, which will match any number of subdirectories.
This makes more sense if you add a file extension to your examples. To match log files immediately inside tmp, you would type:
/tmp/*.log
To match log files anywhere in any subdirectory of tmp, you would type:
/tmp/**/*.log
But testing with git version 1.6.0.4 and bash version 3.2.17(1)-release, it appears that git does not support ** globs at all. The most recent man page for gitignore doesn't mention **, either, so this is either (1) very new, (2) unsupported, or (3) somehow dependent on your system's implementation of globbing.
Also, there's something subtle going on in your examples. This expression:
tmp/*
...actually means "ignore any file inside a tmp directory, anywhere in the source tree, but don't ignore the tmp directories themselves". Under normal circumstances, you'd probably just write:
/tmp
...which would ignore a single top-level tmp directory. If you do need to keep the tmp directories around, while ignoring their contents, you should place an empty .gitignore file in each tmp directory to make sure that git actually creates the directory.
Note that the '**', when combined with a sub-directory (**/bar), must have changed from its default behavior, since the release note for git1.8.2 now mentions:
The patterns in .gitignore and .gitattributes files can have **/, as a pattern that matches 0 or more levels of subdirectory.
E.g. "foo/**/bar" matches "bar" in "foo" itself or in a subdirectory of "foo".
See commit 4c251e5cb5c245ee3bb98c7cedbe944df93e45f4:
"foo/**/bar" matches "foo/x/bar", "foo/x/y/bar"... but not "foo/bar".
We make a special case, when foo/**/ is detected (and "foo/" part is already matched), try matching "bar" with the rest of the string.
"Match one or more directories" semantics can be easily achieved using "foo/*/**/bar".
This also makes "**/foo" match "foo" in addition to "x/foo", "x/y/foo"..
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds#gmail.com>
Simon Buchan also commented:
current docs (.gitignore man page) are pretty clear that no subdirectory is needed, x/** matches all files under (possibly empty) x
The .gitignore man page does mention:
A trailing "/**" matches everything inside. For example, "abc/**" matches all files inside directory "abc", relative to the location of the .gitignore file, with infinite depth.
A slash followed by two consecutive asterisks then a slash matches zero or more directories. For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on.
When ** isn't supported, the "/" is essentially a terminating character for the wildcard, so when you have something like:
public/documents/**/*
it is essentially looking for two wildcard items in between the slashes and does not pick up the slashes themselves. Consequently, this would be the same as:
public/documents/*/*
It doesn't work for me but you could create a new .gitignore in that subdirectory:
tmp/**/*.log
can be replaced by a .gitignore in tmp:
*.log