Looking at the source code, it doesn't seem to be possible, as the definition of white-space relevant for visual-line-mode
appears to be hard-coded in the C part of the source code.
I'm not sure about my conclusions, but here is the sequence of my source archaeology (I'll be linking to github for ease of reference, though when actually carrying out the investigation I had used C-h f
, C-h v
and finally a recursive grep
of the C code.)
visual-line-mode
enables word-wrap by setting the variable word-wrap
to t
. (You can test this by just setting the variable to true, without enabling visual-line-mode
itself.)
The variable word-wrap
is defined in buffer.c:
DEFVAR_PER_BUFFER ("word-wrap", &BVAR (current_buffer, word_wrap), Qnil,
[...]
Guessing (and my terminology will be off, because I'm a horrible person who hasn't yet read all of the texinfo manual), this means that the elisp-accessible variable "word-wrap", sets the C variable word_wrap
.
Searching for where word_wrap
is used, we find:
it->line_wrap = NILP (BVAR (current_buffer, word_wrap))
? WINDOW_WRAP : WORD_WRAP;
i.e. if word_wrap
is set in the current buffer, the it->line_wrap
is set to WORD_WRAP
(A ? B : C
is a ternary operator...).
Looking further on, we get, among other things, this condition:
if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
{
if (IT_DISPLAYING_WHITESPACE (it))
may_wrap = true;
[...]
I'm eliding quite a large amount of code, which I don't really, fully understand, but it seems that unless IT_DISPLAYING_WHITESPACE (it)
then either may_wrap
will be explicitly set to false, or we'll escape the block and do something interesting elsewhere.
IT_DISPLAYING_WHITESPACE
in turn, is defined here:
#define IT_DISPLAYING_WHITESPACE(it) \
((it->what == IT_CHARACTER && (it->c == ' ' || it->c == '\t')) \
|| ((STRINGP (it->string) \
&& (SREF (it->string, IT_STRING_BYTEPOS (*it)) == ' ' \
|| SREF (it->string, IT_STRING_BYTEPOS (*it)) == '\t')) \
|| (it->s \
&& (it->s[IT_BYTEPOS (*it)] == ' ' \
|| it->s[IT_BYTEPOS (*it)] == '\t')) \
|| (IT_BYTEPOS (*it) < ZV_BYTE \
&& (*BYTE_POS_ADDR (IT_BYTEPOS (*it)) == ' ' \
|| *BYTE_POS_ADDR (IT_BYTEPOS (*it)) == '\t')))) \
suggesting that the only two recognised white-space characters are the space and the tab.
Hence, it appears that tabs and spaces are hard-coded as the only characters at which wrapping is allowed to occur, but as already written above, I might (hopefully) be wrong.