1. New and having problems

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.

new topic     » topic index » view message » categorize

2. Re: New and having problems

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

new topic     » goto parent     » topic index » view message » categorize

3. Re: New and having problems

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

new topic     » goto parent     » topic index » view message » categorize

4. Re: New and having problems

peterR said...

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.

new topic     » goto parent     » topic index » view message » categorize

5. Re: New and having problems

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

new topic     » goto parent     » topic index » view message » categorize

6. Re: New and having problems

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

new topic     » goto parent     » topic index » view message » categorize

7. WRe: New and having problems

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.

new topic     » goto parent     » topic index » view message » categorize

8. Re: New and having problems

SDPringle said...

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.

new topic     » goto parent     » topic index » view message » categorize

9. Re: New and having problems

mollusk said...
SDPringle said...

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

new topic     » goto parent     » topic index » view message » categorize

10. Re: New and having problems

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.

new topic     » goto parent     » topic index » view message » categorize

11. Re: New and having problems

mollusk said...

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.

new topic     » goto parent     » topic index » view message » categorize

12. Re: New and having problems

mollusk said...

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

new topic     » goto parent     » topic index » view message » categorize

13. Re: New and having problems

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

new topic     » goto parent     » topic index » view message » categorize

14. Re: New and having problems

  • 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

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu