Eiffel: how do I do a system call? - eiffel

Id like to uncompress a file with bzip2 myFile.bz2 which class do I have to use for that?
I tried to find it into base kernel documentation which made the most sense for me and didn't find it

This works:
make
local
l_env:EXECUTION_ENVIRONMENT
do
create l_env
l_env.system ("bzip2 test.txt")
end

My final solution working on linux with pipes is following:
feature -- Commands
piped_command_result (a_command: STRING): detachable PROCESS_COMMAND_RESULT
-- https://groups.google.com/forum/#!topic/eiffel-users/O9KEtBSPrf4
local
l_cmd: READABLE_STRING_32
l_args: ARRAYED_LIST [READABLE_STRING_32]
l_proc: like {BASE_PROCESS_FACTORY}.process_launcher
l_err, l_res: STRING
l_err_spec, l_res_spec: SPECIAL [NATURAL_8]
do
create l_res.make (0)
create l_err.make (0)
create l_res_spec.make_filled (0, 1024)
create l_err_spec.make_filled (0, 1024)
l_cmd := (create {EXECUTION_ENVIRONMENT}).default_shell
if l_cmd.is_empty then
l_cmd := {STRING_32} "/bin/bash" -- or either "/bin/sh"
end
create l_args.make (2)
l_args.extend ("-c")
l_args.extend (a_command)
l_proc := (create {BASE_PROCESS_FACTORY}).process_launcher (l_cmd, l_args, Void)
l_proc.set_hidden (True)
l_proc.set_separate_console (False)
l_proc.redirect_output_to_stream
l_proc.redirect_error_to_stream
l_proc.launch
check
process_launched: l_proc.launched
then
-- read output
from
until
l_proc.has_output_stream_closed or l_proc.has_output_stream_error
loop
l_proc.read_output_to_special (l_res_spec)
append_special_of_natural_8_to_string_8 (l_res_spec, l_res)
end
-- read error
from
until
l_proc.has_error_stream_closed or l_proc.has_error_stream_error
loop
l_proc.read_error_to_special (l_err_spec)
append_special_of_natural_8_to_string_8 (l_err_spec, l_err)
end
l_proc.wait_for_exit
create Result.make (l_proc.exit_code, l_res, l_err)
end
ensure
instance_free: Class
end
feature {NONE} -- Implementation
append_special_of_natural_8_to_string_8 (spec: SPECIAL [NATURAL_8]; a_output: STRING)
local
i,n: INTEGER
do
from
i := spec.lower
n := spec.upper
until
i > n
loop
a_output.append_code (spec[i])
i := i + 1
end
ensure
instance_free: Class
end
Credits to google groups eiffel users
Note that with another user like an app launched by apache, you have to check your environment variables and $PATH so that it can work!

Related

Is there a way to check if any content of a array is in another array in Roblox

So I am trying to make a script which allows me to ban people but the main script which checks if a player is in the game and in the banned users list to be killed or kicked. Here is my code:
local BannedUsers = {"littleBitsman"}
local Players = game.Players:GetChildren()
wait(10)
for index1,value1 in ipairs(Players) do
for index2,value2 in ipairs(BannedUsers) do
if Players[index1] == BannedUsers[tonumber(index2)] then
local HumanoidToKill = workspace[value1].Character:FindFirstChildWhichIsA("Humanoid")
if HumanoidToKill.Health >= 0 then
HumanoidToKill.Health = 0
print("killed " .. tostring(value1))
end
end
end
end
The wait(10) is so I can test the script without executing too early, and the use of my username is for testing.
Also when I do test it it does nothing at all.
You can use the table.find function.
local BannedUsers = {"littleBitsman"}
for _, player in ipairs(game.Players:GetChildren()) do
if table.find(BannedUsers, player.Name) then
player:Kick("You are banned!")
end
end

Eiffel: regular expressions how to do grouping

