Can you make valid Makefiles without tab characters? - makefile

target: dependencies
command1
command2
On my system (Mac OS X), make seems to require that that Makefiles have a tab character preceding the the content of each command line, or it throws a syntax error.
This is an annoyance when creating or editing Makefiles because I have my editor set up to be all-spaces-all-the-time.
Can you make valid Makefiles without tab characters?

This is a syntax oddity/requirement of make, it has nothing to do with Mac OS X. Unfortunately, there's nothing you can do about it if you are going to use make.
Edit: GNU Make now supports a custom recipe prefix. See this answer.
You are not the first one to dislike this aspect of make. To quote Unix Haters' Handbook:
The problem with Dennis’s Makefile is that when he added the comment line, he inadvertently inserted a space before the tab character at the beginning of line 2. The tab character is a very important part of the syntax of Makefiles. All command lines (the lines beginning with cc in our example) must start with tabs. After he made his change, line 2 didn’t, hence the error.
“So what?” you ask, “What’s wrong with that?”
There is nothing wrong with it, by itself. It’s just that when you consider how other programming tools work in Unix, using tabs as part of the syntax is like one of those pungee stick traps in The Green Berets: the poor kid from Kansas is walking point in front of John Wayne and doesn’t see the trip wire. After all, there are no trip wires to watch out for in Kansas corn fields. WHAM!

In the time since this question was originally asked, a version of GNU Make has been released that allows you to use something other than Tab as the prefix character. From the mailing list announcement:
New special variable: .RECIPEPREFIX allows you to reset the recipe
introduction character from the default (TAB) to something else. The
first character of this variable value is the new recipe introduction
character. If the variable is set to the empty string, TAB is used again.
It can be set and reset at will; recipes will use the value active when
they were first parsed. To detect this feature check the value of $(.RECIPEPREFIX).
This feature was added in GNU Make 3.82, released in July 2010 (six months after this question's original ask date). Since it has in turn been three years and change since that, it's likely that other Make flavors have followed GNU Make.

There is a convoluted way of have a valid makefile without tabs.
If you change your makefile to read:
target: dependencies; command1; command2
If will work. If you want it on more than one line, then you can do:
target: dependencies; \
command1; \
command2
Messy, but it works.

If you have a vimrc in your profile you can add this line to prevent vim from changing to spaces:
autocmd FileType make setlocal noexpandtab
I too was struggling with this, and this fixed it for me. Spread the good word!

This does it for me if you would like to use spaces
.RECIPEPREFIX +=
Example

If you are using EditorConfig, you can add the following lines to your .editorconfig file to force your IDE to use tab for indentation instead of spaces in Makefile:
[Makefile]
indent_style = tab

In vim's insert mode, one can use Ctrl-v <TAB> to insert a literal tab, even if you have set the tab key to insert spaces. This doesn't answer your question, of course, but might be an alternative to the methods available to avoid needing literal tabs.

Until GNU Make 4.2
Steven Penny's answer works.
.RECIPEPREFIX +=
The reason why this works is described in my comment.
Since GNU Make 4.3 (released on 19 Jan 2020)
Behavior of += operator has been changed in a backward-incompatible way. If the left operand has an empty value, a space is no longer added.
You can instead use
.RECIPEPREFIX := $(.RECIPEPREFIX)<space>
, where <space> is a single space. Although $(.RECIPEPREFIX) is expanded as an empty value, this is needed not to let GNU Make ignore <space>. Note this code works even on GNU Make older than version 4.3.

in ubuntu: vi Makefiles
replace space by tab (or anything else you want):
:%s/<space chars>/^I/g
For ex replace 8 spaces by tab:
:%s/ /^I/g
Be attention: ^I insert with tab key, not ^ and I characters :D

Not portably. Certain flavours of make absolutely require tab characters. Yet another reason for preferring tabs over spaces :-)

Related

Weird wrapping of bash prompt with coloring (`\[` and `\]` being used)

