TIL: VS Code tasks and bash scripts

I use Hugo for some static pages on the website. I wanted to convert some common actions that take a couple of steps into a single command. The one I tacked now is to create a new ‘Book’ page template in Hugo and open it in the editor. It’s a simple action, but took me a bit to figure out the basic stuff.

1. Create a VSCode task to execute the commands without opening terminal.

If the workspace doesn’t have a ‘tasks.json‘ already, create one
Press 'F1' - my shortcut key for "Show all commands" Select "Run task", and follow the prompts to create a new task. Select "Other" when selecting task type. VSCode will create a 'tasks.json'  file with a single task that prints 'Hello' on the command line.
If there’s already a ‘tasks.json‘ in the workspace folder, add a new task

Simplest way is to just copy a previous task and change details – label, type, command, args, problemMatcher, etc

2. Configure task and inputs

Label is just the name for the task.

"label": "New Book"

Type is the command type. In my case, this was just ‘shell

"type": "shell"

For command, we’ll just point to the shell script. I use VSC’s in-built variable, ‘${workspaceFolder}‘ to mark the path to the script.

"command": "${workspaceFolder}/pages/makebooks.sh"

I provided two arguments to the shell script—the workspace folder path and the name of the book to create.

"args": [
    "${workspaceFolder}",
    "${input:bookName}"
]

Finally, since I was using a user input ‘input:bookName‘, I had to create an inputs section too.

"inputs": [{
    "id": "bookName",
    "type": "promptString",
    "description": "Name of the book, please:",
    "default": "A book"
}]

Here, id is the variable name of the input which we can use to reference it in the task section. type is the type of input. It can be a promptString asking user to type a string, a pickString providing user options to choose from, or a command which runs a command and returns the output as input. description is the prompt shown to the user when input is asked, and default is the default input.

That’s the task creation done. I still have to make the actual shell script to execute, but this bit is done.

3. Create a shell script to execute when the task is run

Create a new file with the name and path chosen in ‘command‘ section above. Also make the shell script executable.

Now open the shell script in VSC, and make it do the work.

First, just switch to the subfolder where hugo related content is kept.

cd "$1"/pages

$1 is the first argument to the script, which in our case is the first item in the ‘args‘ provided in the task description—the home folder of the VSC workspace.

TIL: Escape inputs with "" to send them to other commands.
It took me a bit of googling to figure out that the easiest way to take user inputs and pass them, escaped, to other commands is to just enclose them in "". Specially, like in my case when there are spaces in book names or paths.
Another alternative that didn’t work for me was using printf: printf -v bookName "%q" $2. This will escape the $2 arg and save it in variable bookName.

Next, create the new books page:

hugo new books/"$2".md

Now, check if the command succeeded (it fails if a book with that name already exists).

if [ $? -eq 0 ]; then

If it succeeded, open the book file for editing:

code content/books/"$2".md

TIL

  • Using $? to get the exit code of the last command. 0 means successfully completed, anything higher means failure.
  • How to use the shell if-then-else
  • Using test with the [...] syntax

That’s it. We’re done. Now when I need to create a new book page, all I do is press F1, select Run task, type in the book name, and it opens a new page with the template for the book.

Continue reading

WordPress setup on my linode

Noting these down here for reference:

The basics:

Download the latest version of WordPress, and scp the zip to server

# Download the latest version of WordPress, and scp the zip to server
$ scp wordpress-5.2.2.zip [email protected]:/home/chewie/c306/holderfolder

# ssh to the remote server, and unzip the zip file
$ ssh [email protected]
$ cd c306/holderfolder
$ unzip wordpress-5.2.2.zip
$ cd wordpress
$ cp wp-config-sample.php wp-config.php

That’s phase one done.

Then create a mysql database for this WordPress installation:

> create database holderfolder;
> create user 'holderfolderuser';
> grant all privileges on holderfolder.* to 'holderfolderuser' identified by '...'
> flush privileges;

Now update the database variables in holderfolder/wp-config.php.

Next, copy the template .htaccess file (or just take one from spkeasy or converge, and replace the blogname) to holderfolder. This will take care of the redirects required for the JSON API.

