0

I am creating a class that I want to use for creating my own worksheets. As such, I want each course that I teach to have its own information file, stored in the file , which, in the assignment, I can access by using a command such as \course{\<course-number-term>}.

Thus, in my class preamble file, I have the following code for the course:

\newcommand*{\course}[1]{\gdef\@course{#1}}
\input{\@course}

I know that the first line works for other text related things I am doing, and that the second line works for other static files in the same folder as my <course-number-term>.tex file, so each of these commands works independently, but not together, since I get the error

! undefined control sequence. 
\@course -> \course

l.42 \input{\@course} 

Is there a way to pass a variable into the \input command, or am I doomed to a lack of flexibility?

——————EDIT——————

Thank you everyone for the comments and solutions. I should have mentioned, I'm mostly using the information from the course tex file INSIDE the preamble—so, doing anything that inputs it after the \begin{document} doesn't quite cut it.

Kyle
  • 101

3 Answers3

1

I have also thought of another solution that actually sounds better for your use case. It being very different from my first answer I have made a second answer.

This seems like something you could accomplish best by defining the courses you teach as class options. You can actually define a bunch of things like this and have them all change at the same time.

mycourses.cls

\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{mycourses}[Sep 29, 2019 short description]

\newcommand{\mycourses@course}{}%
\newcommand{\mycourses@timeslot}{}%
\newcommand{\mycourses@day}{}%

\DeclareOption{ee433}{
    \renewcommand\mycourses@course{ee433}
    \renewcommand\mycourses@timeslot{11:00am}
    \renewcommand\mycourses@day{T Th}
}

\DeclareOption{me390}{
    \renewcommand\mycourses@course{me390}
    \renewcommand\mycourses@timeslot{2:00pm}
    \renewcommand\mycourses@day{M W F}
}

\DeclareOption{stats666}{
    \renewcommand\mycourses@course{stats666}
    \renewcommand\mycourses@timeslot{6:00am}
    \renewcommand\mycourses@day{S Su}
}

\ProcessOptions\relax

\LoadClass[letterpaper,11pt]{report}

\newcommand{\course}{\mycourses@course}%
\newcommand{\timeslot}{\mycourses@timeslot}%
\newcommand{\theday}{\mycourses@day}%

\endinput

main.tex

\documentclass[stats666]{mycourses}

\begin{document}

    \course{} is taught at \timeslot{} on \theday{}

\end{document}

Infact with this meathod, since by the time you have entered in the class option the document knows which one you are going to use, it could actually work to use a variable input command in the .cls file like this.

\DeclareOption{ee433}{
    \input{ee433}
}
Bob
  • 1,270
  • 9
  • 14
  • This allows me to put the stuff I'm including inside the preamble of the class, which is exactly what I want to do. Ideally, I'd like to never have to edit the class file again, so this doesn't provide this flexibility, but it does help out in the meantime. Thank you! – Kyle Sep 28 '19 at 00:16
  • 1
    If this is the case, that you never want to edit the .cls ever again because you want it to be modularized, I dont see the point in doing any of this \newcommand work. Just use the \input{myclassfilename} in your preamble (not in the .cls) and be done with it. You dont need to define any class options this way. – Bob Sep 30 '19 at 17:20
1

Ok one more shot. Here is a solution using a combination of the tricks demonstrated in my prior two answers. Since they are complete as they are I don't want to change them for further readers.

We will define three files: mycource.cls, main.tex, and stats666.tex

mycource.cls

\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{mycourses}[Sep 30, 2019 short description]

\LoadClass[letterpaper,11pt]{report}
\RequirePackage[utf8]{inputenc}


% \makeatletter
\newcommand{\coursename}[1]{\gdef\mycourses@coursename{#1}}%
\newcommand{\coursetime}[1]{\gdef\mycourses@coursetime{#1}}%
\newcommand{\getcoursevalue}[1]{%
  \@ifundefined{mycourses@#1}%
    {\PackageError{mycourses}{Variable '#1' undefined.}{}}%
    {\csname mycourses@#1\endcsname}}
% \makeatother

\newcommand{\setclass}[1]{\coursename{#1}\include{\getcoursevalue{coursename}}}%here is where your magic happens

\endinput

main.tex

\documentclass[12pt]{mycourses}

\setclass{stats666}%there is no way of getting around having this here

\begin{document}

\getcoursevalue{coursename} works.

\getcoursevalue{coursetime} works too.

\begin{tikzpicture}
    \draw (0,0) -- (5,5);
\end{tikzpicture}

\end{document}

stats666.tex

\RequirePackage{tikz}

\coursetime{6:00 AM, Saturday and Sunday}

This demonstrates how you can add preamble material inside the classfilename.tex as well as reference common commands setup inside your mycourses.cls.

You could even set up private course specific commands now in each classfilename.tex.

Bob
  • 1,270
  • 9
  • 14
  • So I haven’t tried this out, but I think you’ve got something here. Thank you so much for your help! I found a workaround that works for me, and for my purposes. – Kyle Oct 01 '19 at 21:04
0

I am a little confused by your question, but If I have it right you are not trying to use \input to add more preamble? I think this is more of what you were asking for?

Here is an example of what I think you are trying to do?

main.tex

\documentclass[12pt]{report}
\usepackage[utf8]{inputenc}


\newcommand{\course}[1]{\gdef\@course{#1}}%you make new commands in your preamble (everything after \documentclass{myclass} and before your \begin{document} 


\begin{document}
    Hello I am Mr Soandso

    \course{ee433}%Here you can call the command to store ee433 to the macro \@course

    Some more friendly words.

    \input{\@course}%Here you can reference \@course to input a like named file.

    Then you can still use the name \@course any time you would like!

\end{document}

ee433.tex

Welcome to EE433

It will print: enter image description here

EDIT----------------------------------------------------

There is something wrong with this code that I am trying to figure out. While it does work as exactly provided, for some reason if you attempt to create a second \newcommand{\varone}[1]{\gdef\@varone{#1}} with different names then call it the program will not compile. Im sure it has something to do with the @ character as removing it fixes the issue.

main.tex

\documentclass[12pt]{report}
\usepackage[utf8]{inputenc}


\newcommand{\course}[1]{\gdef\mycourse{#1}}%
\newcommand{\anothercommand}[1]{\gdef\myanothercourse{#1}}%

\begin{document}

\course{ee433}
\anothercommand{stats666}

\mycourse{} works and so does \myanothercourse{}.

\end{document}

EDIT--------------------------------------------- If you put makeatletter in the correct spot right above the command, it fixes the problem. However this produces some really bad spacing problems. With the help of @PhelypeOleinik this new solution works best. It is a very elegant modification which keep keeping track of variable names nice and clean. main.tex

\documentclass[12pt]{report}
\usepackage[utf8]{inputenc}

\makeatletter
\newcommand{\coursename}[1]{\gdef\mycourses@coursename{#1}}%
\newcommand{\coursetime}[1]{\gdef\mycourses@coursetime{#1}}%
\newcommand{\getcoursevalue}[1]{%
  \@ifundefined{mycourses@#1}%
    {\PackageError{mycourses}{Variable '#1' undefined.}{}}%
    {\csname mycourses@#1\endcsname}}
\makeatother

\begin{document}

\coursename{stats666}

\coursetime{6:00 AM, Saturday and Sunday}

\getcoursevalue{coursename} works.

\getcoursevalue{coursetime} works too.

\getcoursevalue{undefined} does not work.

\end{document}
Bob
  • 1,270
  • 9
  • 14
  • @ is a special character that has to be handled carefully. Take a look at Werner's link in the second comment to the original question. – Teepeemm Sep 27 '19 at 22:19
  • Unfortunately, I'm trying to use the information that I get from inputting the course information inside the preamble itself (see my edits), which means this solution doesn't work for me. Thanks for the help though! – Kyle Sep 28 '19 at 00:17