" Vim syntax file " by G. Branden Robinson, August 2021. GPLv3. " Language: nroff/groff/troff if exists("b:current_syntax") finish endif let s:cpo_save = &cpo set cpo&vim " This syntax should be named 'troff'; it recognizes and does not " distinguish typesetter-specific features, just like the stock Vim " implementation. let b:current_syntax = "nroff" if exists("b:nroff_is_groff") syntax keyword nroffKeyword groff endif if exists("b:nroff_is_groff") syntax match nroffEscapeCharacter /\\/ nextgroup=nroffSimpleEscape, \nroffSingleSpecialCharacter, \nroffSpecialCharacterLeftParenthesis, \nroffGroffLeftBracket, \nroffSpaceEscape, \nroffFixedWidthSpaceEscape, \nroffComment, \nroffOutputEscape, \nroffGroffOutputEscape, \nroffInterpolationEscape, \nroffArgumentInterpolationEscape, \nroffBracketBuildingEscape, \nroffCharacterEscape, \nroffDrawingEscape, \nroffGroffNullableInterpolationEscape, \nroffMotionOffsetEscape, \nroffMarkEscape, \nroffNumberedGlyphEscape, \nroffDelimitedEscape, \nroffTypeSizeEscape, \nroffSlantEscape, \nroffDeviceEscape else syntax match nroffEscapeCharacter /\\/ nextgroup=nroffSimpleEscape, \nroffSingleSpecialCharacter, \nroffSpecialCharacterLeftParenthesis, \nroffSpaceEscape, \nroffFixedWidthSpaceEscape, \nroffComment, \nroffOutputEscape, \nroffInterpolationEscape, \nroffArgumentInterpolationEscape, \nroffBracketBuildingEscape, \nroffCharacterEscape, \nroffDrawingEscape, \nroffMotionOffsetEscape, \nroffMarkEscape, \nroffNumberedGlyphEscape, \nroffDelimitedEscape, \nroffTypeSizeEscape, \nroffSlantEscape, \nroffDeviceEscape endif " Handle simple one-character escape form that takes no arguments. " \% \& \a \c \d \e \p \r \t \u \z \{ \} syntax match nroffSimpleEscape /[%&acdeprtuz{}]/ contained " \) \: \E if exists("b:nroff_is_groff") syntax match nroffSimpleEscape /[):E]/ contained endif " "\ " " Some people might not like the following, but I like how it " discourages use of this escape sequence. syntax match nroffFixedWidthSpaceEscape / / contained syntax match nroffFixedWidthSpaceEscape /\\ $/ " \0 \| \^ syntax match nroffSpaceEscape /[0|^]/ contained " \~ if exists("b:nroff_is_groff") syntax match nroffSpaceEscape /\~/ contained endif " Handle AT&T-style special character escape sequences. " \- \' \` \_ syntax match nroffSingleSpecialCharacter /[-'`_]/ contained " \(xx syntax match nroffSpecialCharacterLeftParenthesis /(/ contained \ nextgroup=nroffDoubleSpecialCharacter,nroffEscapeCharacter syntax match nroffDoubleSpecialCharacter /[^\\][^\\]/ contained " Handle groff-style special character escape sequences. " \[xxx] if exists("b:nroff_is_groff") syntax match nroffGroffLeftBracket /\[/ contained \ nextgroup=nroffGroffSpecialCharacter syntax match nroffGroffSpecialCharacter /[^]]\+/ contained \ nextgroup=nroffGroffRightBracket syntax match nroffGroffRightBracket /\]/ contained endif " Handle comments. They consume the rest of the line. " \" syntax match nroffComment /".*/ contained contains=nroffNote,nroffTodo " \# if exists("b:nroff_is_groff") syntax match nroffComment /#.*/ contained contains=nroffNote, \nroffTodo endif syntax keyword nroffNote Note NOTE contained syntax keyword nroffTodo FIXME TODO XXX contained " Handle "transparent line" escape. It also eats the rest of the line. " \! syntax match nroffOutputEscape /!/ contained nextgroup=nroffDeviceOutput syntax match nroffDeviceOutput /.*/ contained " Handle groff's "inline" device output escape. " \? if exists("b:nroff_is_groff") syntax region nroffGroffDeviceOutput \ matchgroup=nroffGroffOutputEscape start=/\\?/ end=/\\?/ oneline endif " Handle escape sequences that take arguments. " \* \f \g \n syntax match nroffSingleCharacterIdentifer /[^\\]/ contained syntax match nroffIdentifierLeftParenthesis /(/ contained \ nextgroup=nroffIdentifier syntax match nroffIdentifier /[^\\][^\\]/ contained if exists("b:nroff_is_groff") syntax match nroffInterpolationEscape /[*gn]/ contained \ nextgroup=nroffSingleCharacterIdentifer, \nroffIdentifierLeftParenthesis,nroffGroffIdentifierLeftBracket syntax match nroffGroffIdentifierLeftBracket /\[/ contained \ nextgroup=nroffGroffIdentifier syntax match nroffGroffIdentifier /[^]]\+/ contained \ nextgroup=nroffGroffRightBracket " In groff, sometimes the bracket contents can be empty. syntax match nroffGroffNullableInterpolationEscape /f/ contained \ nextgroup=nroffSingleCharacterIdentifer, \nroffIdentifierLeftParenthesis,nroffGroffNullableBracketParameter syntax region nroffGroffNullableBracketParameter \ matchgroup=nroffInterpolationEscape start=/\[/ end=/\]/ contained \ oneline else syntax match nroffInterpolationEscape /[*fgn]/ contained \ nextgroup=nroffSingleCharacterIdentifer, \nroffIdentifierLeftParenthesis endif " macro argument interpolation " \$ syntax match nroffArgumentInterpolationEscape /\$/ contained \ nextgroup=nroffSingleDigitNumber syntax match nroffSingleDigitNumber /\d/ contained if exists("b:nroff_is_groff") syntax match nroffArgumentInterpolationEscape /\$/ contained \ nextgroup=nroffSingleDigitNumber, \nroffGroffArgumentLeftParenthesis,nroffGroffArgumentLeftBracket syntax match nroffGroffArgumentLeftParenthesis /(/ contained \ nextgroup=nroffGroffDoubleDigitNumber syntax match nroffGroffDoubleDigitNumber /\d\d/ contained syntax match nroffGroffArgumentLeftBracket /\[/ contained \ nextgroup=nroffBracketDelimitedNumber syntax match nroffBracketDelimitedNumber /\d\+/ contained \ nextgroup=nroffGroffRightBracket endif " Handle escape sequences that take delimiters. " bracket builder " \b syntax match nroffBracketBuildingEscape /b/ contained \ nextgroup=nroffDelimitedEscapeArgument syntax region nroffDelimitedEscapeArgument \ matchgroup=nroffEscapeDelimiter start=/'/ end=/'/ contained \ contains=nroffEscapeCharacter " special character escape " \C " TODO: Tricky; practically any character can appear in a special " character name, and predefined names (see groff_char(7)) use both " apostrophes and double quotes. However, the double quote is " considerably rarer, used only for the "Hungarian umlaut" (\C'a"'). " Therefore, encourage people to use a double quote for the escape " delimiter. For other escapes, we encourage the apostrophe, following " examples in CSTR #54 and much other troff literature. syntax match nroffCharacterEscape /C/ contained \ nextgroup=nroffCharacterEscapeArgument syntax region nroffCharacterEscapeArgument \ matchgroup=nroffEscapeDelimiter start=/"/ end=/"/ contained \ contains=nroffSpecialCharacter syntax match nroffSpecialCharacter /[^"]\+/ contained " drawing escape " \D " TODO: More precisely highlight the drawing command arguments. syntax match nroffDrawingEscape /D/ contained \ nextgroup=nroffDrawingEscapeArgument syntax region nroffDrawingEscapeArgument \ matchgroup=nroffEscapeDelimiter start=/'/ end=/'/ contained \ contains=nroffArcDrawingCommand,nroffCircleDrawingCommand, \nroffEllipseDrawingCommand,nroffLineDrawingCommand, \nroffSplineDrawingCommand syntax match nroffArcDrawingCommand /a/ contained \ nextgroup=nroffDrawingArguments syntax match nroffCircleDrawingCommand /c/ contained \ nextgroup=nroffDrawingArguments syntax match nroffEllipseDrawingCommand /e/ contained \ nextgroup=nroffDrawingArguments syntax match nroffLineDrawingCommand /l/ contained \ nextgroup=nroffDrawingArguments syntax match nroffSplineDrawingCommand /\~/ contained \ nextgroup=nroffDrawingArguments syntax match nroffDrawingArguments /[-+.0-9cipPmnvu \t]\+/ contained if exists("b:nroff_is_groff") syntax region nroffDrawingEscapeArgument \ matchgroup=nroffEscapeDelimiter start=/'/ end=/'/ contained \ contains=nroffArcDrawingCommand,nroffCircleDrawingCommand, \nroffEllipseDrawingCommand,nroffLineDrawingCommand, \nroffSplineDrawingCommand,nroffSetFillColorDrawingCommand, \nroffPolygonDrawingCommand,nroffSetLineThicknessDrawingCommand syntax match nroffCircleDrawingCommand /C/ contained \ nextgroup=nroffDrawingArguments syntax match nroffEllipseDrawingCommand /E/ contained \ nextgroup=nroffDrawingArguments syntax match nroffSetFillColorDrawingCommand /f/ contained \ nextgroup=nroffDrawingArguments syntax match nroffSetFillColorDrawingCommand /F[cgkr]/ contained \ nextgroup=nroffDrawingArguments syntax match nroffSetFillColorDrawingCommand /Fd/ contained syntax match nroffPolygonDrawingCommand /[pP]/ contained \ nextgroup=nroffDrawingArguments syntax match nroffSetLineThicknessDrawingCommand /t/ contained \ nextgroup=nroffDrawingArguments endif " horizontal and vertical motion, orthogonal line drawing, and line " height adjustment " The optional glyph argument in \[lL] lines that comes right after " the offset is not highlighted if it is an ordinary character. " \h \l \L \v \x syntax match nroffMotionOffsetEscape /[hlLvx]/ contained \ nextgroup=nroffMotionOffsetEscapeArgument syntax region nroffMotionOffsetEscapeArgument \ matchgroup=nroffEscapeDelimiter start=/'/ end=/'/ contained \ contains=nroffOffsetMeasurement,nroffEscapeCharacter syntax match nroffOffsetMeasurement /|\=[-+]\=\d\=.\=\d[cipPmnvu]\=/ \ contained " horizontal place-marking " The form documented in CSTR #54 is degenerate, having no \k(xx form. " \k if exists("b:nroff_is_groff") syntax match nroffMarkEscape /k/ contained \ nextgroup=nroffSingleCharacterIdentifer, \nroffIdentifierLeftParenthesis,nroffGroffIdentifierLeftBracket else syntax match nroffMarkEscape /k/ contained \ nextgroup=nroffSingleCharacterIdentifer endif " font glyph access by code point number " \N syntax match nroffNumberedGlyphEscape /N/ contained \ nextgroup=nroffNumberedGlyphEscapeArgument syntax region nroffNumberedGlyphEscapeArgument \ matchgroup=nroffEscapeDelimiter start=/'/ end=/'/ contained \ contains=nroffDelimitedNumber,nroffEscapeCharacter syntax match nroffDelimitedNumber /\d\+/ contained " overstrike a sequence of glyphs " measure the width of the delimited argument " These escapes have no internal syntax. " \o \w syntax match nroffDelimitedEscape /[ow]/ contained \ nextgroup=nroffDelimitedEscapeArgument syntax region nroffNumberedGlyphEscapeArgument \ matchgroup=nroffEscapeDelimiter start=/'/ end=/'/ contained \ contains=nroffEscapeCharacter " type size escape " One could argue that the sign should get highlighted like the number " even if it's not adjacent to it, but that's too much effort for the " biggest(?) wart in troff syntax. " \s if exists("b:nroff_is_groff") syntax match nroffTypeSizeEscape /s/ contained \ nextgroup=nroffSingleDigitNumber,nroffSignedNumberLeftParenthesis, \nroffTypeSizeEscapeSign,nroffDelimitedSignedNumberEscapeArgument, \nroffGroffTypeSizeLeftBracket syntax match nroffGroffTypeSizeLeftBracket /\[/ contained \ nextgroup=nroffGroffSignedMultiDigitNumber syntax match nroffGroffSignedMultiDigitNumber /[-+]\=\d\+/ contained \ nextgroup=nroffGroffRightBracket else syntax match nroffTypeSizeEscape /s/ contained \ nextgroup=nroffSingleDigitNumber,nroffSignedNumberLeftParenthesis, \nroffTypeSizeEscapeSign,nroffDelimitedSignedNumberEscapeArgument endif " \s(+10 \s(-02 syntax match nroffSignedNumberLeftParenthesis /(/ contained \ nextgroup=nroffSignedDoubleDigitNumber syntax match nroffSignedDoubleDigitNumber /[-+]\=\d\d/ contained " \s+(10 \s-(02 syntax match nroffTypeSizeEscapeSign /[-+]/ contained \ nextgroup=nroffSingleDigitNumber,nroffNumberLeftParenthesis, \nroffDelimitedSignedNumberEscapeArgument syntax match nroffNumberLeftParenthesis /(/ contained \ nextgroup=nroffDoubleDigitNumber syntax match nroffDoubleDigitNumber /\d\d/ contained " \s+'40' \s-'40' \s-'+40' \s+'-40' syntax region nroffDelimitedSignedNumberEscapeArgument \ matchgroup=nroffEscapeDelimiter start=/'/ end=/'/ contained \ contains=nroffDelimitedSignedNumber,nroffEscapeCharacter syntax match nroffDelimitedSignedNumber /[-+]\=\d\+/ contained " font slant escape " \S syntax match nroffSlantEscape /S/ contained \ nextgroup=nroffSlantEscapeArgument syntax region nroffSlantEscapeArgument \ matchgroup=nroffEscapeDelimiter start=/'/ end=/'/ contained \ contains=nroffDelimitedSignedNumber,nroffEscapeCharacter " device escape " \X " TODO: Handle escape sequences within the delimiters. syntax match nroffDeviceEscape /X/ contained \ nextgroup=nroffDeviceEscapeArgument syntax region nroffDeviceEscapeArgument \ matchgroup=nroffEscapeDelimiter start=/'/ end=/'/ contained \ contains=nroffDelimitedDeviceOutput,nroffEscapeCharacter syntax match nroffDelimitedDeviceOutput /[^']/ contained highlight default link nroffEscapeCharacter Preproc highlight default link nroffSimpleEscape Preproc highlight default link nroffSpecialCharacterLeftParenthesis Preproc highlight default link nroffGroffLeftBracket Preproc highlight default link nroffGroffRightBracket Preproc highlight default link nroffOutputEscape Preproc highlight default link nroffGroffOutputEscape Preproc highlight default link nroffInterpolationEscape Preproc highlight default link nroffIdentifierLeftParenthesis Preproc highlight default link nroffGroffIdentifierLeftBracket Preproc highlight default link nroffArgumentInterpolationEscape Preproc highlight default link nroffGroffArgumentLeftParenthesis Preproc highlight default link nroffGroffArgumentLeftBracket Preproc highlight default link nroffBracketBuildingEscape Preproc highlight default link nroffEscapeDelimiter Preproc highlight default link nroffCharacterEscape Preproc highlight default link nroffDrawingEscape Preproc highlight default link nroffGroffNullableInterpolationEscape Preproc highlight default link nroffMotionOffsetEscape Preproc highlight default link nroffMarkEscape Preproc highlight default link nroffNumberedGlyphEscape Preproc highlight default link nroffDelimitedEscape Preproc highlight default link nroffTypeSizeEscape Preproc highlight default link nroffTypeSizeEscapeSign Preproc highlight default link nroffNumberLeftParenthesis Preproc highlight default link nroffSignedNumberLeftParenthesis Preproc highlight default link nroffGroffTypeSizeLeftBracket Preproc highlight default link nroffSlantEscape Preproc highlight default link nroffDeviceEscape Preproc highlight default link nroffFixedWidthSpaceEscape Todo highlight default link nroffSpaceEscape SpecialChar highlight default link nroffSingleSpecialCharacter SpecialChar highlight default link nroffDoubleSpecialCharacter SpecialChar highlight default link nroffGroffSpecialCharacter SpecialChar highlight default link nroffSpecialCharacter SpecialChar highlight default link nroffTodo Todo highlight default link nroffKeyword Error highlight default link nroffDeviceOutput Type highlight default link nroffDelimitedDeviceOutput Type highlight default link nroffGroffDeviceOutput Type highlight default link nroffArcDrawingCommand Type highlight default link nroffCircleDrawingCommand Type highlight default link nroffEllipseDrawingCommand Type highlight default link nroffLineDrawingCommand Type highlight default link nroffPolygonDrawingCommand Type highlight default link nroffSetFillColorDrawingCommand Type highlight default link nroffSetLineThicknessDrawingCommand Type highlight default link nroffSplineDrawingCommand Type highlight default link nroffSingleCharacterIdentifer Identifier highlight default link nroffIdentifier Identifier highlight default link nroffGroffIdentifier Identifier highlight default link nroffGroffNullableBracketParameter Identifier highlight default link nroffSingleDigitNumber Number highlight default link nroffDoubleDigitNumber Number highlight default link nroffSignedDoubleDigitNumber Number highlight default link nroffDelimitedNumber Number highlight default link nroffDelimitedSignedNumber Number highlight default link nroffGroffDoubleDigitNumber Number highlight default link nroffGroffSignedMultiDigitNumber Number highlight default link nroffBracketDelimitedNumber Number highlight default link nroffDrawingArguments Number highlight default link nroffOffsetMeasurement Number let &cpo = s:cpo_save unlet s:cpo_save " vim: set autoindent shiftwidth=4 softtabstop=4 textwidth=72: