3
\$\begingroup\$

R does not support line continuation as Python, and it's disturbing to have long file paths like

/media/user/data/something-not-very-important-but-super-long/some-curious-secret-file.pdf

and can't break it into multiple lines.

The workaround is to use the file.path function:

file.path(
  "/root",
  "folder",
  "file.ods")

Manually editing is tedious, so here is a Python script that does the job for you:

#!/usr/bin/env python3

import sys

x = sys.argv[1]
# split by unix path separator
y = x.split("/")
# get rid of empty strings
y = [i for i in y if i]

# preserve / if it's an absolute path
if x.startswith("/"):
    y[0] = "/" + y[0]

# quote everything
y = ["'" + i + "'" for i in y]

res = "file.path(" + ",\n    ".join(y) + ")"
print(res)
\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

Always throw things in main:

def main():
    # code

main()

It might seem pointless but it does help with preventing global pollution, which is good if you ever decide to add a function somewhere.

Using

x = sys.argv[1]

is acceptable for a trivial script, but it's not much harder to use docopt and implement a proper command-line parser:

"""
Name Of Program.

Usage: prog.py <pathname>
"""

import docopt

def main():
    args = docopt.docopt(__doc__)

    x = args["<pathname>"]

Trivial, but it gives you --help, error reporting and sane handling of bad input, nearly for free.

This can be simplified a little with pathlib:

parts = pathlib.PurePosixPath(args["<pathname>"]).parts

if len(parts) >= 2 and parts[0] == "/":
    parts = ("/" + parts[1],) + parts[2:]

You can actually use just pathlib.Path but it may assume a Windows format on Windows machines.

Your quoting:

parts = ["'" + i + "'" for i in parts]

should be done with repr:

parts = map(repr, parts)

and the formatting should use .format:

res = "file.path({})".format(",\n    ".join(parts))

This gives

#!/usr/bin/env python3

"""
Name Of Program.

Usage: prog.py <pathname>
"""

import docopt
import pathlib

def main():
    args = docopt.docopt(__doc__)
    parts = pathlib.PurePosixPath(args["<pathname>"]).parts

    if len(parts) >= 2 and parts[0] == "/":
        parts = ("/" + parts[1],) + parts[2:]

    args = ",\n    ".join(map(repr, parts))
    print("file.path({})".format(args))

main()

Technically PEP 8 says docopt should be separated from pathlib, the second being in the stdlib, but it looks nicer this way for now.

\$\endgroup\$
2
\$\begingroup\$

This seems quite alright. I have a couple of tips though:

  • Since you use the / in multiple places, it would be good to give it a name.

  • The variable names could be improved: x and y don't tell much about what they are.

  • Instead of "'" + i + "'", it's shorter and perhaps easier to read as "'%s'" % i, though the new style formatting is recommended, so this latter should be written as "'{}'".format(i)

Putting it together:

# use unix path separator
separator = '/'

origpath = sys.argv[1]
parts = origpath.split(separator)

# get rid of empty strings
parts = [item for item in parts if item]

# preserve / if it's an absolute path
if origpath.startswith(separator):
    parts[0] = separator + parts[0]

# quote everything
parts = ["'{}'".format(item) for item in parts]

res = "file.path(" + ",\n    ".join(parts) + ")"
print(res)
\$\endgroup\$
2
  • \$\begingroup\$ "Since you use the / in multiple places, it would be good to give it a name." Not sure I agree 'bout that. Also, new style formatting rulez: "'{}'".format(item). \$\endgroup\$
    – Veedrac
    Jan 15, 2015 at 2:22
  • \$\begingroup\$ @Veedrac replacing a magic string literal with a well-named variable is certainly a good thing. You seem to miss the point with the gist, which would only be marginally related if I had named the variable forward_slash. You're right about new style formatting though, updated that in my answer \$\endgroup\$
    – janos
    Jan 15, 2015 at 6:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.