Monthly Archives: June 2022

The Method that I Used to Improve My English Initially


Actually, this post is not suitable for English native speakers or guys that are good at English. To avoid wasting any chances to improve my written English, I still put an English version of this post here. If you are interested in the Chinese version, feel free to switch with the language switcher in the menu or widget.

Best regards and thanks,

I have worked at a company where nearly no one speaks Chinese for more than one year. During the chitchat, most colleagues seemed quite amazed when they learned that I had never worked in an English-speaking environment or studied abroad. This also tells one thing that is mute English is prominent in China.

These days some of my friends in China come to ask me to share how to improve my English. My English still sucks, many guys are excellent at English without experience working and studying abroad, and I don’t dare to claim that I can teach. However, I still decided to share the method that I used to improve my English initially, and I hope this post can help buddies who would like to lead some changes in their lives find the entry for practicing English 😄.

Open your mouth

Actually, I occasionally started my English practicing. At that moment, I had just moved from Beijing to Hangzhou, so I nearly had no friends. To make some friends not among my colleagues, I decided to have a try in some English corners.

Luckily, I found an English corner called Have Fun English Club and made several exciting friends. Here I should say thank you to these friends because I couldn’t get through an extremely dark period in my life without them. In the beginning, I am a typical minor mute English speaker. I could talk really a lot very fast in Chinese, but when I switched to English, I became a low-voice stammerer. Thanks to my thick skin, I quickly became one of them. At that moment, I told myself that mistakes were acceptable, but retreat was absolutely not allowed. 🤣 To make more friends, I applied to be a volunteer at HFEC. As a volunteer, I needed to help initiate topics for activities and act as the Group Leader during the activities. Gradually practicing English became one of my favorite things. (I will draft another post introducing how we run the English club. Our way is quite unique and one of the most popular. Some other English corners learn from our way.)

After a short while, HEFC was disbanded due to some internal issues. Suddenly we were bored when out of English club activities. To continue improving our spoken English and make more friends, we, friends known at HEFC, founded Whatever English Club. We ran it the same way as HEFC and added more game elements. It was pretty good and became popular among local English corners.

To improve spoken English, don’t give yourself too much pressure, especially in the beginning. For example, don’t care too much about the accents. If you have a chance to talk to many foreigners, you will see that there are a large number of kinds of accents around the world. You will also see that the accents can never cover their excellent English skills. Also, don’t care too much about making mistakes. We always make mistakes even when speaking in our mother tongue, so why do we need to care about making mistakes when speaking in English. Mistakes lead to rectifications which lead to improvement.

Regard yourself as a primary school student

Many friends mention that they always stumble when speaking in English because their mouths cannot catch their brains. But why the month cannot catch the brain is hard to clarify.

Once, someone told me that why Chinese are bad at speaking English is mainly due to our excessively excellent Chinese.

I think this really makes sense, and let me share my understanding. When you just started learning English, I believe whenever you would like to speak in English, firstly, you would figure out how to say it in Chinese, and secondly, you would translate that into English and speak out. But Chinese is our native Tongue, and Chinese and English belong to two totally different language families. So when you were trying to translate these beautiful Chinese lines into English, you would be stuck entirely and end with ”err…”.

Therefore my way was to force myself to become a primary school student. Whenever I would like to express sth. in English, I would use the basic subject-verb-object structure to build my line without idioms, proverbs, hymns, and other literary techniques. So that it would be much easier for me to translate the lines into English, the fewer chances I am stuck, the more confident I am, and the longer I will keep practicing.

Regard yourself as a foreigner

We may always face such a situation when speaking in English with another non-English speaker. For example, during a conversation in an English corner or during a session with my Polish colleagues. The situation is they may not be able to understand a word or a phrase we mentioned. If we don’t practice enough, the conversation will end with a long awkward silence.

So after becoming a primary school student, I began to try to make myself a foreign primary school student. I started to look up words in English-English dictionaries instead of English-Chinese dictionaries. After that, I gradually became able to explain it in another way in English to others when they could not understand what I said. In my opinion, this is a beneficial English communication skill.

By the way, I have not memorized words based on a word list for a long time, and it is much easier for me to remember new words I meet when I look them up in English-English dictionaries. Meanwhile, Lexico became one of my favorite sites.

Make yourself in a “foreign country”.

Someone always says that the environment is significant to learning English, so guys in a foreign country improve their English really fast. I may say this is half right and half wrong, cause English learning can really benefit a lot from a suitable environment. But it doesn’t mean that all the ex-pats count. Some guys that work in a team full of Chinese speakers speak only in Chinese during working hours and still talk in Chinese with family after work. The only chances that need English are shopping and dining. So their English has not been significantly improved even after years.

