Time to get to that last menu item: 'S': 'Search country/region names'. We will have a couple of things to sort out, but we can deal with those later. Well, if necessary. But let’s just do something basic for the moment. Get a bit of text (a string) the user wants to search for, execute the search and display the matching values we found.

Another Development Branch

I expect that in the real world, when working on a new development branch, programmers would create a new directory, clone the master branch, create a new branch and work on the code in there. And not in the directory containing the master branch code like I did when refactoring all the chart and database code in the previous several posts. That said, it’s only me working on the code. I don’t expect to be hit with a rush bug fix, or some urgent enhancement. So, I will once again create the branch, search-names, in my py_play directory and go from there. Push comes to shove I can create a new directory and clone the master branch into it.

You may chose to practice the more mainstream approach.

terminal window showing creation of the new branch

Processing the Main Menu’s Search Selection

Like I said start simple. Something like the following.

terminal window showing simple search code results terminal window showing simple search code results for a longer list of matching results

For our purposes the bulk of the work was done some time back when we wrote database/rc_names.py. Don’t forget to deal with the ’no search results found’ situation. The code for the search menu item in population_by_age.py now looks like this:

    elif u_choice.upper() == 'S':
      srch_txt = input("Please enter the text you'd like to search for: ")
      fnd_nms = rcn.find_names(srch_txt)
      if fnd_nms:
        # print blank line between menu input and search results
        print(f"\n{fnd_nms}")
      else:
        print("\nNo search results found!")        

Paging Lengthy Output

The problem I have now is figuring out how to present the list when it is lengthy. And, should I allow the user to somehow select a country and use it for a chart. Was thinking about doing something like git log does. Though not sure how it knows how much to print to get a screenful at a time.

Well, after some web searching, turns out the pydoc module has a function, pager(), that takes care of the hard work. But it needs a text string with linebreaks to function properly. But, if I wanted to allow the user to select a displayed name for charting using pydoc.pager() won’t allow me to do so. But, just for fun, let’s have a look at what it does offer.

At the top of the file I imported the function: from pydoc import pager. Then modified the menu item code to use it. But, I also wanted to have a line count for each name just to see how things were working. So, I added a list comprehension to add an incrementing line number in front of each name. The built-in function enumerate() came in handy here.

    elif u_choice.upper() == 'S':
      srch_txt = input("Please enter the text you'd like to search for: ")
      fnd_nms = rcn.find_names(srch_txt)
      if fnd_nms:
        # put an incrementing line number in front of each country/region name
        nbr_nms = [ f"{i}: {rnm}" for i, rnm in enumerate(fnd_nms, start=1) ]
        # pager() needs sting with linebreaks to function properly
        lns_nms = '\n'.join(nbr_nms)
        # print blank line between menu input and search results, looks nicer
        pager(f"\n{lns_nms}")
      else:
        print("\nNo search results found!")

So, I ran the app in an Anaconda terminal window. Selected ‘S’ and searched for ‘un’.

Here’s the terminal window just before the search is initiated. terminal window showing search steps prior to display of search results And, the first page of search results as output by pydoc.pager(). 1st page of search results as generated by pydoc.pager() At this point hitting Enter will display the next line of search results, hitting the spacebar will display the next page or all the remaining results if less than a page, and pressing q will exit the pager and return to the menu. In this case, page is the number of lines available on the terminal less one. Need room for the ‘–– More ––’ prompt at the bottom of the window.

After pressing “Enter” the bottom of the screen scrolled one item:

28: UNICEF Regions: Sub-Saharan Africa
29: UNICEF Regions: West and Central Africa
30: UNICEF Regions: Western Europe
-- More  --

And, after pressing ‘Q’:

28: UNICEF Regions: Sub-Saharan Africa
29: UNICEF Regions: West and Central Africa
30: UNICEF Regions: Western Europe

        Please make a selection:
                A: About
                C: Plot chart
                S: Search country/region names
                X: Exit the application
        Your selection:

A lot tidier than simpling printing the array. And, the user (me, us, we) could use copy and paste to get the name we need. But, might be nicer if we could somehow just select the name we want and let the menu system deal with it.

Done I Think

I had originally planned to go further in this post with the idea of selecting a name from the presented search results. But, on reflection, the post subject is essentially complete.

I had thought I could use the ‘line’ numbers next to each name to tell the app which country I wanted to plot. But, that might preclude using pydoc.pager() for paging the search output. And would likely involve a lot of new code. Probably considerably more than reasonable for inclusion in this post.

And, I am kind of leaning toward the cut and paste solution. It is simple. At any rate the menu search item basically works as intended.

Take care and be safe!

Resources