I was working on my own bash prompt when hit strange behaviour (both iTerm and Terminal.app on macos). I managed to boil it down to the minimum working example:
~/.bash_profile:
WHITE="\[\033[1;37m\]"
COLOR_NONE="\[\033[0m\]"
# This always wraps correctly
PS1="\u:\w"
# This (added coloring) wraps incorrectly when using small window.
# PS1="${WHITE}\u:\w${COLOR_NONE}"
Now create a long directory name say
mkdir ~/very_long_name_very_long_name_very_long_name_very_long_name_very_long_name_very_long_name_very_long_name_very_long_name_very_long_name_very_long_name_very_long_name_very_long_name_very_long_name_very_long_name_very_long_name_very_long_name_very_long_name
and cd to it. Problem is: with the first version of the PS1 it wraps perfectly, while adding just one color breaks wrapping for small windows. Can anybody clarify of give a workaround? Adding \n to the end is an option, but looks ugly for short prompts.
Thanks!
Sources I have already seen:
BashFAQ/053 about colors
SO question about \[ and \]
Issue with \x01 and \x02
UPD:
bash version version 3.2.57(1)-release (x86_64-apple-darwin17)
Bash has always had trouble handling long prompts with invisible characters, so the usual practice is to avoid them. For example, you could automatically trim the length of the prompt by omitting the beginning of the path if it is too long, or you could automatically output a trailing newline if the path is very long. (In such cases, you might want to use $COLUMNS, which will normally tell you the width of the window.)
In patch 19 to bash v4.4 (which I realise is not really relevant to your environment since you seem to still be using the antique version of bash provided by a default OS X install), a long-standing bug was corrected, which had the effect of triggering a segfault in certain very rare cases of multiline prompts with both invisible and multibyte characters. The behaviour definitely changed between v4.4.18 and v4.4.19, but even with that patch very long prompts cause problems when the prompt extends to a third line.
There is a comment in lib/readline/display.c which indicates that the readline library assumes that prompts will not exceed two lines. I suggest that you use that as a limit.

Searching for a character in the bash prompt

In vim, to find a character you can use 'f' to find the next matching character in the line that your cursor is on, and 'F' to find the previous matching character in the line that your cursor is on.
Is there a way to move around like that on the bash command line?
I know that you can set bash to be in vim mode, by saying set -o vim, and this works great for my local machine, but I administer a lot of machines where I can't change that setting.
Ignoring for a moment the security issues associated with everybody in your office sharing the same user, you could add a key binding to the readline command character-search:
# ~/.inputrc
C-]: character-search
To use the search, type Ctrl-] followed by the character you want to search for. You can bind the command to any key sequence, not just Ctrl-], but for obvious reasons you probably don't want to emulate vi mode by binding it to the letter f.
This would be less invasive than turning on vi mode so most users would probably not even notice the change. However, somebody could easily stumble upon your key sequence by accident and become very confused. You would also have to use three keystrokes instead of the two you're accustomed to with vi.

What are these shell escape characters?