I'd like to do grouping of regular expressions with eiffel. How do I do something like
l_reg.compile ("^([0-9]{3}) (rabbit[0-9]).*")
l_groups := l_reg.groups ("123 rabbit1")
my_first_rabbit := l_groups.at (2)
Didn't find any example on groups, LX_DFA_REGULAR_EXPRESSION class and other googlings
One solution is to use RX_PCRE_REGULAR_EXPRESSION instead of LX_DFA_REGULAR_EXPRESSION:
Including $ISE_LIBRARY\contrib\library\gobo\library\regexp\src\library.ecf library
l_reg: RX_PCRE_REGULAR_EXPRESSION
...
l_reg.compile ("^([0-9]{3}) (rabbit[0-9]).*")
l_reg.match ("123 rabbit1")
my_first_rabbit := l_reg.captured_substring (2)
There is no groups routine, although it could be implemented by calling captured_substring internally. There is only a routine split which does the reverse: returns the substrings which did not match the regular expression.
Something like
regex_groups (a_haystack, a_needle: STRING): ARRAY[STRING]
-- Test with https://www.regextester.com/1911
require
regex_match (a_haystack, a_needle)
local
l_reg: RX_PCRE_REGULAR_EXPRESSION
l_index: like {RX_PCRE_REGULAR_EXPRESSION}.match_count
do
create Result.make_empty
create l_reg.make
l_reg.compile (a_needle)
if l_reg.is_compiled then
l_reg.match (a_haystack)
from
l_index := 1
until
l_index > l_reg.match_count
loop
Result.extend (l_reg.captured_substring (l_index))
l_index := l_index + 1
end
else
--- error compiling regex
fallible.set_last_error (create {SIT_INTERNAL_ERROR}.make ("regex_group-> regex does not compile:" + a_needle))
end
ensure
not fallible.has_error
instance_free: Class
end
you could test your regex here: https://www.regextester.com/1911

Anaconda (Python) + Cmder (Clink) on Windows - Unify Dueling Custom Prompts

