Incorrect #INC in Activestate Perl in Windows - windows

I am using ActiveState perl with Komodo Edit.
I am getting the following error.
Can't locate MyGengo.pm in #INC (#INC contains: C:/Perl/site/lib C:/Perl/lib .)
at D:\oDesk\MyGengo Integration\sample line 6.
Why is the interpreter looking in C:/Perl/lib instead of C:\Perl\lib?
Doesn’t it know that it is Windows and not Linux?
EDIT
I resolved the problem by copying the .pm file in C:\Perl\lib directory. I think, the issue happened since this module was manually downloaded. PPM install would copy the .pm file to the lib directory.

As far as Windows is concerned, C:/Perl/lib and C:\Perl\lib are the same directory.
The perlport documentation notes (emphasis added)
DOS and Derivatives
Perl has long been ported to Intel-style microcomputers running under systems like PC-DOS, MS-DOS, OS/2, and most Windows platforms you can bring yourself to mention (except for Windows CE, if you count that). Users familiar with COMMAND.COM or CMD.EXE style shells should be aware that each of these file specifications may have subtle differences:
my $filespec0 = "c:/foo/bar/file.txt";
my $filespec1 = "c:\\foo\\bar\\file.txt";
my $filespec2 = 'c:\foo\bar\file.txt';
my $filespec3 = 'c:\\foo\\bar\\file.txt';
System calls accept either / or \ as the path separator. However, many command-line utilities of DOS vintage treat / as the option prefix, so may get confused by filenames containing /. Aside from calling any external programs, / will work just fine, and probably better, as it is more consistent with popular usage, and avoids the problem of remembering what to backwhack and what not to.
Your comment shows that you’re using mygengo-perl-new but have it installed in C:\Perl\lib\MyGengo\mygengo-api\nheinric-mygengo-perl-new-ce194df\mygengo. This is an unusual location to install the module. The way the module is written, it expects mygengo.pm to be in one of the directories named in #INC. Client code then pulls it in with
use mygengo;
My suggestion is to move mygengo.pm from C:\Perl\lib\MyGengo\mygengo-api\nheinric-mygengo-perl-new-ce194df\mygengo to C:\Perl\site\lib.
As an alternative if you are using mygengo as part of another package that you’re developing, you could drop mygengo in your source tree, perhaps as a git submodule. Don’t forget to add use lib 'mygengo'; if you do it this way.
For full details, read about the #INC search process in the perlfunc documentation on require and the extra semantics for modules via use.
General advice on slashes versus backslashes
Even if your code will run on Windows only, prefer using forward-slash as the separator in hardcoded paths. Backslash is an escape character in the Perl language, so you have to think more carefully about it. In double-quoted strings, you have to remember to escape the escape character to get its ordinary meaning, e.g.,
# my $dir = "C:\Perl\lib"; # oops, $path would be 'C:Perlib'
$dir = "C:\\Perl\\lib";
The situation can be a little nicer inside single-quoted strings. Setting $dir as in
$dir = 'C:\Perl\lib';
does what you expect, but say you want $dir to have a trailing slash.
$dir = 'C:\Perl\lib\';
Now you have a syntax error.
Can't find string terminator "'" anywhere before EOF at dirstuff line n.
You may want to interpolate another value into $dir.
$dir = 'C:\Perl\lib\$module'; # nope
Oh yeah, you need double-quotes for interpolation.
$dir = "C:\Perl\lib\$module"; # still not right
After headscratching and debugging
$dir = "C:\\Perl\\lib\\$module"; # finally
Backslash is therefore more mistake-prone and a maintenance irritant. Forward slash is an ordinary character inside both single- and double-quoted strings, so it almost always means what you expect.
As perlport notes, the Windows command shell treats forward slash as introducing options and backslash as path separators. If you cannot avoid the shell, then you may be forced to deal with backslashes.

Related

