Author Archives: mahdi

کیبورد فارسی برای اوبونتو

خیلی وقت پیش‌تر، در مورد کیبورد فارسی برای ویندوز نوشته بودم. به نظر خودم که کیبورد خوبی بود!

مساله ی جدید، استفاده از Ubuntu برای کارهای جدیدم بود و کیبورد فارسی استانداردش که واقعاً معلوم نیست چرا این شکلیه! خوشبختانه البته، تغییر کلید های کیبورد توی لینوکس خیلی راحت تر از ویندوزه. در حد ویرایش یه فایل متنیِ خیلی سر-راست.

برای انجام این تغییرات، باید توانایی sudo داشته باشید و یک ویرایشگر متن خوب مثل Visual Studio Code یا NANO روی دستگاهتون نصب باشه.

فایلهای mapping کلیدهای کیبورد به کاراکترها رو میتونید توی این مسیر پیدا کنید:

/usr/share/X11/xkb/symbols

برای اینکه کلیدهای زبان فارسی رو تغییر بدهید، باید فایل ir رو ویرایش کنید؛ اما بهتون پیشنهاد میکنم اول یک نسخه ی بک آپ ازش نگه دارید.

su -
cd /usr/share/X11/xkb/symbols
cp ir{,BACKUP}
nano ir

اگر از Visual Studio Code استفاده میکنید، برای اینکه این فایل رو بهتر ببینید،‌تنظیمات indentation رو بگذارید روی tabs: 8 و اگر نه فایل رو یه مقدار به هم ریخته خواهید دید.

توی این فایل قسمتهای مختلفی هست که کلیدها رو به کاراکتر اصلی، کاراکتری که با Shift تایپ خواهند کرد و کاراکتری که با Alt-Gr تایپ میکنن، مرتبط میکنه؛ به این صورت:

key <AD04> { [ Arabic_qaf,		Arabic_fathatan,	VoidSymbol	] };

اون کد ۴ حرف و رقمی که جلوی key نوشته، یعنی AD04 در واقع یک کد ۳ قسمتی خیلی ساده است.

A یعنی این کلید در قسمت حرف و عددی کیبورد واقع شده؛ در مقابل K که یعنی در قسمت Numeric Keypad که فقط عدد داره (سمت راست کیبورد).

D یعنی این کلید در سطر چهارم (اگر از پایین بشماریم و با A شروع کنیم) واقع شده. اون سطری که کلید فاصله داخلش هست رو فرض کنید A باشه، اونی که “ظ” توشه میشه B، اونی که “ش” توشه میشه C و اونی که “ض” توشه میشه D.

04 هم یعنی شماره‌ی کلیدِ حرف یا عددی از سمت چپ توی اون سطر.

کلیدی که توی مثال بالا نوشتم رو اگر نگاه کنید می‌بینید که توی قسمت حرف و عددی (A)، سطر چهارم (D) کلید حرف و عددی چهارم (04) میشه حرف “ق”.

الان توی حالت عادی، این کلید حرف “ق” رو تایپ می‌کنه، با Shift براتون “ــًـ” رو تایپ می‌کنه و با Alt-Gr هم چیزی تایپ نمیکنه.

به جز این حالت “کُد بندی” که توضیح دادم، یه سری کد های خاص هم وجود داره. مثل TLDE برای کلیدی که کاراکتر Tilde یعنی ~ رو تایپ میکنه؛ یا مثلا BKSL برای Backslash یعنی \

حالا همه ی اینها رو گفتم که متوجه بشید توی اون فایله چه خبره و اگر خواستید خودتون تغییرش بدید، اما براتون فایل تغییر داده شده‌ی خودم رو هم میگذارم که بتونید راحت کپی کنیدش توی اون مسیری که اول نوشتم.

Building OpenCV on Ubuntu – with pyenv

Installing the OpenCV on Ubuntu can be really straight forward. Especially if you don’t want the latest version of python. However, if you’re into the “moving on tech-edge” and if you value the efforts behind software updates, you have probably installed the latest python using a version manager like pyenv.

The bad news is, if you have done so, the easy apt-get-ish way will not work for you; but the bright side is you can build it from source like a piece of cake.

On my journey towards the following solution, I found this gist by pohmelie and then this much better solution by him again. The only problem was, they’re cloning the old branch and cloning opencv’s main git repo will not yield the stable version.

I changed his solution a bit so that it will download that release source instead of cloning a repository and here’s the result:

Supposing, you have already installed pyenv and its prerequisites and also have enabled the latest python version (which is 3.7.4 as of now), first of all, install build dependencies for OpenCV and some PyPI packages (sh) required to run the installer script and use Opencv