I'm trying out the coffee script repl inside Emacs (under ArchLinux) and I'm seeing these escape characters surrounding the prompt:
[1Gcoffee> [0K[9G
These shouldn't be colors as I already enabled the ansi-color-for-comint-mode. So does anyone recognize these?
P.S.: Funny thing is I don't have this issue under my Emacs+Cygwin setup!
I don't know where they're coming from (something to do with your shell prompt, obviously, but it's hard to say more than that).
I read them as:
ESC[1G - Move to column 1 (Cursor Character Absolute)
ESC[0K - Erase to right
ESC[9G - Move to column 9
It looks like an attempt by the shell to ensure that the prompt is at the far left of an empty line. Not sure what shell you have, but zsh does something similar when the PROMPT_SP option is enabled. I don't think it uses the above sequences, though.
Many, many, control sequences can be found here. Note that the sequence "ESC[" is interpreted as a "Control Sequence Introducer" (CSI) and is shown as that on that page.
I had the same problem and was able to solve it by adding
export NODE_NO_READLINE=1
to my .bashrc file.
So, the characters appear to have come from the CoffeeScript REPL's use of Readline. Perhaps the reason you didn't have the issue in Cygwin was because Readline wasn't available there.

word boundaries in irb

I'm using Terminal on Snow Leopard.
At the command line, if I've typed foo.bar.baz.bang.quuz.quux, when i tap option-B, it moves the cursor backward word by word -- stopping at every period, because it considers a period to be a word boundary. Likewise, option-F moves forward word by word.
In irb (0.9.5, ruby 1.8.7), option-B and -F also have this behavior, but the period is no longer treated as a word boundary, which makes these keyboard shortcuts significantly less useful.
How can I change this?
EDIT: Curiouser and curiouser: On an EC2 instance which has the same irb and ruby versions, the period is treated as a word boundary.
I think this has more to do with the Readline module.
The word break characters can be changed. Run this in your IRB and see what characters is Readline using:
Readline.basic_word_break_characters
Readline is part of the standard ruby library: http://ruby-doc.org/stdlib/libdoc/readline/rdoc/index.html
Could this be of relevance here?
http://jorgebernal.info/2009/11/18/fixing-snow-leopard-ruby-readline/
In any case make sure option-B/F are actually bound to forward and backward-word in your inputrc files, like John pointed out.
Also word boundaries are determined by your locale (see the "locale" command), and more specifically by LC_CTYPE (character classification). I don't think that's the problem here, but you might want to check out and compare your locale settings just in case.
Readline also uses the following configuration files:
/etc/inputrc
~/.inputrc (or a filename specified by the environment variable INPUTRC)
This can cause different behavior on different machines (but probably not between ruby versions - I guess ruby adds another layer of configuration on top).

What setting in vim counteracts smartindent's refusal to indent # comments in shell scripts?

I recently started using vim 7 (previously vim 6) and the smartindent setting. For the most part, it works well, though I'm so used to typing a tab after an open brace that it is almost counter-productive.
However, there is one piece of maniacal behaviour. When editing a shell script, I try to create a comment at the current indent level, but smartindent will have nothing to do with it. It insists that the comment must be at level 0 (no indent). What's worse, it breaks shift-right ('>>' and friends) so that they do not work. This is outright insubordination, and I'd like to know what's the best way to fix it?
(I'm also not keen on smartindent's ideas about indenting then after if.)
Preferred solutions will save me manual bashing - I'm being lazy. One option would be 'turn off smartindent when editing shell scripts (leave it on for the rest)'. Another option would be guidelines on how to find the control script for smartindent and what to edit to change the characteristics I don't like. The final option (which I don't need advice on how to do - just the hint that it is the best, or only, way to restore sanity) is to leave smartindent unset.
I saw the vaguely related question on "(PHP and) annoying vim unindent rules"; it doesn't provide me with the direct answer, though maybe the cindent and related items mentioned in there are in fact part of the answer.
Find the indent file, (e.g. /usr/share/vim/vim71/indent/sh.vim on my system)
This line looks like the problem:
setlocal indentkeys-=:,0#
Perhaps you can fix this in your .vimrc or load a custom indent file manually.
edit: It looks more complicated than I thought, but maybe there is something specifically set in the indenting file that you would need to fix.
2nd edit: Looks like I was completely wrong, Check out:
Restoring indent after typing hash
or
howto-configure-vim-to-not-put-comments-at-the-beginning-of-lines-while-editing
Well, after exploring some options, including using ':set cindent' instead of ':set smartindent', I've ended up reverting to just using ':set autoindent'. There probably are ways to make this stuff work exactly as I want it to, but it is messy enough and fiddly enough that I can't be bothered. I've worked fine with autoindent for the previous 20-odd years, and the benefits from the extra bells and whistles provided by smartindent are outweighed by the what I regard as its misbehaviour.
Thank you, Juan, for your assistance. Believe it or not, it did help - quite a lot.
I also discovered a couple of other neat commands, though, while following up on this:
>i}
>a}
These right-shift the block of code you are in. The 'i' version indents the body and not the closing braces (my preferred style), and the 'a' version indents the closing braces to (the version that is required at work).
Also, you can apply qualifiers to '%' in commands executed at the shell:
:make %:r.o
This would run make on the 'root' of the current file name (that's '%:r') followed by '.o'. Or, in other words, if I'm editing somefile.c, this executes make somefile.o.
Add the line below in your .vimrc
filetype indent on
(it will set the right indent mode depending on the filetype)
I had this same issue for a long time, until I realized that autoindent and smartindent are both unnecessary if "filetype indent on" is set in your vimrc - 'filetype indent on' uses the indent/sh.vim (or whatever language) file in your vim directory to figure out the indentation rules, and autoindent and smartindent both can interfere with it.
I haven't tested this with sh, but perl suddenly started behaving properly when I switched.
Sidenote: Juan's redirect, "Restoring indent after typing hash", is not a good solution - while it does correct the problem in one situation (typing code in), it doesn't change how the editor thinks it should be indented, so a re-indent (visual =, or normal ==) will shove it back to the left.
The previous answer suggesting:
:inoremap # X^H#
is excellent. It is the answer suggested by the VIM documentation at ":help smartindent". Note that ^H is entered using CTRL-V CTRL-H. The relevant section from the documentation is below.
When typing '#' as the first character in a new line, the indent for
that line is removed, the '#' is put in the first column. The indent
is restored for the next line. If you don't want this, use this
mapping: ":inoremap # X^H#", where ^H is entered with CTRL-V CTRL-H.
When using the ">>" command, lines starting with '#' are not shifted
right.
I have the following lines in my .vimrc and I don't observe the problem.
set smartindent
inoremap # X^H#
I used to have set autoindent after these two lines but it seems that it has no effect.
Yes that is very annoying. smartindent is really only for C like languages.
See how I enable the appropriate indenting based on language at:
http://www.pixelbeat.org/settings/.vimrc

Resources