Is ./*/ portable?

I often use ./*/ in a for loop like
for d in ./*/; do
: # do something with dirs
done
to match all non-hidden directories in current working directory, but I'm not really sure if this is a portable way to do that. I have bash, dash and ksh installed on my system and it works with all, but since POSIX spec doesn't say anything about it (or it says implicitly, and I missed it) I think I can't rely on it. I also checked POSIX bug reports, but to no avail, there's no mention of it there as well.
Is its behaviour implementation or filesystem dependent? Am I missing something here? How do I know if it's portable or not?
Short answer: YES
Long Answer:
The POSIX standard (from opengroup) states that / will only match slashes in the expanded file name. Since Unix/Linux does not allow / in the file name, I believe that this is a safe assumption on Unix/Linux systems.
From the bolded text below, it seems that even for systems that will allow / in the file name, the POSIX standard require that / will not be matched to such file.
On Windows, looks like / is not allowed in the file name, but I'm not an expert on Windows.
From Shell Programming Language § Patterns Used for Filename Expansion:
The slash character in a pathname shall be explicitly matched by using one or more slashes in the pattern; it shall neither be matched by the asterisk or question-mark special characters nor by a bracket expression. Slashes in the pattern shall be identified before bracket expressions; thus, a slash cannot be included in a pattern bracket expression used for filename expansion.
...
Additional Note - clarifying pathname:
The pathname is defined in 4.13, with explicit reference to pathname with trailing slash in General Concepts § Pathname Resolution.
A pathname that contains at least one non-<slash> character and that ends with one or more trailing <slash> characters shall not be resolved successfully unless the last pathname component before the trailing <slash> characters names an existing directory or a directory entry that is to be created for a directory immediately after the pathname is resolved. Interfaces using pathname resolution may specify additional constraints when a pathname that does not name an existing directory contains at least one non-<slash> character and contains one or more trailing <slash> characters.

Installing emacs plugins on windows

I already looked through other topics, but I still couldn't find a solution. I'm trying to install "nxhtml" plugin for Emacs in windows 7. I already setup my "HOME" environment variable as "C:\". So, my .emacs.d folder is there, and I put the nxhtml in there and added the following line to my "_emacs.d" file, as the readme says:
(load "C:\.emacs.d\nxhtml\autostart.el")
But it doesn't load.
I also tried putting:
(add-to-list 'load-path "C:\.emacs.d\nxhtml")
(load "autostart.el")
But to no avail... can anyone shed some light here? tnx.
A number of points here:
Firstly, _emacs.d is not a default file name for your init file, ie emacs will not load it automatically. Try ~/.emacs.d/init.el, or ~/.emacs instead.
Secondly, Windows 7 has a feature where it prevents programs from writing to certain system directories, but for backwards compatibility for the many old programs that do this, rather than causing them to fail, it silently redirects the write elsewhere, in an application specific directory. C:\ is one of those directories, so setting your HOME to point there is asking for trouble.
Thirdly, see the other response about backslash being an escape character in Lisp strings.
\ is special in the (double-quote) read syntax for strings, as certain characters take on a new meaning when prefixed by a backslash (e.g. \n is a newline, \t is a tab, and \" is a double-quote character). When the following character does not have any special meaning in conjunction with the backslash, that character is used verbatim, and the backslash is ignored.
"C:\.emacs.d\nxhtml\autostart.el" is actually the string:
C:.emacs.d
xhtml^Gutostart.el
To include a \ in the string you need to write \\
However, although it will understand the backslashes, Emacs is nowadays consistent across all platforms in allowing / as a directory separator1; so just do that instead.
1 and the obsolete directory-sep-char variable has been removed entirely.

Using environment variables to form paths in Make and windows

I have a make file and I am trying to use it to copy files to a directory. The path of the directory is stored in an environment variable. The problem is when I run make the C:\Data from the environment variable is interpreted as C:Data. How do I stop this being intrepreted as an escape character?
copyData : buildData
cp Release/*.tbl $(DATA)/index
results in:
cp Release/*.tbl C:\Data/index
cp: `C:Data/index': specified destination directory does not exist
Try `cp --help' for more information.
Actually, using forward slashes is the best, and correct, solution. Windows utilities always support forward slashes so it works, and trying to remember to always quote pathnames to avoid issues with backslashes is a major hassle.
In this case the first thing to note is that the problem is not a problem with make. make is passing the right content to the shell; it's the shell which is parsing the backslash as an escape character.
As I said above the right answer is to use forward slashes BUT if you want to allow people to use backslashes you'll have to go through your makefile and quote all arguments where a backslash might appear. For example:
copyData : buildData
cp Release/*.tbl '$(DATA)'/index
will fix your immediate problem.
If you have just a couple of these variables you could also do something like:
QDATA = '$(DATA)'
then remember to use $(QDATA) where you wanted the quoted value:
copyData : buildData
cp Release/*.tbl $(QDATA)/index
PS. Use forward slashes!! :-)

Why doesn't this path work to open a Windows file in PERL?

I tried to play with Strawberry Perl, and one of the things that stumped me was reading the files.
I tried to do:
open(FH, "D:\test\numbers.txt");
But it can not find the file (despite the file being there, and no permissions issues).
An equivalent code (100% of the script other than the filename was identical) worked fine on Linux.
As per Perl FAQ 5, you should be using forward slashes in your DOS/Windows filenames (or, as an alternative, escaping the backslashes).
Why can't I use "C:\temp\foo" in DOS paths? Why doesn't `C:\temp\foo.exe` work?
Whoops! You just put a tab and a formfeed into that filename! Remember that within double quoted strings ("like\this"), the backslash is an escape character. The full list of these is in Quote and Quote-like Operators in perlop. Unsurprisingly, you don't have a file called "c:(tab)emp(formfeed)oo" or "c:(tab)emp(formfeed)oo.exe" on your legacy DOS filesystem.
Either single-quote your strings, or (preferably) use forward slashes. Since all DOS and Windows versions since something like MS-DOS 2.0 or so have treated / and \ the same in a path, you might as well use the one that doesn't clash with Perl--or the POSIX shell, ANSI C and C++, awk, Tcl, Java, or Python, just to mention a few. POSIX paths are more portable, too.
So your code should be open(FH, "D:/test/numbers.txt"); instead, to avoid trying to open a file named "D:<TAB>est\numbers.txt"
As an aside, you could further improve your code by using lexical (instead of global named) filehandle, a 3-argument form of open, and, most importantly, error-checking ALL your IO operations, especially open() calls:
open(my $fh, "<", "D:/test/numbers.txt") or die "Could not open file: $!";
Or, better yet, don't hard-code filenames in IO calls (the following practice MAY have let you figure out a problem sooner):
my $filename = "D:/test/numbers.txt";
open(my $fh, "<", $filename) or die "Could not open file $filename: $!";
Never use interpolated strings when you don't need interpolation! You are trying to open a file name with a tab character and a newline character in it from the \t and the \n!
Use single quotes when you want don't need (or want) interpolation.
One of the biggest problems novice Perl programmers seem to run into is that they automatically use "" for everything without thinking. You need to understand the difference between "" and '' and you need to ALWAYS think before you type so that you choose the right one. It's a hard habit to get into, but it's vital if you're going to write good Perl.

How can I construct OS-independent file paths in Perl including an optional Windows drive letter?

I need to construct a file path inside a Perl script. Which path separator should I use to allow my script to work on both Windows and Unix?
Keep in mind that Windows needs a drive letter.
You want File::Spec's catpath:
catpath()
Takes volume, directory and file portions and returns an entire path.
Under Unix, $volume is ignored, and directory and file are
concatenated. A '/' is inserted if need be. On other OSes, $volume
is significant.
$full_path = File::Spec->catpath( $volume, $directory, $file );
You want File::Spec. There are specific versions for Unix, Win32, and MacOS as well others.
If you find File::Spec cumbersome, as I do, try Path::Class. It gives you directory and file objects to work with rather than having to call long winded File::Spec class methods on strings.
It sounds like you are using path separator to mean the character between directory/file name components. But just in case you meant the other meaning:
Some things (notably environment variables like MANPATH or PERL5LIB) take a list of file or directory names, separated by a path separator character. Perl's Config module portably supplies such a character as $Config::Config{'path_sep'}.
Q:Which path separator should I use to allow my script to work on both Windows and Unix?
A: /.
Explanation:
Windows can work similarly to Unix with / as path separator.
(Mac OS uses : as a path separator instead of /).
The File::Spec modules can also help.
use File::Spec::Functions;
chdir(updir()); # go up one directory
$file = catfile(curdir(), 'temp', 'file.txt');
# on Unix and Win32, './temp/file.txt'
# on Mac OS, ':temp:file.txt'
# on VMS, '[.temp]file.txt'
Source:
http://www.xav.com/perl/lib/Pod/perlport.html

Resources