sudo apt-get update
sudo apt-get build-dep opencv
sudo apt-get upgrade
pip install sh numpy scipy

Then edit OPEN_CV_VERSION to the latest available release and run this python file:

import pathlib
import sys
import sh

OPEN_CV_VERSION="4.1.0"


def download_sources_if_not_exist(version=OPEN_CV_VERSION):
    if not pathlib.Path("opencv.{}.src.tar.gz".format(version)).exists():
        print("Downloading opencv release v{0} from https://github.com/opencv/opencv/archive/{0}.tar.gz".format(version))
        sh.curl("https://github.com/opencv/opencv/archive/{}.tar.gz".format(version), "-L", "--output", "opencv.{}.src.tar.gz".format(version))
    if not pathlib.Path("opencv_contrib.{}.src.tar.gz".format(version)).exists():
        print("Downloading opencv_contrib release v{0} from https://github.com/opencv/opencv_contrib/archive/{0}.tar.gz".format(version))
        sh.curl("https://github.com/opencv/opencv_contrib/archive/{}.tar.gz".format(version), "-L", "--output", "opencv_contrib.{}.src.tar.gz".format(version))
    pass

def extract_sources_clean(version=OPEN_CV_VERSION):
    print("Refreshing opencv...")
    sh.rm("-rf", "opencv")
    sh.mkdir("opencv")
    sh.tar("xzf", "opencv.{}.src.tar.gz".format(version), "-C" ,"opencv", "--strip-components=1")
    print("Refreshing opencv_contrib...")
    sh.rm("-rf", "opencv_contrib")
    sh.mkdir("opencv_contrib")
    sh.tar("xzf", "opencv_contrib.{}.src.tar.gz".format(version), "-C" ,"opencv_contrib", "--strip-components=1")
    pass

def build_opencv():
    sh.pip.install("numpy")
    download_sources_if_not_exist()
    extract_sources_clean()
    sh.rm("-rf", "opencv-build")
    sh.mkdir("opencv-build")
    sh.cd("opencv-build")
    python_path = pathlib.Path(sh.pyenv.which("python").stdout.decode()).parent.parent
    version = "{}.{}".format(sys.version_info.major, sys.version_info.minor)
    sh.cmake(
        "../opencv",
        "-DCMAKE_BUILD_TYPE=RELEASE",
        "-DCMAKE_INSTALL_PREFIX={}/usr/local".format(python_path),
        "-DWITH_CUDA=OFF",
        "-DWITH_FFMPEG=OFF",
        "-DINSTALL_C_EXAMPLES=OFF",
        "-DBUILD_opencv_legacy=OFF",
        "-DBUILD_NEW_PYTHON_SUPPORT=ON",
        "-DBUILD_opencv_python3=ON",
        "-DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules",
        "-DBUILD_EXAMPLES=ON",
        "-DPYTHON_EXECUTABLE={}/bin/python".format(python_path),
        "-DPYTHON3_LIBRARY={}/lib/libpython{}m.so".format(python_path, version),
        "-DPYTHON3_PACKAGES_PATH={}/lib/python{}/site-packages/".format(python_path, version),
        "-DPYTHON3_NUMPY_INCLUDE_DIRS={}/lib/python{}/site-packages/numpy/core/include".format(python_path, version),
        "-DPYTHON_INCLUDE_DIR={}/include/python{}m".format(python_path, version),
        _out=sys.stdout,
    )
    sh.make("-j4", _out=sys.stdout)
    sh.make.install(_out=sys.stdout)


if __name__ == "__main__":
    build_opencv()

Git change remote repo

Sometimes you start a git repo and some time later, you have to change your remote repo. This can be done really easy with a small catch:

Your new repo should be completely clean.

git remote -v
git remote set-url origin https://github.com/<NEW_USER>/<NEW_REPO_NAME>.git
git merge --allow-unrelated-histories FETCH_HEAD

This will work now:

git push

… and will transfer your old repo’s history to the new repo.

Python Logging Config Sample with Multiple Sinks

Multiple sinks for default logger’s levels

[loggers]
keys=root

[handlers]
keys=consoleHandler, fileHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler, fileHandler

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

[handler_fileHandler]
class=FileHandler
level=INFO
formatter=simpleFormatter
args=("%(log_path)s/%(log_filename)s", "a", "utf-8", False)

[formatter_simpleFormatter]
format=[%(levelname)-8s] - %(asctime)s (%(threadName)-10s) %(message)s

Test like this:

import logging
import logging.config
from logging import debug, log
from os import path


def main():
    debug("Hello %s", 1)


if __name__ == "__main__":
    logging.config.fileConfig(
        r"C:\Workspace\Python\VS Code\Logging\default.conf",
        {
            'log_path': path.dirname(path.realpath(__file__)),
            'log_filename': "%s.log" % path.basename(__file__)[:-3]
        }
    )

    log(logging.INFO, "Started")
    main()
    log(logging.INFO, "Finished")