I watched TV series with only English subtitles to immerse myself in English. We may not understand a lot initially, but English subtitles can also help us accelerate our reading velocity. Although I also like to watch movies, I watch TV series much more than movies because the lines in TV series are closer to life than in movies. And this makes the immersion more real. If the lines are too difficult, English animation may be a better choice as a kickstart because guys talk slower with simple words in most English animation. I don’t use all but most here because there are exceptions. For example, the speed of speech and vocabulary are both terrible in Rick and Morty. After a long while, I began playing with my cellphone while watching the videos. If I couldn’t catch, I would reverse a little. I know this really made me spend more time finishing watching every episode, but it was worth trying because gradually, I was able to listen to English lines as to Chinese ones. For example, I am drafting this post while watching one of the episodes of Young Sheldon. Because when we are listening to guys chatting in Chinese, we don’t need to concentrate on that. Thanks to this practice, now I can have sessions with guys in another time zone at noon when I have a lunch box. Besides this, I also listened to English podcasts, news, TV series lines, etc., when performing things that needed less concentration, such as commuting, cooking, surfing the Internet, etc. By the way, I think listening to the news is the hardest because they are all very short and mostly have no contextual relationship to the previous one and the next one.

Let me share the milestones of improving my listening and sense of English:

  • One day, I found that I didn’t need to stare at the subtitles all the time.
  • One day, I found that I could catch the pace even though I played with my cellphone during the video play.
  • One day, I found that I could pick out the errors in the subtitles.
  • One day, I found that I could be aware of the story even though I played with my cellphone during the video play.
  • One day, I found that I could get their point when someone suddenly talked to me in English.
  • One day, I found that I could understand the whole story after watching the video without subtitles.

The change above is the process from quantitative to qualitative change based on long-term practice. In a word, do keep practicing patiently.

But I also should admit that if you stay in a foreign country and fully use this environment, your English can improve significantly. At least, my improvement here is much faster than before; of course, this also benefits from fundamentals accumulated by my long-time practice.

Result Evaluation

I worked really happily in Hangzhou but still faced some issues, so I tried several overseas companies when I just became into practicing English. As I expected, all ended due to poor communication in English. Ages later, my baby was born, and I would like to make some changes to my life. I tried four companies and came across many rounds of interviews in English with Indian, Irish, American, Italian, Japanese, Singaporean, or Chinese interviewers. And all of them issued offers to me. This really encouraged me to keep practicing my English.

Rule No. 1 to make your practicing count is that do not deceive yourself. Don’t make English learning become your excuse to be a video addict. And watching them for English learning is the key.

Do not waste any chance to practice your English.

The longer I worked in the current company, the more shortcomings in English I found. For example, my poor written English. I cannot stand my poor English mail, so Grammarly has also become one of my favorite sites. This is also one of the reasons for reopening my blog and setting this up as a bilingual site. Not sure if you have noticed that every post here has two versions of Chinese and English. And you can easily switch between versions with the language switcher in the menu item and the widget. I hope I can improve my written English by writing more. To avoid wasting any chance to practice my English, I also put an English version of this post here even though this post is not suitable for English speakers 🤣.

So much for the stories about my English learning. During English learning, practicing is a complicated and inevitable process. Don’t expect can get this immediately, and giving up too fast means you are not ready to learn English yet. I would be honored if anyone could get just a little from this post. If this post can inspire anyone to practice English, I am happy to hear that.

Hammerspoon: one Swiss Army Knife on macOS

I may believe that most computers contain unique customizations, which may be why most people hate reinstalling the operating systems or setting up a new computer.

Such as my laptop, there are a bunch of tools that improve my experience using a computer. Here is a non-exhaustive list:

SizeUpCan easily attach the windows to the sides or corners of the screen. If the screen is big enough, you may put the documentation on the left and IDE on the right.
Pap.erIt can periodically and automatically set a beautiful sightseeing image as your wallpaper.
StretchlyTimely covers your screen to make you have a rest.
Lexico.comThe official site of the Oxford dictionary.
CheatsheetIt can show you the list of the selected application’s hotkeys.
New Terminal HereOpen a terminal with the current folder path.
One non-exhaustive list of my favorite tools

Besides improving my experience in using a computer, these tools also cause a few inconveniences, especially when I need to reinstall the OS and set up a new laptop. I have to look for an alternative because sometimes one is no longer free of charge, or sometimes one no longer supports the latest OS. This didn’t bother me much until I changed my Macbook Pro thrice in half a year. So I tried to find a way to minimize the number of tools I relied on, and I found Hammerspoon. I can say this is really a Swiss Army Knife on macOS.

