Get current system local encoding in Perl on Windows - windows

I need to get the current encoding according to the system local settings. I'm looking for such function working this way:
my $sysEncoding = getSystemEncoding();
#and now $sysEncoding equals e.g. 'windows-1250'
I looked everywhere on the internet. I've found just the module PerlIO::locale. But I thing that the system encoding should be recognized easier without additional modules.

Encode::Locale provides the means to handle this.

use Win32::API;
if (Win32::API->Import('kernel32', 'int GetACP()')) {
$enc = GetACP();
print "Current local encoding is '$enc'\n";
}
Thanks for hint to Ikegami.

Related

Astyle does not work in Windows

I just download Astyle from SourceForge. When I execute Astyle.exe in /bin, it said
Cannot convert to multi-byte string, reverting to English.
I don't know what happened.
I find there is a similar question, but that is about Astyle in OS X.
Here are the source code related to the error. I don't know the meaning of the second line.
// Not all compilers support the C++ function locale::global(locale(""));
// For testing on Windows change the "Region and Language" settings or use AppLocale.
// For testing on Linux change the LANG environment variable: LANG=fr_FR.UTF-8.
// setlocale() will use the LANG environment variable on Linux.
char* localeName = setlocale(LC_ALL, "");
if (localeName == NULL) // use the english (ascii) defaults
{
fprintf(stderr, "\n%s\n\n", "Cannot set native locale, reverting to English");
setTranslationClass();
return;
}
Finally, please feel free to correct my English.
Add following include to both ASLocalizer.cpp and style_main.cpp:
<#include "locale.h">

Why isn't this glob working for a Rake FileList for my server?

How come I get an empty filelist from:
files = FileList.new("#{DEPLOYMENT_PATH}\**\*")
Where DEPLOYMENT_PATH is \\myserver\anndsomepath
How to get a filelist from a server like this? Is this an issue of Ruby/Rake?
UPDATE:
I tried:
files = FileList.new("#{DEPLOYMENT_PATH}\\**\\*")
files = Dir.glob("#{DEPLOYMENT_PATH}\\**\\*")
files = Dir.glob("#{DEPLOYMENT_PATH}\**\*")
UPDATE AGAIN: It works if I put server as:
//myserver/andsomepath
and get files like this:
files = FileList.new("#{DEPLOYMENT_PATH}/**/*")
Ruby' File.join is designed to be your helper when dealing with file paths, by building them in a system-independent way:
File.join('a','b','c')
=> "a/b/c"
So:
DEPLOYMENT_PATH = File.join('', 'myserver', 'andsomepath')
=> "/myserver/andsomepath"
Ruby determines the file path separator by sensing the OS, and is supposed to automatically supply the right value. On Windows XP, Linux and Mac OS it is:
File::SEPARATOR
=> "/"
File.join(DEPLOYMENT_PATH, '**', '*')
=> "/myserver/andsomepath/**/*"
While you can ignore the helper, it is there to make your life easier. Because you are working against a server, you might want to look into File::ALT_SEPARATOR, or just reassigning to SEPARATOR and ignore the warning, letting Ruby do the rest.
What happens if you do
Dir.glob("#{DEPLOYMENT_PATH}\**\*")
Edit: I think Ruby prefers you doing Unix-style slashes, even when you're on Windows. I assume the rationale is that it's better for the same code to work on both Unix and Windows, even if it looks weird on Windows.
tl;dr: If it works with / but not with \, then use what works.
Because:
> "\*" == "*"
=> true
Use "\\**\\*" instead.

slash and backslash in Ruby

I want to write a application that works in windows and linux. but I have a path problem because windows use "\" and Linux use "/" .how can I solve this problem.
thanks
In Ruby, there is no difference between the paths in Linux or Windows. The path should be using / regardless of environment. So, for using any path in Windows, replace all \ with /. File#join will work for both Windows and Linux. For example, in Windows:
Dir.pwd
=> "C/Documents and Settings/Users/prince"
File.open(Dir.pwd + "/Desktop/file.txt", "r")
=> #<File...>
File.open(File.join(Dir.pwd, "Desktop", "file.txt"), "r")
=> #<File...>
File.join(Dir.pwd, "Desktop", "file.txt")
=> "C/Documents and Settings/Users/prince/Desktop/file.txt"
As long as Ruby is doing the work, / in path names is ok on Windows
Once you have to send a path for some other program to use, especially in a command line or something like a file upload in a browser, you have to convert the slashes to backslashes when running in Windows.
C:/projects/a_project/some_file.rb'.gsub('/', '\\') works a charm. (That is supposed to be a double backslash - this editor sees it as an escape even in single quotes.)
Use something like this just before sending the string for the path name out of Ruby's control.
You will have to make sure your program knows what OS it is running in so it can decide when this is needed. One way is to set a constant at the beginning of the program run, something like this
::USING_WINDOWS = !!((RUBY_PLATFORM =~ /(win|w)(32|64)$/) || (RUBY_PLATFORM=~ /mswin|mingw/))
(I know this works but I didn't write it so I don't understand the double bang...)
Take a look at File.join: http://www.ruby-doc.org/core/classes/File.html#M000031
Use the Pathname class to generate paths which then will be correct on your system:
a_path = Pathname.new("a_path_goes_here")
The benefit of this is that it will allow you to chain directories by using the + operator:
a_path + "another_path" + "and another"
Calling a_path.to_s will then generate the correct path for the system that you are on.
Yes, it's annoying as a windows users to keep replacing those backslashes to slashes and vice-versa if you need the path to copy it to your filemanager, so i do it like his.
It does no harm if you are on Linux or Mac and saves a lot of nuisance in windows.
path = 'I:\ebooks\dutch\_verdelen\Komma'.gsub(/\\/,'/')
Dir.glob("#{path}/**/*.epub").each do |file|
puts file
end