Finding ancestors in a SQL-Server’s HierarchyId tree

Imagine this table, filled with more than a million records containing a 7-levels tree:

CREATE TABLE HierTest (
	Id		BIGINT PRIMARY KEY IDENTITY(1,1),
	Path	HIERARCHYID NOT NULL UNIQUE,
	Name	NVARCHAR(100) NOT NULL
)

Now imagine there’s a node with Id=1839861 and you want to get all of its ancestors. I know of two ways to do this (sources: Simon Ince’s blog post and StackOverflow):

DECLARE @Hiernode HIERARCHYID;
SELECT @Hiernode=[ht].[Path] FROM [TestSchema].[HierTest] AS [ht] WHERE [ht].[Id]=1839861;
SELECT
	*--,
	--[ht].[Path].ToString() AS PathString
FROM [TestSchema].[HierTest] AS [ht]
WHERE @Hiernode.[IsDescendantOf]([ht].[Path])=1
ORDER BY [ht].[Path];

and

WITH Tree(Id, Name, Path, AncestorPath) AS(
	SELECT
		[ht].[Id],
		[ht].[Name],
		[ht].[Path],
		[ht].[Path].GetAncestor(1) AS 'AncestorPath'
	FROM [TestSchema].[HierTest] AS [ht]
	WHERE [ht].[Id]=1839861

	UNION ALL

	SELECT
		[ht].[Id],
		[ht].[Name],
		[ht].[Path],
		[ht].[Path].GetAncestor(1) AS 'AncestorPath'
	FROM [TestSchema].[HierTest] AS [ht]
	INNER JOIN [Tree] t ON [ht].[Path] = [t].[AncestorPath]
)
SELECT
	[t].[Id],
	[t].[Name],
	[t].[Path]
FROM [Tree] t
ORDER BY [t].[Path]

Measuring the execution time shows the “Take II” to be more than 100 times faster than “Take I”!!

I’ll update this post with what I’ll learn in the future.


Download the scripts from: Hierarchy Test.

Windows TCP 49154 – What is it!!?

Just had a tough struggle with my “MUTE” friend – Windows Server – trying to understand what’s running behind tcp/49154 on my server, accepting connection.

There are many ALLOW ALL PROFILES WITH ANY PORTS listed on windows’ firewall by default and thinking of them as being secure is not right.

File Server Remote Management (WMI-In) was listening on that port! Disabled the rule and now I’m in peace again! 😀

 

Use Powershell 5 to start automatic services not running

There are times when windows doesn’t start some automatic services. In situations like this, the best way would be a clean fresh windows installation; but what if you can’t re-install the OS?

This script will be very handy when you can’t re-install the Windows. It runs those nasty services 🙂

clear
$svcs=Get-Service | Where-Object {$_.Status -eq 'stopped' -and $_.StartType -like "*Automatic*"}
foreach ($svc in $svcs){
    Write-Host Starting $svc.Name
    Start-Service $svc
}

Linux – Find last 10 modified folders.

This post will be updated, but for the mean time this should work:

find . -maxdepth 2 -type d -exec stat -c "%y %n" {} \; | sort | tail -n 20

Update 1:

This is much faster:

find . -maxdepth 2 -type d -printf "%TY-%Tm-%Td %TH:%TM:%TS %TZ %p\n" | sort | tail -n 20

🙂

%Path% variable analyzer

Use this in Powershell:

 $env:Path.Split(";".ToCharArray()) | Select-Object @{Name="Path";Expression={$_}},@{Name="Exists";Expression={[System.IO.Directory]::Exists($_)}}

کیبورد فارسی برای همه ویندوز ها

قبلاً در مورد کیبورد فارسی یک پست نوشته بودم. اون کیبورد فارسی یک ایراد کوچک داشت که توی این نسخه جدید برطرف شده. ایراد این بود که اگر کیبورد در حالت فارسی باشد و Caps Lock هم روشن باشد، نمیتوان با استفاده از Shift، کاراکترهایی مانند % ( )  و اینها را تایپ کرد؛ که خوب حالا می شود!!

تغییر دیگری که ایجاد شده، استفاده از Zero-Width Space به جای Zero-Width Non-Joiner در Shift+Space است که کاربردش دقیقاً طراحی شده برای عبارتهایی مثل این: “در سده‌ی گذشته” کاراکتری که بدون اینکه فاصله ایجاد کند، باعث شود حروف به هم نچسبند.

حالا این کیبورد جدید رو از اینجا دانلود کنید: Farsi Keyboard Layout Patch