Actually, there are some similar tools, but Hammerspoon finds the best balance between usage simplicity and functionality complexity. The users only need a little knowledge of Lua before customizing with Hammerspoon. Under the situation of no experience in Lua, I quickly finished the customizing based on the official documentation.

We can customize with the official spoons, such as windows manipulation.

-- We can quickly implement this with the WinWin spoon

-- Check whether WinWin is loaded and bind hotkeys to different directions.
if spoon.WinWin then
  -- Supporting symbol characters in the message of Hammerspoon is quite helpful. We will talk about this later. I will talk about this later.
  -- Side
  hs.hotkey.bind({"cmd", "alt", "ctrl"}, "left", "Window ⬅", function() spoon.WinWin:moveAndResize("halfleft") end) 
  hs.hotkey.bind({"cmd", "alt", "ctrl"}, "right", "Window ➡", function() spoon.WinWin:moveAndResize("halfright") end) 
  hs.hotkey.bind({"cmd", "alt", "ctrl"}, "up", "Window ⬆", function() spoon.WinWin:moveAndResize("halfup") end) 
  hs.hotkey.bind({"cmd", "alt", "ctrl"}, "down", "Window ⬇", function() spoon.WinWin:moveAndResize("halfdown") end) 
  -- Corner
  hs.hotkey.bind({"shift", "alt", "ctrl"}, "left", "Window ↖", function() spoon.WinWin:moveAndResize("cornerNW") end) 
  hs.hotkey.bind({"shift", "alt", "ctrl"}, "right", "Window ↘", function() spoon.WinWin:moveAndResize("cornerSE") end) 
  hs.hotkey.bind({"shift", "alt", "ctrl"}, "up", "Window ↗", function() spoon.WinWin:moveAndResize("cornerNE") end) 
  hs.hotkey.bind({"shift", "alt", "ctrl"}, "down", "Window ↙", function() spoon.WinWin:moveAndResize("cornerSW") end) 
  -- Stretch
  hs.hotkey.bind({"cmd", "alt", "ctrl"}, "C", "Window Center", function() spoon.WinWin:moveAndResize("center") end) 
  hs.hotkey.bind({"cmd", "alt", "ctrl"}, "M", "Window ↕↔", function() spoon.WinWin:moveAndResize("maximize") end) 
  -- Screen
  hs.hotkey.bind({"alt", "ctrl"}, "right", "Window ➡ 🖥", function() spoon.WinWin:moveToScreen("next") end) 
  -- Other
  hs.hotkey.bind({"cmd", "alt", "ctrl"}, "/", "Window Undo", function() spoon.WinWin:undo() end) 
endCode language: PHP (php)

It is pretty easy, right? Only several hotkey bindings to functionality are enough.

We can also create spoons with the API, such as BreakTime.

To implement this, we need to periodically use a page or image to cover the whole screen to make the guys in front of the PC take a rest.

Firstly, we can quickly start a timer with hs.timer:

obj.Timer =, refresh)
obj.Timer:start()Code language: PHP (php)

Then, we can create a page covering the whole screen with hs.webview. Using a transparent image to make the page translucent is also not bad.

function makeBrowserOfBreakTime ()
  local screen = require"hs.screen"
  local webview = require"hs.webview"

  local mainScreenFrame = screen:primaryScreen():frame()
  browserFrame = {
     x = mainScreenFrame.x,
     y = mainScreenFrame.y,
     h = mainScreenFrame.h,
     w = mainScreenFrame.w

  local options = {
      developerExtrasEnabled = true,

  -- local browser =, options):windowStyle(1+2+4+8)
  local browser =, options):windowStyle(1+2+128)

  return browser
endCode language: PHP (php)

Next, we can show and remove the cover with browser:show() and browser:delete() periodically with the timer.