A Ruby method for resolving relative paths while keeping absolute paths?

I am working on writing a rake build scrip which will work cross platform ( Mac OSX, Linux , Windows ). The build script will be consumed by a CI server.
I want the logic of my script to be as follows:
If the path is determined to be relative, make it absolute by making output_path = FOO_HOME + user_supplied_relative_path
If the path is determined to be absolute, take it as-is
I'm currently using Pathname.new(location).absolute? but it's not working correctly on windows.
What approach would you suggest for this?
require 'pathname'
(Pathname.new "/foo").absolute? # => true
(Pathname.new "foo").absolute? # => false
The method you're looking for is realpath.
Essentially you do this:
absolute_path = Pathname.new(path).realpath
N.B.: The Pathname module states that usage is experimental on machines that do not have unix like pathnames. So it's implementation dependent. Looks like JRuby should work on Windows.
There is a built-in function that covers both cases and does exactly what you want:
output_path = File.absolute_path(user_supplied_path, FOO_HOME)
The trick is supplying a second argument. It servers as a base directory if (and only if) the first argument is a relative path.
Pathname can do all that for you
require "pathname"
home= Pathname.new("/home/foo")
home + Pathname.new("/bin") # => #<Pathname:/bin>
home + Pathname.new("documents") # => #<Pathname:/home/foo/documents>
I am not sure about this on windows though.
You could also use File.expand_path if the relative directory is relative to the current working directory.
I checked on Linux and windows and didn't have any issues.
Assuming FOO_HOME is the working directory, the code would be:
output_path = File.expand_path user_supplied_relative_path

How can I include Win32 modules only when I'm running my Perl script on Windows?

I have a problem that I cannot seem to find an answer to.
With Perl I need to use a script across Windows and unix platforms. Te problem is that on Windows we use Win32-pecific modules like Win32::Process, and those modules do not exist on unix.
I need a way to include those Win32 modules only on Windows.
if($^O =~ /win/i)
{
use win32::process qw(CREATE_NEW_CONSOLE);
}
else
{
#unix fork
}
The problem lies in that use statement for windows. No matter what I try this does not compile on unix.
I have tried using dynamic evals, requires, BEGIN, etc.
Is there a good solution to this problem? Any help will be greatly appreciated.
Thanks in advance,
Dan
Update:
A coworker pointed out to me this is the correct way to do it.
require Win32;
require Win32::Process;
my $flag = Win32::Process::CREATE_NEW_CONSOLE();
Win32::Process::Create($process,
$program,
$cmd,
0,
$flag, ".") || die ErrorReport();
print "Child started, pid = " . getPID() . "\n";
Thank you all for your help!
Dan
use is executed at compile time.
Instead do:
BEGIN {
if( $^O eq 'MSWin32' ) {
require Win32::Process;
# import Win32::Process qw(CREATE_NEW_CONSOLE);
Win32::Process->import(qw/ CREATE_NEW_CONSOLE /);
}
else {
#unix fork
}
}
See the perldoc for use.
Also see perlvar on $^O.
Update:
As Sinan Unur points out, it is best to avoid indirect object syntax.
I use direct method calls in every case, except, with calls to import. Probably because import masquerades as a built-in. Since import is really a class method, it should be called as a class method.
Thanks, Sinan.
Also, on Win32 systems, you need to be very careful that you get the capitalization of your module names correct. Incorrect capitalization means that symbols won't be imported properly. It can get ugly.use win32::process may appear to work fine.
Are you sure win32::process can be loaded on OSX? "darwin" matches your /win/i.
You may want to use http://search.cpan.org/dist/Sys-Info-Base/ which tries to do the right thing.
That aside, can you post an example of the code that you actually are using, the failure message you're receiving, and on which unix platform (uname -a) ?
What about a parser that modifies the file on each OS?
You could parse your perl file via a configure script that works on both operating systems to output perl with the proper Use clauses. You could even bury the parse action in the executable script to launch the code.
Originally I was thinking of precompiler directives from C would do the trick, but I don't know perl very well.
Here's an answer to your second set of questions:
Are you using strict and warnings?
Did you define an ErrorReport() subroutine? ErrorReport() is just an example in the synopsis for Win32::Process.
CREATE_NEW_CONSOLE is probably not numeric because it didn't import properly. Check the capitalization in your call to import.
Compare these one-liners:
C:\>perl -Mwin32::process -e "print 'CNC: '. CREATE_NEW_CONSOLE;
CNC: CREATE_NEW_CONSOLE
C:\>perl -Mwin32::process -Mstrict -e "print 'CNC: '. CREATE_NEW_CONSOLE;
Bareword "CREATE_NEW_CONSOLE" not allowed while "strict subs" in use at -e line 1.
Execution of -e aborted due to compilation errors.
C:\>perl -MWin32::Process -e "print 'CNC: '. CREATE_NEW _CONSOLE;
CNC: 16
You could just place your platform specific code inside of an eval{}, and check for an error.
BEGIN{
eval{
require Win32::Process;
Win32::Process->import(qw'CREATE_NEW_CONSOLE');
};
if( $# ){ # $# is $EVAL_ERROR
# Unix code here
}
}

Resources