1. New and having problems
- Posted by mollusk May 18, 2016
- 1969 views
So I decided Euphoria was something worth checking out and wanted to port a small project over from ruby. Needless to say I have been having problems which I am sure is part of being new to the language and my own terrible logic when it comes to working things out.
So the program is supposed to be simple: a program that can take multiple command line arguments and pass them to my package manager. The goal is to make a basic package manager wrapper and so far I have had more problems doing it in Euphoria than in Ruby due to all the difference in syntax. I am just not used to the Euphoria ways of doing things quite yet.
Here is the code with which I am having problems. All this code is supposed to do is take command line arguments and pass them to a variable which is then passed to the system(). The problem is that when I run my program (e.g myprog -i gimp firefox) only the second argument after -i is being read but if I take away the second argument, then gimp in the example will be read.
The goal is to have everything read and passed to the package manager. One big long string of words!
include std/io.e include std/console.e include std/os.e include std/cmdline.e global sequence cmd = command_line() global sequence pkgargs for i = 4 to length(cmd) do --start at 4 to skip the first few arguments pkgargs = cmd[i] end for switch cmd[3] do --start at 3 to capture -i case "-i" then printf(1,"%s\n",pkgargs) --a debug line to print pkgargs system ("sudo xbps-install " & pkgargs,2) --simply passing pkgargs to system end switch
The debug line only prints out the first character of the word it was given. So if I typed 'gimp' it would print 'g'. I thought it would print the full word or the full list of arguments in pkgargs but I was wrong and I don't know why this is happening.
Overall though I have the feeling that I am doing something very wrong that is simple to fix but instead of spending the next several days tearing my hair out I decided to ask for help.
Thanks for helping, I am glad to be here.
2. Re: New and having problems
- Posted by peterR May 18, 2016
- 1933 views
Hi Mollusk
It's probably easiest to answer this by copy-pasting from the depths of the manual:
Comments
Watch out for the following common mistake, in which the intention is to output all the characters in the third parameter but which ends up by only outputing the first character ...
include std/io.e sequence name="John Smith" printf(STDOUT, "My name is %s", name)
The output of this will be My name is J because each format specifier uses exactly one item from the values parameter. In this case we have only one specifier so it uses the first item in the values parameter, which is the character 'J'. To fix this situation, you must ensure that the first item in the values parameter is the entire text string and not just a character, so you need code this instead:
include std/io.e name="John Smith" printf(STDOUT, "My name is %s", {name})
Now, the third argument of printf() is a one-element sequence containing all the text to be formatted.
Also note that if there is only one format specifier then values can simply be an atom or integer.
Also, I think there's a problem with your for loop. It keeps overwriting the arguments instead of concatenating them (so the problem only shows up when you have more than one arg). For your system call you need a single sequence (a string). Initialise pkgargs to an empty string before the loop, and then concatenate it with the commands on each iteration (don't forget the space) - e.g. pkgargs = pkgargs & cmd[i] & " ", or even better, pkgargs &= cmd[i] & " ". PeterR
Edit: Fixed formatting for you. -Greg
3. Re: New and having problems
- Posted by peterR May 18, 2016
- 1926 views
Sorry, look like a messed up the formatting again - it didn't show up on the preview. Ignore the line through the text. Peter R
4. Re: New and having problems
- Posted by mollusk May 18, 2016
- 1917 views
Hi Mollusk
It's probably easiest to answer this by copy-pasting from the depths of the manual:
----------------
Comments:
Watch out for the following common mistake, in which the intention is to output all the characters in the third parameter but which ends up by only outputing the first character ...
include std/io.e sequence name="John Smith" printf(STDOUT, "My name is %s", name)
The output of this will be My name is J because each format specifier uses exactly one item from the values parameter. In this case we have only one specifier so it uses the first item in the values parameter, which is the character 'J'. To fix this situation, you must ensure that the first item in the values parameter is the entire text string and not just a character, so you need code this instead:
include std/io.e name="John Smith" printf(STDOUT, "My name is %s", {name})
Now, the third argument of printf() is a one-element sequence containing all the text to be formatted.
Also note that if there is only one format specifier then values can simply be an atom or integer.
-------
Also, I think there's a problem with your for loop. It keeps overwriting the arguments instead of concatenating them (so the problem only shows up when you have more than one arg). For your system call you need a single sequence (a string). Initialise pkgargs to an empty string before the loop, and then concatenate it with the commands on each iteration (don't forget the space) - e.g. pkgargs = pkgargs & cmd[i] & " ", or even better, pkgargs &= cmd[i] & " ".
PeterR
This is what I was missing! I had tried to initiate pkgargs before the loop once before but I was really missing the concatenation (the most important part). Thank you for saving me many hours. The new code looks like this:
include std/io.e include std/console.e include std/os.e include std/cmdline.e global sequence cmd = command_line() global sequence pkgargs pkgargs = " " for i = 4 to length(cmd) do --start at 4 to skip the first few arguments pkgargs &= cmd[i] & " " end for switch cmd[3] do --start at 3 to capture -i case "-i" then printf(STDOUT,"%s\n",{pkgargs}) --a debug line to print pkgargs system ("sudo xbps-install " & pkgargs,2) --simply passing pkgargs to system end switch
I will probably be back for more questions though since the next task is to tie this in with my iteration over the package managers themselves and then ultimately reading a file and using it's variables to set the proper bindings.
Just to show the package iteration script I made that is going to tie into the one you helped fix, here it is.
include std/io.e include std/filesys.e global sequence pmlist = {"apt","apt-get","yum","dnf","equo","xbps-install"} global sequence pkmgr --create variable to store found package manager global sequence gogo --Variable to bind 'PkIterate' to later and use it to evaluate return global function PkIterate() for i=1 to length(pmlist) do pkmgr = locate_file(pmlist[i]) if file_exists(pkmgr) then return pkmgr else end if end for return "false" end function gogo = PkIterate() if compare(gogo,"false") != 0 then puts(1,gogo &"\n") else puts(1, "No package manager found\n") end if
I still have a long way to go and a lot to learn. Once I get everything put together the hope is to have a modular wrapper for package managers that can read bindings from multiple config files and use the commands in the config to pass onto the package manager.
5. Re: New and having problems
- Posted by SDPringle May 18, 2016
- 1898 views
Hello I am a volunteer developer of Euphoria. Can you please tell us what attracted you to Euphoria in particular? Why are you not using Ruby?
The manual details a function for parsing command arguments. Remember that everything is pass by value (or simulated pass by value).
SD Pringle
6. Re: New and having problems
- Posted by _tom (admin) May 18, 2016
- 1896 views
In "Ruby thinking" there is a tendency to invent a new convenient rule for every situation. If your mind works like that of Matsumoto, then these "rules" effectively do not exist and you become a fan of Ruby. If you study how Ruby is put together you will find lots of inconsistencies, but if you think in Ruby then these inconsistencies are why you use Ruby.
In "Euphoria thinking" there are just a few rules that work the same all the time. The "charm" of Euphoria is that you don't have to put lots of ideas into your head, and when everything works the same, all the time, you reduce "congnitive load" and your brain feels better.
object stuff -- "%s" means output **one** //item//; THAT IS THE RULE -- the 's' means in 'string format' -- sorry, the "s" was borrowed from "C" syntax printf(1, "%s", "hello" ) --> h -- "hello" is a sequence with **five** items -- one item; THE RULE IS FOLLOWED printf(1, "%s", { "hello" } ) --> hello -- { "hello" } is a sequence with **one** item -- one item; THE RULE IS FOLLOWED
I something is "going wrong" in Euphoria, it is because you forgot the RULE IS THE SAME ALL THE TIME.
As SDPringle just mentioned take a look at:
include std/cmdline.e
cmd_parse()
You can concatenate command line arguments together, or you an join them:
-- must execute this demo this some command line arguments... -- for example $ eui demo -i foo moo include std/sequence.e include std/console.e sequence cmd = command_line() display( cmd ) /* { "eui", "demo", "-i", "foo", "moo" } */ sequence arg = join( cmd[4..$], " " ) display( arg ) --> foo moo
_tom
7. WRe: New and having problems
- Posted by irv May 18, 2016
- 1880 views
locate_file will need some help, and file_exists may not be the best choice. Try file_type(locate(file(...
file_type will return 0 for "not found', 1 for 'file', and 2 for 'folder'. There's a chance someone might have a folder somewhere with a name the same as one of the listed pkg managers.
8. Re: New and having problems
- Posted by mollusk May 18, 2016
- 1867 views
Hello I am a volunteer developer of Euphoria. Can you please tell us what attracted you to Euphoria in particular? Why are you not using Ruby?
The manual details a function for parsing command arguments. Remember that everything is pass by value (or simulated pass by value).
SD Pringle
Euphoria has a plentiful standard library, it can be compiled or interpreted, it can run on ARM, it's portable, it's under a BSD license, it's pretty simple to pick up for most people. Now it just needs an interactive interpreter (it may already have one) like irb, python and lua.
9. Re: New and having problems
- Posted by _tom (admin) May 19, 2016
- 1841 views
Hello I am a volunteer developer of Euphoria. Can you please tell us what attracted you to Euphoria in particular? Why are you not using Ruby?
The manual details a function for parsing command arguments. Remember that everything is pass by value (or simulated pass by value).
SD Pringle
Euphoria has a plentiful standard library, it can be compiled or interpreted, it can run on ARM, it's portable, it's under a BSD license, it's pretty simple to pick up for most people. Now it just needs an interactive interpreter (it may already have one) like irb, python and lua.
I a curious, why do you want an interactive interpreter? Is there a real application for interactive mode?
I haven't worked with irb, but in the case of Python my observations are:
Python was designed to be a "teacher's language." That means it has features that make a teacher happy like: the interactive mode, and controversial syntax. Interactive mode is good for the first few lessons in a Python course--it gives teachers something to do. The strange Python syntax is good for people marking Python code--easy on the marker's eyes and has just enough oddities to trick students and allow them to fail. They get stuck with it, but learners and users do not want a teacher's language.
Get the WEE editor. You can enter the command line arguments into the editor and then execute code. Because Euphoria is fast you do not need a slow interactive mode. You get a hard-copy of your test code--writing disposable code that vanishes is described as a feature when you use Python in interactive mode. Writing code with WEE is better than interactive mode.
For example, pretending to be newby, I offer this interative help session on Python:
To get a list of available modules, keywords, or topics, type "modules", "keywords", or "topics". Each module also comes with a one-line summary of what it does; to list the modules whose summaries contain a given word such as "spam", type "modules spam". help> spam no Python documentation found for 'spam' help> modules spam Here is a list of matching modules. Enter any module name to get more help. help>
Yes, I should know better, but I feel this help system is overrated.
Friendly | Flexible | Fast
I am trying to develop Friendly, Flexible, Fast as the unique signature for Euphoria. (Phix is can also be called Friendly | Flexible | Fast.)
Using your words in my framework I get this:
Friendly
"it's pretty simple to pick up for most people."
Flexible
"Euphoria has a plentiful standard library, it can be compiled or interpreted, it can run on ARM, it's portable, it's under a BSD license, "
Fast
Not mentioned. (I get the impression that most people like slow sluggish languages.) Is a fast Euphoria better than a interactive interpreter?
_tom
10. Re: New and having problems
- Posted by mollusk May 19, 2016
- 1766 views
I did forget to mention fast which is something I tend not to find in something like python. Further while claiming to be easier to use, python has sure confused the heck out of me many times before. I always found stuff like init(self) to be confusing to look at. Sure experienced python programmers understand the strange syntax, but it always made me feel pretty uncomfortable. Python is not for me, I never liked the white space concept (for one thing) and I never will. It was just nice to type python in terminal and experiment with something by itself real quick to make sure it works. I don't really need or care that much about it but it was nice to have sometimes.
I downloaded wee but it had a runtime error which seemed to be related to incorrect syntax. So I moved on to something else and ended up using vim, then kate. I would like to get wee working one of these days and can share the error I got later in a different thread.
EDIT: By the way, is there an IRC channel available? I usually have trouble learning from documentation alone and having a chat room would be helpful for me as a slow learner.
11. Re: New and having problems
- Posted by ryanj May 20, 2016
- 1749 views
I did forget to mention fast which is something I tend not to find in something like python. Further while claiming to be easier to use, python has sure confused the heck out of me many times before. I always found stuff like init(self) to be confusing to look at. Sure experienced python programmers understand the strange syntax, but it always made me feel pretty uncomfortable. Python is not for me, I never liked the white space concept (for one thing) and I never will. It was just nice to type python in terminal and experiment with something by itself real quick to make sure it works. I don't really need or care that much about it but it was nice to have sometimes.
I downloaded wee but it had a runtime error which seemed to be related to incorrect syntax. So I moved on to something else and ended up using vim, then kate. I would like to get wee working one of these days and can share the error I got later in a different thread.
EDIT: By the way, is there an IRC channel available? I usually have trouble learning from documentation alone and having a chat room would be helpful for me as a slow learner.
I have used euphoria for years, and i really like the simple syntax. It's easy to read and understand.
There is a #euphoria chatroom on freenode.net. I'm one of the few people who still hang out in there, if you want to chat.
12. Re: New and having problems
- Posted by _tom (admin) May 20, 2016
- 1895 views
I did forget to mention fast which is something I tend not to find in something like python. Further while claiming to be easier to use, python has sure confused the heck out of me many times before. I always found stuff like init(self) to be confusing to look at. Sure experienced python programmers understand the strange syntax, but it always made me feel pretty uncomfortable. Python is not for me, I never liked the white space concept (for one thing) and I never will. It was just nice to type python in terminal and experiment with something by itself real quick to make sure it works. I don't really need or care that much about it but it was nice to have sometimes.
I downloaded wee but it had a runtime error which seemed to be related to incorrect syntax. So I moved on to something else and ended up using vim, then kate. I would like to get wee working one of these days and can share the error I got later in a different thread.
EDIT: By the way, is there an IRC channel available? I usually have trouble learning from documentation alone and having a chat room would be helpful for me as a slow learner.
Easy to Learn
Kernighan and Ritchie describe C as "It is easy to learn, and it wears well as on's [sic] experience with it grows." in the preface to their book on C programming.
Just about every Python book says Python is easy to learn (and some toss in fast).
You should find Euphoria to be genuinely "easy to learn." The syntax is easier on the eyes and there is less clutter in the syntax. Learning to use just atom-sequence means problems often reduce to two choices--if you choose wrong then pick the other option.
Ultimately, the personality of the programmer must match the personality of the computer language.
WEE
Please describe you problems in another thread. We want WEE to be newby ready.
Forum
The Forum tends to be the exclusive way to ask for help.
If you can chat with Ryanj you will have expert help. I haven't got around to trying IRC yet.
If you have any (small or trivial) problems with the documentation then just complain here.
Ruby
Not that I know Ruby, but if you post a code sample in Ruby and then your Euphoria effort it may be easier to explain the Euphoria way of doing things.
_tom
13. Re: New and having problems
- Posted by mollusk May 20, 2016
- 1784 views
I must have been using an old archive of WEE previously as the github version works fine. As for Ruby code, I wrote the same application in Ruby that I am trying to write in Euphoria which you can find at https://gitlab.com/silvernode/tux.git
14. Re: New and having problems
- Posted by _tom (admin) May 24, 2016
- 1755 views
- I tried to run you Ruby code, but with no luck.
- I compiled Ruby
$ ruby -v ruby 2.3.1p112 (2016-04-26 revision 54768) [i686-linux]
- result of running tux.rb
$ ./tux.rb ./tux.rb:59:in `<main>': undefined method `[]=' for nil:NilClass (NoMethodError)
Looking at your code, and trying some Euphoria code.
- file PklgMgrs.rb
This looks like database. The identifiers with a prefixed $ are global in scope.
The def is declaring a routine (procedure in this example).
I often nest stuff like this into one sequence.
#!/usr/bin/env ruby #Add your package managers here $fedoraBased="dnf" $rhelBased="yum" $debianBased="apt-get" $archLinux="pacman" $voidLinux="xbps-install" $sabayon="equo" $opensuse="zypper" #command binding methods for different package managers def dnf() $installCmd = "dnf install" $reinstallCmd = "dnf reinstall" $searchCmd = "dnf search" $updateCmd = "dnf upgrade" $syncCmd = "dnf --refresh check-update" $syncANDupdateCmd = "dnf --refresh upgrade" $refreshSyncCmd = "dnf --refresh check-update" $removeCmd = "dnf remove" $recursiveRemoveCmd = "dnf remove" $checkUpdatesCmd = "dnf check-update" $cleanCmd = "dnf autoremove" end def yum() $installCmd = "yum install" $reinstallCmd = "yum reinstall" $searchCmd = "yum search" $updateCmd = "yum update" $syncCmd = "yum check-update" $syncANDupdateCmd = "yum check-update; yum update" $refreshSyncCmd = "yum check-update" $removeCmd = "yum remove" $recursiveRemoveCmd = "yum remove" $checkUpdatesCmd = "yum check-update" $cleanCmd = "yum autoremove" end def pacman() $installCmd = "pacman -S" $reinstallCmd = "pacman -S --force" $searchCmd = "pacman -Ss" $updateCmd = "pacman -Su" $syncCmd = "pacman -Sy" $syncANDupdateCmd = "pacman -Syu" $refreshSyncCmd = "pacman -Syy" $removeCmd = "pacman -R" $recursiveRemoveCmd = "pacman -Rdd" $checkUpdatesCmd = "checkupdates" $cleanCmd = "pacman -Rsn $(pacman -Qdtq)" end def apt_get() $installCmd = "apt install" $reinstallCmd = "apt install --reinstall" $searchCmd = "apt search" $updateCmd = "apt upgrade" $syncCmd = "apt update" $syncANDupdateCmd = "apt update; sudo apt upgrade" $refreshSyncCmd = "apt update" $removeCmd = "apt remove" $recursiveRemoveCmd = "apt remove --purge" $cleanCmd = "apt autoremove" end def xbps_install() $installCmd = "xbps-install" $reinstallCmd = "xbps-install -f" $searchCmd = "xbps-query -Rs" $updateCmd = "xbps-install -u" $syncCmd = "xbps-install -S" $syncANDupdateCmd = "xbps-install -Su" $refreshSyncCmd = "xbps-install -f -S" $removeCmd = "xbps-remove" $recursiveRemoveCmd = "xbps-remove -f" $cleanCmd = "xbps-remove -O" end def equo()
In Euphoria sequences can be used in a variety of ways:
export enum installCmd, reinstallCmd, searchCmd, updateCmd, syncCmd, syncANDupdateCmd, refreshSyncCmd, removeCmd, recursiveRemoveCmd, cleanCmd -- I assume the same commands in the same order for all package managers -- you get a list of constants numbered starting with value one -- ( no need to capitalize a constant like in Ruby ) -- ( no need to use all caps as is the convention for some languages.) export sequence managers = { { "dnf", -- fedoraBased {"dnf install", "dnf reinstall", "dnf search", "dnf upgrade", "dnf --refresh check-update", "dnf --refresh upgrade", "dnf --refresh check-update", "dnf remove", "dnf remove", "dnf check-update", "dnf autoremove", } }, -- add more as needed { "apt_get", { "apt install" "apt install --reinstall" "apt search" "apt upgrade" "apt update" "apt update; sudo apt upgrade" "apt update" "apt remove" "apt remove --purge" "apt autoremove" } }, { "$sabayon="equo", -- saybayon { "equo i" "equo i" "equo s" "equo u" "equo up" "equo up && sudo equo u" "equo update --force" "equo rm" "equo rm --norecursive" "equo cleanup" } }, -- all items followed by , if you use $ end marker $ } -- the $ end marker lets you update a list easily -- the comment line double dash can go anywhere to the right of code -- now the database is in an isolated scope -- rather than make variables global, you "export" them to just the file -- that includes this database (result is in less name pollution.) -- you can name this file PkgMgrs.e -- the .e extension suggests that it is to be used as an include file -- (but, the extension is optional, or could be anything you choose) -- you execute "$ eui PkmMgrs.e" to test for typos -- again, the .e extension is not important -- every file that wants access to this database will include this file -- instead of making everything global
- which.rb
#!/usr/bin/env ruby # Cross-platform way of finding an executable in the $PATH. # # which('ruby') #=> /usr/bin/ruby def which(cmd) exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : [''] ENV['PATH'].split(File::PATH_SEPARATOR).each do |path| exts.each { |ext| exe = File.join(path, "#{cmd}#{ext}") return exe if File.executable?(exe) && !File.directory?(exe) } end return nil end
Not going to try an figure out this Ruby code; instead just copied your code snippet.
using your first example
include std/filesys.e include std/io.e include std/console.e include PkgMgrs.ex export function PkIterate() object packmgr = 0 for i=1 to length(managers) do packmgr = locate_file( managers[i][1] ) if file_exists(packmgr) then return packmgr end if end for return 0 end function -- test this function --------------------------------------------------------------------- -- this file is intended to be an include file so it has no executable code -- however, I often tack on a few test lines to evaluate the routines -- then comment out when debugging is finished -- to test this code -- remove the /* */ multiline comments -- $ eui which.e object pkmgr = PkIterate() if atom( pkmgr ) then display( "\n no manager found" ) else display( "\nfound " & PkIterate() ) end if -- ok, this found apt-get on my Mint Linux
Now re-write this to use the suggestion by Irv Mullins:
-- use Irv Mullin's idea -- use file_type to evaluate your return value include std/filesys.e include std/io.e include std/console.e include PkgMgrs.ex export function PkIterate() for i=1 to length( managers ) do sequence pkmgr = locate_file( managers[i][1] ) if file_type( pkmgr ) = 1 then return i end if end for return 0 end function -- test this function --------------------------------------------------------------------- -- this file is intended to be an include file, so it has no executable code -- however, I often tack on a few test lines to evaluate the routines -- then comment out when debugging is finished object test = PkIterate() display( test ) display( managers[test][1] ) -- ok, apt-get is on my Mint Linux
Often we just remember that zero means false and not zero means true. Code is easier to understand if you define
constant FALSE = 0 constant TRUE = 1
(Usually too lazy to do this...)
This leaves you main file to decode. No time for this now.
The database file may require a re-write after I understand your main file. But, that is part of program development.
_tom