If you run Anaconda on windows, you have an activate.bat file which concludes with this line to put your current conda env on the prompt:
set PROMPT=[%CONDA_DEFAULT_ENV%] $P$G
If you run cmder on windows, there is a nice lua script to customize your prompt:
function lambda_prompt_filter()
clink.prompt.value = string.gsub(clink.prompt.value, "{lamb}", "λ")
end
clink.prompt.register_filter(lambda_prompt_filter, 40)
These two scripts do not play very nicely with each other. Clink has an API that seems like I could use to incorporate the change from activate.bat, but I cannot figure out how to call it from a batch file.
My overall goal is to merge these two prompts into the nicer Cmder-style. My thought is to create an environment variable, change activate.bat to check for the existence of the variable, and, if so, call the Clink API to change the prompt instead of set PROMPT. At that point I would think I could create a new filter to cleanly merge the value in. I can't figure out how to call the API from the batch file, though.
Other solutions welcome.
EDIT: Partial, non-working solution
require "os" -- added to top of file, rest in filter function
local sub = os.getenv("CONDA_DEFAULT_ENV")
if sub == nil then
sub = ""
end
print(sub)
clink.prompt.value = string.gsub(clink.prompt.value, "{conda}", sub)
I added a {conda} in the prompt definition at the very beginning; removed the prompt statement from activate.bat, and added this to git_prompt_filter. Prior to using activate, everything is fine - the {conda} gets suppressed by the ''. However, if I use activate and switch into a folder with a git repo to trigger the change, I see:
{conda}C:\...
Does os.getenv not get user set variables? Don't know what else the problem would be. I also tried adding a print, it doesn't print out the contents of CONDA... either.
This is what I do to reset the prompt and add the conda env name to the prompt:
---
-- Find out the basename of a file/directory (last element after \ or /
-- #return {basename}
---
function basename(inputstr)
sep = "\\/"
local last = nil
local t={} ; i=1
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
--t[i] = str
--i = i + 1
last = str
end
return last
end
---
-- Find out current conda env
-- #return {false|conda env name}
---
function get_conda_env()
env_path = clink.get_env('CONDA_DEFAULT_ENV')
if env_path then
basen = basename(env_path)
return basen
end
return false
end
---
-- after conda activate: reset prompt and add conda env name
---
function conda_prompt_filter()
-- reset to original, e.g. after conda activate destroyed it...
if string.match(clink.prompt.value, "{lamb}") == nil then
-- orig: $E[1;32;40m$P$S{git}{hg}$S$_$E[1;30;40m{lamb}$S$E[0m
-- color codes: "\x1b[1;37;40m"
cwd = clink.get_cwd()
prompt = "\x1b[1;32;40m{cwd} {git}{hg} \n\x1b[1;30;40m{lamb} \x1b[0m"
new_value = string.gsub(prompt, "{cwd}", cwd)
clink.prompt.value = new_value
end
-- add in conda env name
local conda_env = get_conda_env()
if conda_env then
clink.prompt.value = string.gsub(clink.prompt.value, "{lamb}", "["..conda_env.."] {lamb}")
end
end
clink.prompt.register_filter(conda_prompt_filter, 10)
I want to build on #Jan-Schulz answer since it didn't exactly work for me in April 2017.
Instead of editing cmder/vendor/clink/clink.lua I added custom code into cmder/config/prompt.lua which is not overwritten on upgrade (You can add additional modifications to cmder prompt in this file as well using the clink lua api)
I was having an issue where the {lamb} was not being replaced with the proper λ character so I added another filter to run at the end of all processing.
---
-- Find out the basename of a file/directory (last element after \ or /
-- #return {basename}
---
function basename(inputstr)
sep = "\\/"
local last = nil
local t={} ; i=1
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
--t[i] = str
--i = i + 1
last = str
end
return last
end
---
-- Find out current conda env
-- #return {false|conda env name}
---
function get_conda_env()
env_path = clink.get_env('CONDA_DEFAULT_ENV')
if env_path then
basen = basename(env_path)
return basen
end
return false
end
---
-- after conda activate: reset prompt and add conda env name
---
function conda_prompt_filter()
-- reset to original, e.g. after conda activate destroyed it...
if string.match(clink.prompt.value, "{lamb}") == nil then
-- orig: $E[1;32;40m$P$S{git}{hg}$S$_$E[1;30;40m{lamb}$S$E[0m
-- color codes: "\x1b[1;37;40m"
cwd = clink.get_cwd()
prompt = "\x1b[1;32;40m{cwd} {git}{hg} \n\x1b[1;30;40m{lamb} \x1b[0m"
new_value = string.gsub(prompt, "{cwd}", cwd)
clink.prompt.value = new_value
end
-- add in conda env name
local conda_env = get_conda_env()
if conda_env then
clink.prompt.value = string.gsub(clink.prompt.value, "{lamb}", "["..conda_env.."] {lamb}")
end
end
function fix_lamb()
if string.match(clink.prompt.value, "{lamb}") ~= nil then
clink.prompt.value = string.gsub(clink.prompt.value, "{lamb}", "λ")
end
end
clink.prompt.register_filter(conda_prompt_filter, 1)
clink.prompt.register_filter(fix_lamb, 999)
Why not just delete the line from activate.bat and do all the logic in your cmder profile? CONDA_DEFAULT_ENV will be empty if no environment is active.

Delphi 6: How can I change created filedate (= file creation date)

I've been searching now for HOURS on Google (and here).
And I cannot find a solution.
I want to CHANGE the "Created Filetime" (= creation filetime) in DELPHI 6.
Not the "Modified file time" (for which a simple call to "FileSetDate()" is needed)
and not the "Last accessed file time".
How do I do this?
Call the SetFileTime Windows API function. Pass nil for lpLastAccessTime and lpLastWriteTime if you only want to modify the creation time.
You will need to obtain a file handle by calling CreateFile, or one of the Delphi wrappers, so this is not the most convenient API to use.
Make life easier for yourself by wrapping the API call up in a helper function that receives the file name and a TDateTime. This function should manage the low-level details of obtaining and closing a file handle, and converting the TDateTime to a FILETIME.
I would do it like this:
const
FILE_WRITE_ATTRIBUTES = $0100;
procedure SetFileCreationTime(const FileName: string; const DateTime: TDateTime);
var
Handle: THandle;
SystemTime: TSystemTime;
FileTime: TFileTime;
begin
Handle := CreateFile(PChar(FileName), FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, 0);
if Handle=INVALID_HANDLE_VALUE then
RaiseLastOSError;
try
DateTimeToSystemTime(DateTime, SystemTime);
if not SystemTimeToFileTime(SystemTime, FileTime) then
RaiseLastOSError;
if not SetFileTime(Handle, #FileTime, nil, nil) then
RaiseLastOSError;
finally
CloseHandle(Handle);
end;
end;
I had to add the declaration of FILE_WRITE_ATTRIBUTES because it is not present in the Delphi 6 Windows unit.
Based on FileSetDate, you can write a similar routine:
function FileSetCreatedDate(Handle: Integer; Age: Integer): Integer;
var
LocalFileTime, FileTime: TFileTime;
begin
Result := 0;
if DosDateTimeToFileTime(LongRec(Age).Hi, LongRec(Age).Lo, LocalFileTime) and
LocalFileTimeToFileTime(LocalFileTime, FileTime) and
SetFileTime(Handle, #FileTime, nil, nil) then Exit;
Result := GetLastError;
end;

How to traverse a directory in eiffel?

Simple
How can I get a list of the files that are inside directory using eiffel?
For example:
class CARPETAS
creation
make
feature {NONE}
make is
local
directory: DIRECTORY
path: STRING
do
path := "." -- Current directory
!!directory.scan_with(path)
list_directory(directory)
end
list_directory(directory: DIRECTORY) is
local
i: INTEGER
do
std_output.put_string("Content of " + directory.path + "%N")
from
i := directory.lower
until
i > directory.upper
loop
std_output.put_string("%T" + directory.name(i) + "%N")
i := i + 1
end
end
end
with recent version of Eiffel, I would recommend to use DIRECTORY.entries
local
p: PATH
do
across dir.entries as ic loop
p := ic.item.path
-- then use interface of PATH, such as PATH.name
end
end
note that the base_extension library also provides DIRECTORY_VISITOR , which is helpful to iterate recursively on directories

Resources