leo-colisson / robust-externalize

A LaTeX library to cache pictures (including tikz, python code, and more) in a robust, customizable, and pure way.
7 stars 2 forks source link

Properly deal with indented python code #25

Closed tobiasBora closed 4 months ago

tobiasBora commented 4 months ago

If we indent the python code like in:

    \begin{CacheMeCode}{python}
        import matplotlib.pyplot as plt
        import matplotlib
        matplotlib.use('pgf')
        year = [2014, 2015, 2016, 2017, 2018, 2019]
        tutorial_count = [39, 117, 111, 110, 67, 29]
        plt.plot(year, tutorial_count, color="#6c3376", linewidth=2)
        plt.title("Simple plot")
        plt.xlabel('Year')
        plt.ylabel('Number of futurestud.io Tutorials')
        print(get_filename_from_extension(".pgf"))
        plt.savefig("__ROBEXT_OUTPUT_PDF__")
    \end{CacheMeCode}

then this will work… but this is by pure chance (and it is not even doing what we expect it to do). The reason is that it is inserted inside another function:

def finished_with_no_error():
    '''
    Call this at the end of your script. This creates the path of the final pdf file that should be
    created (otherwise robust-externalize will think that the compilation failed)
    '''
    if not os.path.exists(get_filename_from_extension(".pdf")):
        # we create a nearly empty pdf (not empty or arxiv will remove it)
        with open(get_filename_from_extension(".pdf"), 'w') as f:
            f.write("ok")

### Starting main content
    import matplotlib.pyplot as plt
    import matplotlib
    matplotlib.use('pgf')
    year = [2014, 2015, 2016, 2017, 2018, 2019]
    tutorial_count = [39, 117, 111, 110, 67, 29]
    plt.plot(year, tutorial_count, color="#6c3376", linewidth=2)
    plt.title("Simple plot")
    plt.xlabel('Year')
    plt.ylabel('Number of futurestud.io Tutorials')
    print(get_filename_from_extension(".pgf"))
    plt.savefig("robExt-C0AB840F6AB86E71DA0968FAFE7B4ACF.pdf")

### Ending main content
finished_with_no_error()

but the output will be different depending on the number of spaces in front of the file which is not what we expect.

For now, the user is supposed to remove the spaces in front of the text… but it is not very convenient and easy to forget. It would be better instead to automatically trim the spaces.

tobiasBora commented 4 months ago

See also my discussion here, hopefully we will find some clean solution for this: https://tex.stackexchange.com/questions/709973/latex3-efficient-way-to-remove-spaces-in-front-of-a-command?noredirect=1#comment1765765_709973

tobiasBora commented 4 months ago

Solved in c9aae9fd84adf2acecba5cfd17ed2c99f895bc58

dflvunoooooo commented 4 months ago

Can confirm, it is working and the errors are shown properly despite the indention :) Good work, thank you!

dflvunoooooo commented 4 months ago

This is not true for the PlaceholderFromCode environment. If I insert indention there, python does not work.

tobiasBora commented 4 months ago

Yes, indeed, the problem in that case is that when creating a placeholder this way, I don't know yet how this placeholder will be used (maybe indentation is important?), as it is independent of any preset. For now, you can either add in your preset options something like:

placeholder remove leading spaces={__TMP__}

or right after the \end{PlaceholderFromCode} you can run \placeholderRemoveLeadingSpaces{__TMP__}. I will think to see if it makes sense to apply it by default on any such placeholders.

tobiasBora commented 4 months ago

This is fixed in v2.7, now published in CTAN. This should even be part of Texlive 2024 as the froze is tonight.

dflvunoooooo commented 4 months ago

Great work as ever, thank you very much!