How can you read Text from standard input in Unison?
You can read Text with io.console.getLine; from the doc example:
use Text ++
printLine "Important question: what's your favorite type of pie?"
printLine "> "
pie = !getLine
printLine (pie ++ "!? No way, me too!!! 🎉")
And as you can see in the example, you can print a line of Text with io.console.printLine.
Related
I am a student working on my first CLI project with Ruby, and there is a website I am trying to scrape with Nokogiri. The contents of the website are not strictly organized into their own classes/id, but there is some information that I simply cannot figure out how to scrape.
This is what it looks like:
<p>
<strong> First Aired:</strong>
"2017 | "
<strong> Episodes:</strong>
" 24"
<br>
I want to know if there is a way to scrape the string that comes after each "Episode:" element. The code I tried was
doc = Nokogiri::HTML(open(https://www.techradar.com/best/best-anime))
doc.css('p strong')[1].text <= and that got me the "Episodes:"
then i tried:
doc.css('p strong')[1].next_element <= and it skipped the string and gave me "<br>
I also tried the .children method, but that also returned "Episodes:". I think I am confusing a lot of terms since these methods have no effect on the string. Is it even possible to grab that string with CSS? Lastly, if that were possible to grab, it there a way to grab only the strings after "Episodes:"?
I appreciate any help. I tried to do some research on Nokogiri and Css, but I think I am confusing a lot of things.
HTML is heirarchical, so for all the elements you pasted, p is the parent, and the others are its children. This is especially apparent if the HTML is properly formatted and indented.
This means that you will find the " 24" under p, like this:
html = <<~STR
<p>
<strong> First Aired:</strong>
"2017 | "
<strong> Episodes:</strong>
" 24"
<br>
STR
html_doc = Nokogiri::HTML.parse(html)
p_element = html_doc.css('p')
p_element.children.map(&:name)
# => ["text", "strong", "text", "strong", "text", "br", "text"]
p_element.children.map(&:to_s)
# => [
# "\n ",
# "<strong> First Aired:</strong>",
# "\n \"2017 | \"\n ",
# "<strong> Episodes:</strong>",
# "\n \" 24\"\n ", <------------ this is what you wanted
# "<br>",
# "\n"
# ]
p_element.children[4]
=> #(Text "\n \" 24\"\n ")
If you want the sibling element immediately after one that has "Episodes:" in it, one way is to do this:
consecutive_pairs = p_element.children.each_cons(2)
_before, after = consecutive_pairs.detect do |before, after|
before.text.include?("Episodes")
end
after
# => #(Text "\n \" 24\"\n ")
This question already has an answer here:
Return the first line of a String in Haskell
(1 answer)
Closed 8 years ago.
Just a simple question, my code is complete. It takes an input file, breaks it into lines, reads the file line by line, does the conversions, which is in this case, turns certain things into HTML format (ex: #This is a line into a line with H1 HTML tags, formatting it into a header). The only thing I have left is to take the First line of code, and print that code into the browser tab. Also, the body, or tail must be printed into the window, not the tab. So the first line of my .txt file is The Title! which I want to show in the tab of the web browser. Here is something I have for that:
formatToHTML :: String -> String
formatToHTML [] = []
formatToHTML x
| head x == --any char = "<title>" ++ head ++ "</title>"
| tail x == --rest of file = "<body>" ++ tail ++ "</tail>"
| otherwise = null
or
formatToHTML :: [String] -> String
formatToHTML = unlines. map (show) "<title>" ++ head ++ </title>" $ lines
I dont want to, or I think even need to use guards here, but I cant think of a shorter way to do my task.
I would call this from my main method before I output my file to html.
Also, I know its a amateur haskell question. but how would I represent any char. Say, I want to say, if the head of x exists, print the head with the title tags. print tail with body tags. Help? Thank You
My guess of what you want is:
formatHtml :: [String] -> String
formatHtml [] = ""
formatHtml (x:xs) = unlines theLines
where theLines = [ "<title>" ++ ...convert x to html... ++ "</title>",
"<body>" ] ++ map toHtml xs ++ [ "</body>" ]
toHtml :: String -> String
toHmtl str = ...converts str to HTML...
Example:
formatHtml [ "the title", "body line 1", "body line2" ]
results in:
<title>the title</title>
<body>
body line 1
body line 2
</body>
You still have to define the toHtml function and decide how to convert the first line to the inner html of the tag.
I had a question concerning some basic transformations in Haskell.
Basically, I have a written Input file, named Input.md. This contains some markdown text that is read in my project file, and I want to write a few functions to do transformations on the text. After completing these functions under a function called convertToHTML, I have output the file as an .html file in the correct format.
module Main
(
convertToHTML,
main
) where
import System.Environment (getArgs)
import System.IO
import Data.Char (toLower, toUpper)
process :: String -> String
process s = head $ lines s
convertToHTML :: String -> String
convertToHTML str = do
x <- str
if (x == '#')
then "<h1>"
else return x
--convertToHTML x = map toUpper x
main = do
args <- getArgs -- command line args
let (infile,outfile) = (\(x:y:ys)->(x,y)) args
putStrLn $ "Input file: " ++ infile
putStrLn $ "Output file: " ++ outfile
contents <- readFile infile
writeFile outfile $ convertToHTML contents
So,
How would I read through my input file, and transform any line that starts with a # to an html tag
How would I read through my input file once more and transform any WORD that is surrounded by _word_ (1 underscore) to another html tag
Replace any Character with an html string.
I tried using such functions such as Map, Filter, ZipWith, but could not figure out how to iterate through the text and transform each text. Please if anybody has any suggestions. I've been working on this for 2 days straight and have a bunch of failed code to show for a couple of weeks and have a bunch of failed code to show it.
I tried using such functions such as Map, Filter, ZipWith, but could not figure out how to iterate through the text and transform each text.
Because they work on appropriate element collection. And they don't really "iterate"; you simply have to feed the appropriate data. Let's tackle the # problem as an example.
Our file is one giant String, and what we'd like is to have it nicely split in lines, so [String]. What could do it for us? I have no idea, so let's just search Hoogle for String -> [String].
Ah, there we go, lines function! Its counterpart, unlines, is also going to be useful. Now we can write our line wrapper:
convertHeader :: String -> String
convertHeader [] = [] -- that prevents us from calling head on an empty line
convertHeader x = if head x == '#' then "<h1>" ++ x ++ "</h1>"
else x
and so:
convertHeaders :: String -> String
convertHeaders = unlines . map convertHeader . lines
-- ^String ^[String] ^[String] ^String
As you can see the function first converts the file to lines, maps convertHeader on each line, and the puts the file back together.
See it live on Ideone
Try now doing the same with words to replace your formatting patterns. As a bonus exercise, change convertHeader to count the number of # in front of the line and output <h1>, <h2>, <h3> and so on accordingly.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I would like to output a table in html format.
Basically I would like something like :
[[a]] -> <table>
What is the easiest way to do so ?
The easiest way to generate Html is probably blaze:
import Text.Blaze.Html5 (table, td, tr, toHtml, ToMarkup, Html)
import Control.Monad (forM_, mapM_)
myTable :: (ToMarkup a) => [[a]] -> Html
myTable xs = table $ forM_ xs (tr . mapM_ (td . toHtml))
Note that you need to use renderHtml from Text.Blaze.Renderer.* to get a ByteString, String or Text.
Edit: During writing the answer #Zeta already posted a better solution using blaze-html. So I recommend using his solution (see section "Words of Warning" for the listening of this solutions disadvantages...) ;-)
Here is an implementation:
-- file test.hs:
insideTag :: String -> String -> String
insideTag tag content = "<" ++ tag ++ ">" ++ content ++ "</" ++ tag ++ ">"
toTable :: Show a => [[a]] -> String
toTable = insideTag "table" . concatMap (insideTag "tr") . map (concatMap (insideTag "td" . show))
main :: IO ()
main = do
putStrLn $ toTable [[1,2,3],[4,5,6],[7,8,9]]
return ()
The command runhaskell test.hs will now print
<table><tr><td>1</td><td>2</td><td>3</td></tr><tr><td>4</td><td>5</td><td>6</td></tr><tr><td>7</td><td>8</td><td>9</td></tr></table>
Explanation of the code
insideTag encapsulates content inside a html tag:
ghci> let insideTag tag content = "<" ++ tag ++ ">" ++ content ++ "</" ++ tag ++ ">"
ghci> insideTag "h1" "hello world"
"<h1>hello world</h1>"
map (concatMap (insideTag "td" . show)) list encapsulate the inner elements into <td> tags and concatenate them:
ghci> map (concatMap (insideTag "td" . show)) [[1,2], [3,4]]
["<td>1</td><td>2</td>","<td>3</td><td>4</td>"]
The same can be done for the outer list:
ghci> concatMap (insideTag "tr") ["<td>1</td><td>2</td>","<td>3</td><td>4</td>"]
"<tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr>"
The last string only has to be encapsulate into a <table> tag:
ghci> insideTag "table" "<tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr>"
"<table><tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr></table>"
Words of warning
The above code uses the normal [Char] type for strings which is not memory efficient. So I recommend that you use Data.Text if you deal with big tables (toTable remains the same, you just have to change show to pack . show; insideTag has to reimplemented for Data.Text).
There is also no HTML escaping for the table content!!! So the above code is vulnerable to XSS attacts. So do not use the above code, if the produced HTML shall be included in a website (especially if the website user has an influence on the table content)!
Often I find myself doing repetitive file & replace operations in a file. Most often that comes down to fixed find and replace operations; deleting some lines, changing some strings that are always the same and so on.
In Vim that is a no-brainer,
function! Modify_Strength_Files()
execute':%s/?/-/'
execute':%s/Ä/-/'
"--------------------------------------------------------
execute':%s/Ä/-/'
execute':%s///g'
"--------------------------------------------------------
execute':g/Version\ of\ Light\ Ship/d'
execute':g/Version\ of\ Data\ for\ Specific\ Regulations/d'
"--------------------------------------------------------
" execute':g/LOADING\ CONDITION/d'
" execute':g/REGULATION:\ A\.562\ IMO\ Resolution/d'
" This is to reduce multiple blank lines into one.
execute ':%s/\s\+$//e'
execute ':%s/\n\{3,}/\r\r/e'
" ---------------------
endfunction
copied verbatim.
How could a function like this be defined in Sublime Text editor, if it can be done at all, and then called to act upon the currently opened file?
Here are resources to write Sublime Text 2 plugins:
Sublime Text 2 API Reference
Sublime Text 2 Plugin Examples
How to run Sublime Text 2 commands
Setting up Sublime Text 2 Custom Keyboard Shortcuts
Example: you can write a similar plugin and bind a hot key to it, that is, batch_edit command. Then you can open a file and execute the command via that hot key. By the way, in this script, I didn't consider the file encoding. You can get the file encoding via self.view.encoding().
# -*- coding: utf-8 -*-
import sublime, sublime_plugin
import re
class BatchEditCommand(sublime_plugin.TextCommand):
def run(self, edit):
self._edit = edit
self._replace_all(r"\?", "-")
self._replace_all(u"Ä", "-")
self._delete_line_with(r"Version of Light Ship")
self._delete_line_with(r"Version of Data for Specific Regulations")
self._replace_all(r"(\n\s*\n)+", "\n\n")
def _get_file_content(self):
return self.view.substr(sublime.Region(0, self.view.size()))
def _update_file(self, doc):
self.view.replace(self._edit, sublime.Region(0, self.view.size()), doc)
def _replace_all(self, regex, replacement):
doc = self._get_file_content()
p = re.compile(regex, re.UNICODE)
doc = re.sub(p, replacement, doc)
self._update_file(doc)
def _delete_line_with(self, regex):
doc = self._get_file_content()
lines = doc.splitlines()
result = []
for line in lines:
if re.search(regex, line, re.UNICODE):
continue
result.append(line)
line_ending = {
"Windows" : "\r\n",
"Unix" : "\n",
"CR" : "\r"
}[self.view.line_endings()]
doc = line_ending.join(result)
self._update_file(doc)