function refresh()

  obj.curTime = obj.curTime + 1
  if obj.curTime > obj.microbreakInterval then
    obj.curMicrobreakCount = obj.curMicrobreakCount + 1
    if obj.curMicrobreakCount > obj.microbreakCount then .. " minute break starts")

      local browser = makeBrowserOfBreakTime();
      browser:url("file://" .. hs.spoons.scriptPath() .. "BreakTime.html?time=" .. (obj.breakTime * 60 - 1)):show()
      hs.timer.doAfter(obj.breakTime * 60, function()
        if browser ~= nil then 

      obj.curMicrobreakCount = 0
    else .. " second microbreak starts")

      local browser = makeBrowserOfBreakTime();
      browser:url("file://" .. hs.spoons.scriptPath() .. "BreakTime.html?time=" .. (obj.microbreakTime - 1)):show()
      hs.timer.doAfter(obj.microbreakTime, function() 
        if browser ~= nil then 

    obj.curTime = obj.curTime - obj.microbreakInterval

endCode language: JavaScript (javascript)

Load the BreakTime spoon in the same way to load the WinWin spoon, and start it. Done!

We can also customize the taskbar menu to improve the user experience.

Take BreakTime as an example. We can show the timeline of the next break.

BreakTime's Menu
BreakTime’s Menu

Besides this, we can also show all the hotkeys defined with Hammerspoon.

Menu showing all the hotkeys
Menu showing all the hotkeys

Hammerspoon supports symbol characters quite well, so users can make the menu items more attractive. Isn’t this amazing? 😄

obj.menubar:setTooltip("Hot Key Info")

local hotkeys = hs.hotkey.getHotkeys()
local menuItem = {}
for key, value in pairs(hotkeys) do  
  local item = { title = value["msg"] }
  table.insert(menuItem, item)

obj.menubar:setMenu(menuItem)Code language: JavaScript (javascript)

Besides all the above, Hammerspoon still has much that needs going through. I am also keeping going through to make my customization more additional. Here’s mine.

BTW, not only reinstalling these tools, but I also need to reinstall all of the common applications such as VS Code, Plex, Sublime Text, VIM, etc. This is also terrible. Now I am maintaining a tap list containing the applications with homebrew. 😂

ImgCache 0.2.1 Released

I promised 12 years ago that I would enable the HTTPS support in the next release. And now, I have finally released a new version of ImgCache. I also made fun of myself for this in my first blog post. Now I have made my word and implemented this in this version. Better late than never 😂

Released ImgCache 0.2.1 after 12 years
Released ImgCache 0.2.1 after 12 years

Besides enabling the HTTPS support, I upgraded the Snoopy class, updated the code format and the README file, and fixed two interesting bugs.

The first one is about the suffix extraction of the cache images. When I coded for the HTTPS support functionality, I passed the test with PNG images. But when I tried with SVG images, the cached images didn’t show on the pages because the suffix of the cached image file was not .svg but .svg+xml.

To be honest, I could hardly remember how I confirmed the suffix in this 12-year-old ancient code. So I went through the code and found the suffix was defined based on the Content-Type inside the HTTP header fields when accessing the image’s link. The HTTP header will contain a field named Content-Type like this Content-Type: image/png when we access the image’s URL. This field helps clients confirm the MIME type of the response, so we can use the former part before / to verify whether this is an image and use the later part after / to get the suffix. Because I was the one who mostly used this plugin, I only tested with several typical image types and released it when I passed all the cases

But the Content-Type of SVG is image/svg+xml not image/svg. The cached image doesn’t show on the pages because we set .svn+xml as the suffix of the cached image file.

It says on Wikipedia that SVG is an XML file containing all the vector graphic information. That makes sense.

Scalable Vector Graphics (SVG) is an XML-based vector image format for two-dimensional graphics with support for interactivity and animation. The SVG specification is an open standard developed by the World Wide Web Consortium (W3C) since 1999.

SVG images are defined in a vector graphics format and stored in XML text files. SVG images can thus be scaled in size without loss of quality, and SVG files can be searched, indexed, scripted, and compressed. The XML text files can be created and edited with text editors or vector graphics editors, and are rendered by the most-used web browsers.

Therefore, I must split the Content-Type’s value to confirm the suffix. Actually, SVG is not the only one, and I will handle the other types in the following release.

The second bug was due to the IMG tag generated by the WordPress’ new editor. The image tags generated by the WordPress’ new editor are not closed. And there is no space between the last attribute and the tag end as below.

<meta http-equiv="content-type" content="text/html; charset=utf-8"><img src="">
Code language: HTML, XML (xml)

At that moment, in my opinion, all the HTML tags should be closed, and there must be a space between the attribute and the end of the tag as below.

<meta http-equiv="content-type" content="text/html; charset=utf-8"><img src="" />
<img src="" ></img>
Code language: HTML, XML (xml)

Based on this understanding, the REGEX for URL extraction in the previous version was not robust enough to handle this. So the URL extracted was invalid, and the plugin would stop caching this image. 😅

So much for the stories about this version. Users may be able to set customized expiration times of cached images in the next version. I used this plugin to show the Feedburner subscribers’ count images. Because the count kept changing, I set the expiration time as one hour, which is 3600 seconds in the code. Now the usage changes, a customized expiration time may make sense.

Alright! Let’s see the next release.