Puppy Linux Discussion Forum Forum Index Puppy Linux Discussion Forum
Puppy HOME page : puppylinux.com
"THE" alternative forum : puppylinux.info
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

The time now is Sun 21 Jul 2019, 00:41
All times are UTC - 4
 Forum index » Advanced Topics » Additional Software (PETs, n' stuff) » Unsorted
mdshell - an interactive shell for writing Markdown document
Moderators: deshlab, Flash, GuestToo, Ian, JohnMurga, Lobster
Post new topic   Reply to topic View previous topic :: View next topic
Page 1 of 1 [2 Posts]  
Author Message
sc0ttman


Joined: 16 Sep 2009
Posts: 2691
Location: UK

PostPosted: Mon 04 Feb 2019, 17:43    Post subject:  mdshell - an interactive shell for writing Markdown document
Subject description: supports embedding bash commands in your markdown!
 

mdshell

An interactive shell for generating Markdown documents, with
support for embedding executable commands in your markdown!

Usage: mdshell <path/to/file.md>

Write the file line by line.
Hit ENTER 3 times to exit and save the file.

Demo:


More info:

I wanted a way to create Markdown documents in the terminal, and to
embed shell commands in the Markdown, so I could generate the final
file dynamically - the results of the embedded shell commands are
saved in the final file.


The script:

Code:
#!/bin/bash

# sc0ttman
# Based on an example script by Stéphane Chazelas.

if [ ! "$1" ] || [ "$1" = "-h" ] || [ "$1" = "-help" ] || [ "$1" = "--help" ];then
cat << HELP_MSG

 An interactive shell for writing Markdown documents, with
 support for embedding bash sub-shells \$() in your Markdown!

 Usage:  mdshell <path-to-file> # creates the file if it doesn't exist

 Note backtick subshells (\`\`) not supported, only \$()

 Example:   Add \$(uname) in your Markdown and the saved
            file will contain your system info.

HELP_MSG
exit
fi

# define default settings

# define run-time vars used by this program
prev_line=none
line_is_bash=false
line_was_bash=false
multi_line_string=false
was_multi_line_string=false
command=''
command_line_count=0

if [ ! -f "$1" ];then
  mkdir -p "$(dirname "$1")"
  touch "$1"
fi

while :
do
  # the user just hit ENTER, so read the line they input
  #  -e  use readline
  #  -r  dont escape backslashes include them as literals chars
  read -er line

  # if line starts with ``` we know it's a markdown line, not part of a bash sub-shell
  [ "$(echo "$line" | grep '^```')" != "" ] && line_is_bash=false

  # if the line contains $( then the user is starting a bash sub-shell on this line
  [ "$(echo "$line" | grep -m1 '$(')" != "" ] && line_is_bash=true

  # if the line is not bash, then it's also not a multi line string
  #if [ "$line_is_bash" = false ];then
  #  multi_line_string=false
  #fi

  # if the previous last (one before last entered) was part of a multi-line string,
  # then this line probably is too, and so it's part of a bash command
  [ "$was_multi_line_string" = true ] && line_was_bash=true

  # the the line given was bash, not markdown, we need to interpret it
  if [ "$line_is_bash" = true ];then

    # count the bumber of double quotes, and chck if that number is even
    quote_count=$(echo "$line" | tr -cd '"' | wc -c)
    quote_count_is_even=$(( ${quote_count} %2 ))

    # if $line has quotes, and an odd number of them, we moved in/out of a string
    if [ $quote_count -gt 0 ] && [ $quote_count_is_even -ne 0 ];then
      # toggle whether in a string or not
      if [ "$multi_line_string" = true ];then
        multi_line_string=false    # toggle it
      else
        multi_line_string=true     # toggle it
      fi
    fi

    # while we are in a bash sub-shell, lets save each line in the $command var
    if [ "$command" = "" ];then
      command="$line"
    else
      command="$command\n$line"
    fi
    command_line_count=$(($command_line_count + 1))

    # check if the command has a closing parenthesis ) - cos then we might be ending the sub-shell
    subshell_has_ended="$(echo "$command" | grep -Eq ')' && echo true || echo false)"

    # if line is part of a multi string, it's been saved into $command, so skip
    if [ "$multi_line_string" = true ];then

      line_is_bash=true

    # else if we detected the end of a sub-shell, lets evaluate it, get its output
    # and then save that to our markdown file, instead of the bash commands themselves
    elif [ "$subshell_has_ended"  = true ];then

      # strip any leading chars up to the sub-shell invocation '$(' and
      # strip any chars after the sub-shell, and
      # keep only the command
      pre_text="$(echo "$command" | sed -e 's/$(.*//' -e 's/)$//')"
      post_text="$(echo "$command" | sed 's/.*$(.*)//g')"
      if [ "$pre_text"  != "" ] || [ "$post_text"  != "" ];then
        command="$(echo "$command" | sed -e "s/^$pre_text//g" -e "s/$post_text//")"
        [ "$post_text" = "$command" ] && post_text=""
      fi

      # if previous line was not part of a string, then it each was a separate command
      if [ "${was_multi_line_string}" = false ];then
        # each line is a separate command, so replace newlines with semi-colons
        result="$(eval $(echo -e "${command//\\/\\\\}" | sed s'/\\n/;/g' | tr -d '`' | sed -e 's/$(//g' -e 's/)$//g') 2>/dev/null)"
        retval=$?
      else
        result="$(eval $(echo -e "${command//\\/\\\\}" | tr -d '`' | sed -e 's/$(//g' -e 's/)$//g') 2>/dev/null)"
        retval=$?
      fi
      [ "$was_multi_line_string" = false ] && line_is_bash=false
      [ "$multi_line_string" = false ] && line_is_bash=false
      [ $retval -eq 0 ] && text="$text\n$pre_text$result$post_text" && line_is_bash=false
    fi

  elif [ "$line_is_bash" = false ];then

      command_line_count=0
      command=""
      text="$text\n$line"
      multi_line_string=false
      [ -z "${prev_line}" ] && [ -z "$line" ] && break

  fi

  ###### done working out what was in $line #######

#  xmessage "
#  was multi-line string: $was_multi_line_string
#  multi-line string:     $multi_line_string
#  line_was_bash:         $line_was_bash
#  line_is_bash:          $line_is_bash
#  command line count:    '${command_line_count}'
#  command:               '${command//\\/\\\\}'
#  result:                '${result}'
#  "

  was_multi_line_string=${multi_line_string}
  line_was_bash=${line_is_bash}
  prev_line="$line"
  [ ${retval:-1} -eq 0 ] && result=''
done

echo -e "$text" > "$1"

echo
echo '------------------------------'
echo
echo "File $1 created:"
echo
less -X "$1"

unset prev_line
unset line_is_bash
unset multi_line_string
unset quote_count_is_even
unset file
unset text
unset command
unset command_line_count
unset result
unset retval

exit 0

_________________
Pkg, mdsh, Woofy, Akita Linux, VLC-GTK

Last edited by sc0ttman on Mon 04 Feb 2019, 18:52; edited 4 times in total
Back to top
View user's profile Send private message 
sc0ttman


Joined: 16 Sep 2009
Posts: 2691
Location: UK

PostPosted: Mon 04 Feb 2019, 17:53    Post subject:  

Eventually this might form part of a larger CLI based program for writing a blog, or
possibly a puppy linux wiki/documentation builder.

However, first I would very much like to clean up the code in 'mdshell'.

It works, though breakable, but I think it works 'by accident or luck' .... I'm not
sure the code works as intended, and might be way more complex and convoluted
than needed ... although I get the results I want (somehow).

Although the approach I took will always be 'dumb', so don't expect too much.

------

And just FYI, here is a great script for converting markdown to HTML:

https://daringfireball.net/projects/markdown/

_________________
Pkg, mdsh, Woofy, Akita Linux, VLC-GTK
Back to top
View user's profile Send private message 
Display posts from previous:   Sort by:   
Page 1 of 1 [2 Posts]  
Post new topic   Reply to topic View previous topic :: View next topic
 Forum index » Advanced Topics » Additional Software (PETs, n' stuff) » Unsorted
Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group
[ Time: 0.0387s ][ Queries: 11 (0.0063s) ][ GZIP on ]