Next, change owner for the folder so Apache can access it. Also give myself, via group, some rights.

$ chown www-data:chewie *
$ chmod g+rw *

Finally, open the url to the holderfolder in the browser, and follow the setup instructions there.

Continue reading

Javascript class methods

My understanding of javascript object methods (pre-ES6) from Douglas Crockford’s post.

Public

Can’t access private members of the object

Anything created with this.xyz inside the constructor, or

Any methods added by MyObject.prototype.myMethod outside the constructor.

Private

Not accessible from outside the object definition (e.g. as myObj.myMethod())

Any variables or functions created inside the constructor with var or function abc(){...}.

Privileged

(I.e. publicly accessible, but can access private members)1

Methods declared with this.myMethod = function()... inside the constructor.

Continue reading

Installing RCurl on linux

Will keep failing without providing a valid reason.

The reason is lack of a system library – libcurl4-openssl-dev.

Install the library from default sources:

sudo apt-get install libcurl4-openssl-dev

Now, install package RCurl inside R again, and we’re ready to go

Note to self: Use curlies!

This small block of code – it looks clean, and easy to understand

signout: function(callback){
  dropbox.client.signOut(function(error){

    if(error)
      if(callback) callback(false, showError(error));
    
    else
      resetLocalStorage(true, function(){
        if(callback) callback(true);
      });

  });
}

Sadly, it’s also buggy.

When I started programming in javascript, I’d come from a C & Java background, so I encapsulated everything in curlies.

Then sometime later, I started dabbling in Python for work related data processing. I loved how indentation was used to identify code blocks in Python. Didn’t need curlies cluttering everything.

Soon after I discovered that single statements following a loop command (for…) or a conditional (if… else…) didn’t need to be encapsulated inside curlies either. If there was just one statement, you could write it straight after – in same line, or a following one, with any amount of indentation.

Recently, I’ve become addicted to this style of coding. I don’t like unnecessary curlies cluttering the code, and I get rid of them quite aggressively.

Too aggressively as this example shows.

Looking at the code, it appears that the else statement triggers when there isn’t an error. However, in reality, the js parser attaches that else to the if(callback) inside the error conditional.

The correct way to write this is:

signout: function(callback){
  dropbox.client.signOut(function(error){
    
    if(error){
      if(callback) callback(false, showError(error));
    }
    
    else
      resetLocalStorage(true, function(){
        if(callback) callback(true);
      });
    
  });
}

Offline Testing In Chrome

Offline - No Wifi
Offline testing in Chrome – No more WiFi toggling

Despite ever expanding web of internet connectivity, no modern web app can expect not to work decently when offline.

Testing offline functionality, though, can be a bit of a bummer for people like me who develop almost exclusively in/for Google Chrome – unlike the old Internet Explorer, it doesn’t have a quick to access ‘Offline Mode’.

Not being a professional developer, I didn’t have extensive tools at my service to test my app in offline mode, and switching WiFi off-on was becoming tiresome. This is the solution I’ve ended up with, and if you’re looking for offline testing in Chrome, here’s an easy way:

1. Install the Proxy SwitchySharp extension from Chrome Web Store.

2. In extension’s settings, set up a proxy to a non-existent IP Address, preferably on your local network. You could even set it to localhost/127.0.0.1 if you aren’t running a server on local machine.

Proxy Switchy Sharp Settings
Proxy SwitchySharp Extension Settings

3. Now every time you need to switch to offline mode, all you have to do is go to the extension’s browser button, and select the local-profile you created.

 

Browser Button - Select Proxy
Browser Button – Select proxy to go offline.

4. When you want to go back on-line, just select ‘Direct Connection’ or, if you have a corporate proxy, then that.

That’s it! No more toggling WiFi to test offline mode for your web apps.

Joy

Just got the 1st cut of ConvertIt extension working in the browser. Nothing spectacular, doesn’t even filter anything yet, still it’s a source of joy bounding on exhilaration. Joy of seeing it in action :)

Now on with the hard work of actually getting it to do something useful.

Posted from WordPress for Android