newtcblisting 中的长度操作

newtcblisting 中的长度操作

考虑以下代码:

\documentclass[10pt,letterpaper]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[french]{babel}
\usepackage{calc}
\usepackage{tikz}
\usepackage{listings}
\usepackage[listings,skins,theorems]{tcolorbox}

\newlength{\numlen}
\newcommand{\getnumlen}[1]{
    \setlength{\numlen}{\widthof{\fontfamily{cmtt}\selectfont#1 0123456789}}
    \setlength{\numlen}{0.1\numlen}
}
\newtcblisting{mytcblisting}[1][]{
    before = {\getnumlen{#1}},
    enhanced,
    left = 4.\numlen,%\numlen is correct here
    listing only,
    listing options = {
        language = C++,
        basicstyle=\fontfamily{cmtt}\selectfont#1,
        showstringspaces = false,
        numbers = left,
        numbersep = 4.\numlen,%\numlen seems to be 0 here
    },
}

\begin{document}
\begin{mytcblisting}[\tiny]
int main(int argc, char* argv[]) {
    return 0;
}
\end{mytcblisting}
\end{document}

我希望left数字和代码之间的测量和分离numbersep基于在cmtt系列中写入的数字的典型长度,其大小作为参数传递mytcblisting

但是使用此代码,left选项可以正常工作,但不能numbersep

如何让它工作?

答案1

显然,在使用和设置listing options之前先进行评估。这意味着必须在此特殊选项块中调用-- > 。before=\getnumlen{#1}numlennumlen0pt\getnumlen{#1}

肮脏的试验 -->在选项\getnumlen{#1}中使用basicstyle--> 它是一个有效的代码宏,没有排版/字体宏,所以它不会造成危害。

\documentclass[10pt,letterpaper]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[french]{babel}
\usepackage{calc}
\usepackage{tikz}
\usepackage{listings}
\usepackage[listings,skins,theorems]{tcolorbox}

\newlength{\numlen}
\newcommand{\getnumlen}[1]{%
  \setlength{\numlen}{\widthof{\fontfamily{cmtt}\selectfont#1 0123456789}}%
  \setlength{\numlen}{0.1\numlen}%
}
\newtcblisting{mytcblisting}[1][]{%
    listing options = {%
        language = C++,
        basicstyle=\getnumlen{#1}\fontfamily{cmtt}\selectfont#1,
        showstringspaces = false,
        numbers = left,
        numbersep = 4.\numlen,%\numlen seems to be 0 here
    },%
    before = {\getnumlen{#1}},
    enhanced,
    left = 4.\numlen,%\numlen is correct here
    listing only
}

\begin{document}
\begin{mytcblisting}[\tiny]
int main(int argc, char* argv[]) {
    return 0;
}
\end{mytcblisting}
\end{document}

编辑一种更简洁的方法:向密钥系列中添加一个密钥lst

\documentclass[10pt,letterpaper]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[french]{babel}
\usepackage{calc}
\usepackage{tikz}
\usepackage{listings}
\usepackage[listings,skins,theorems]{tcolorbox}

\makeatletter
\define@key{lst}{numlen}[\protect\tiny]{%%
  \getnumlen{#1}%
}
\makeatother

\newlength{\numlen}
\newcommand{\getnumlen}[1]{%
  \setlength{\numlen}{\widthof{\fontfamily{cmtt}\selectfont#1 0123456789}}%
  \setlength{\numlen}{0.1\numlen}%
}
\newtcblisting{mytcblisting}[1][]{%
    listing options = {%
        language = C++,
        basicstyle=\fontfamily{cmtt}\selectfont#1,
        showstringspaces = false,
        numbers = left,
        numlen={\protect #1},
        numbersep = 6.\numlen,%\numlen seems to be 0 here
    },%
    before = {\getnumlen{\protect #1}},
    enhanced,
    left = 4.\numlen,%\numlen is correct here
    listing only
}

\begin{document}
\begin{mytcblisting}[\tiny]
int main(int argc, char* argv[]) {
    return 0;
}
\end{mytcblisting}


\end{document}

相关内容